Commit 269f3061 269f306190c59535d84cf7323f8998147bbee875 by Christian Gerdes

Nytt webtest plugin ClientCertificatePlugin som sätter ett angivet client cert p…

…å alla request och automatiskt importerar det till certstore på maskinen om det inte finns.
1 parent 0f8854a0
using System.Reflection;
using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
......@@ -9,8 +10,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Plugins for Web and Load Tests")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("LIGHTS IN LINE AB")]
[assembly: AssemblyProduct("Visual Studio 2010 Ultimate")]
[assembly: AssemblyCopyright("© LIGHTS IN LINE AB 2014")]
[assembly: AssemblyProduct("Visual Studio 2015 Enterprise")]
[assembly: AssemblyCopyright("© LIGHTS IN LINE AB 2016")]
[assembly: AssemblyTrademark("All Rights Reserved")]
[assembly: AssemblyCulture("")]
......@@ -34,3 +35,5 @@ using System.Runtime.InteropServices;
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.3.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: NeutralResourcesLanguage("sv-SE")]
......
......@@ -8,6 +8,7 @@ using Microsoft.VisualStudio.TestTools.LoadTesting;
using System.IO;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Security.Cryptography.X509Certificates;
namespace LIL_VSTT_Plugins
{
......@@ -540,6 +541,178 @@ namespace LIL_VSTT_Plugins
}
}
/// <summary>
/// WebTest Client Certificate
/// </summary>
[DisplayName("Client Certificate")]
[Description("(C) Copyright 2016 LIGHTS IN LINE AB\r\nSätter webtestet att använda ett specifikt client cert för SSL. Certifikatet behöver inte installeras i certstore först.")]
public class ClientCertificatePlugin : WebTestPlugin
{
[DisplayName("Certificate Path")]
[Description("Sökvägen till certifikatfilen (P12/PFX med privat nyckel)")]
[DefaultValue("")]
public string pCertificatePath { get; set; }
[DisplayName("Certificate Path Parameter")]
[Description("Ange namn på parameter som ska användas för sökvägen till certifikatfilen (P12/PFX). Om parametern saknas eller är tom används Certificate Path")]
[DefaultValue("")]
public string pCertificatePathParameter { get; set; }
[DisplayName("Certificate Password")]
[Description("Ange lösenordet för att öppna certifikatfilen")]
[DefaultValue("")]
public string pCertificatePassword { get; set; }
[DisplayName("Certificate Password Parameter")]
[Description("Ange namn på parameter som ska användas för lösenordet till certifikatfilen. Om parametern saknas eller är tom används Certificate Password")]
[DefaultValue("")]
public string pCertificatePasswordParameter { get; set; }
[DisplayName("Log Certificate Data")]
[Description("Sätt till True om certifikatinfo ska loggas i början av varje test")]
[DefaultValue(false)]
public bool pDebug { get; set; }
[DisplayName("Install trusted certificates")]
[Description("Sätt till True om certifikat ska installeras automatiskt om det är giltigt")]
[DefaultValue(false)]
public bool pInstallTrusted { get; set; }
[DisplayName("Install untrusted certificates")]
[Description("Sätt till True om ogiltiga som giltiga certifikat ska installeras automatiskt")]
[DefaultValue(false)]
public bool pInstallUntrusted { get; set; }
private bool haveCert = false;
private X509Certificate myClientCert;
public override void PreWebTest(object sender, PreWebTestEventArgs e)
{
base.PreWebTest(sender, e);
String certPath, certPass;
// Ladda in certifikatet och sätt CertPolicy
if (!String.IsNullOrWhiteSpace(pCertificatePathParameter) && e.WebTest.Context.ContainsKey(pCertificatePathParameter) && !String.IsNullOrWhiteSpace(e.WebTest.Context[pCertificatePathParameter].ToString()) )
{
certPath = e.WebTest.Context[pCertificatePathParameter].ToString();
} else
{
certPath = pCertificatePath;
}
if (!String.IsNullOrWhiteSpace(pCertificatePasswordParameter) && e.WebTest.Context.ContainsKey(pCertificatePasswordParameter) && !String.IsNullOrWhiteSpace(e.WebTest.Context[pCertificatePasswordParameter].ToString()))
{
certPass = e.WebTest.Context[pCertificatePasswordParameter].ToString();
}
else
{
certPass = pCertificatePassword;
}
if(string.IsNullOrWhiteSpace(certPass))
{
// Cant continue, cert is missing
if (pDebug) e.WebTest.AddCommentToResult("No certificate loaded, since both Certificate Path and Certificate Path Parameter are empty");
return;
}
try {
myClientCert = new X509Certificate(certPath, certPass);
} catch (Exception ex)
{
if (pDebug) e.WebTest.AddCommentToResult("Exception during loading of certificate: " + certPath + " Exception: " + ex.Message);
return;
}
if(myClientCert == null) {
if (pDebug) e.WebTest.AddCommentToResult("Certificate File " + certPath + " could not be loaded.");
return;
} else
{
if (pDebug) e.WebTest.AddCommentToResult("Certificate File " + certPath);
}
if (!string.IsNullOrWhiteSpace(myClientCert.GetCertHashString()))
{
if (pDebug) e.WebTest.AddCommentToResult("Loaded client certificate for Subject: [" + myClientCert.Subject + "] Issued by: [" + myClientCert.Issuer + "] Expires: [" + myClientCert.GetExpirationDateString() + "]");
// Check if the certificate is trusted (i.e. chain can be validated)
bool myCertTrusted = false;
X509Certificate2 cer = new X509Certificate2(certPath, certPass, X509KeyStorageFlags.PersistKeySet);
cer.FriendlyName = "VSTT";
if (cer.Verify())
{
if (pDebug) e.WebTest.AddCommentToResult("Certificate is TRUSTED");
myCertTrusted = true;
} else
{
if (pDebug) e.WebTest.AddCommentToResult("Waring: Certificate is NOT TRUSTED by client. Might not be trusted on server either. Check that the Issuer/CA root and intermediary certificates are installed on the client and server.");
myCertTrusted = false;
}
// Check if we have a private key
if (!cer.HasPrivateKey)
{
// Cant use it without private key
if (pDebug) e.WebTest.AddCommentToResult("Certificate HAS NO PRIVATE KEY, cannot use it without one.");
return;
} else
{
if (pDebug) e.WebTest.AddCommentToResult("Certificate HAS PRIVATE KEY");
}
// Check that the certificate exists in the cert store
X509Store cuStore = new X509Store();
cuStore.Open(OpenFlags.ReadWrite);
if(cuStore.Certificates.Contains(cer)) {
if (pDebug) e.WebTest.AddCommentToResult("Certificate is INSTALLED");
} else
{
if (pDebug) e.WebTest.AddCommentToResult("Certificate is NOT INSTALLED");
if(pInstallTrusted && myCertTrusted || pInstallUntrusted)
{
// Try to install certificate
if (myCertTrusted || !myCertTrusted)
{
// Install in user store
try {
cuStore.Add(cer);
if (pDebug) e.WebTest.AddCommentToResult("Certificate HAS BEEN INSTALLED in the Windows Certificate Store");
} catch (Exception ex)
{
if (pDebug) e.WebTest.AddCommentToResult("Error: COULD NOT INSTALL in the Windows Certificate Store, Exception: " + ex.Message);
return;
}
}
}
}
// Set the PreRequest method to add the certificate on requests
haveCert = true;
if (pDebug) e.WebTest.AddCommentToResult("Certificate will be ADDED TO REQUESTS");
} else
{
if (pDebug) e.WebTest.AddCommentToResult("Certificate File " + certPath + " contains no SHA1 hash. Not using it.");
return;
}
}
public override void PreRequest(object sender, PreRequestEventArgs e)
{
base.PreRequest(sender, e);
if (haveCert)
{
if (!e.Request.ClientCertificates.Contains(myClientCert))
{
e.Request.ClientCertificates.Add(myClientCert);
}
e.WebTest.Context["Client Certificate"] = myClientCert.Subject;
} else
{
e.WebTest.Context["Client Certificate"] = "No certificate was added";
}
}
}
/*
/// <summary>
......@@ -549,6 +722,16 @@ namespace LIL_VSTT_Plugins
[Description("(C) Copyright 2011 LIGHTS IN LINE AB\r\nFörklaring")]
public class myPlugin : WebTestPlugin
{
private string paramName;
[DisplayName("Parameter namn")]
[Description("Ange namnet på parametern i ditt webtest, tex TimeStampParameter1")]
[DefaultValue("TimeStampParameter1")]
public string ParamNameVal
{
get { return paramName; }
set { paramName = value; }
}
public override void PreWebTest(object sender, PreWebTestEventArgs e)
{
base.PreWebTest(sender, e);
......
......@@ -46,6 +46,10 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="LIL_VSTT_Plugins, Version=1.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\LIL_VSTT_Plugins\bin\Debug\LIL_VSTT_Plugins.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Microsoft.VisualStudio.QualityTools.LoadTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>False</Private>
</Reference>
......@@ -87,6 +91,10 @@
<None Include="WebTest21.webtest">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="WebTest4.webtest">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<SubType>Designer</SubType>
</None>
<None Include="WebTest3.webtest">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
......@@ -97,12 +105,6 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LIL_VSTT_Plugins\LIL_VSTT_Plugins.csproj">
<Project>{06A22593-601E-4386-917A-9835DE30E14E}</Project>
<Name>LIL_VSTT_Plugins</Name>
</ProjectReference>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
......
<?xml version="1.0" encoding="utf-8"?>
<WebTest Name="WebTest3" Id="5f8fe34b-e853-4a88-95cb-a8e963383b09" Owner="" Priority="2147483647" Enabled="True" CssProjectStructure="" CssIteration="" Timeout="0" WorkItemIds="" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" Description="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="default" StopOnError="False" RecordedResultFile="" ResultsLocale="">
<WebTest Name="WebTest3" Id="f36a8078-a24b-41a0-ac62-678ed0b4ac50" Owner="" Priority="2147483647" Enabled="True" CssProjectStructure="" CssIteration="" Timeout="0" WorkItemIds="" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" Description="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="default" StopOnError="False" RecordedResultFile="" ResultsLocale="">
<Items>
<Request Method="GET" Guid="359feba0-105f-4dbf-a630-32d640c10817" Version="1.1" Url="https://new.vinnarum.com/" ThinkTime="0" Timeout="300" ParseDependentRequests="False" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="0" ExpectedResponseUrl="" ReportingName="" IgnoreHttpStatusCode="False" />
<Request Method="GET" Guid="359feba0-105f-4dbf-a630-32d640c10817" Version="1.1" Url="https://new.vinnarum.com/" ThinkTime="0" Timeout="300" ParseDependentRequests="False" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="0" ExpectedResponseUrl="" ReportingName="" IgnoreHttpStatusCode="False" />
......
<?xml version="1.0" encoding="utf-8"?>
<WebTest Name="WebTest4" Id="5f8fe34b-e853-4a88-95cb-a8e963383b09" Owner="" Priority="2147483647" Enabled="True" CssProjectStructure="" CssIteration="" Timeout="0" WorkItemIds="" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" Description="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="default" StopOnError="False" RecordedResultFile="" ResultsLocale="">
<Items>
<Request Method="POST" Guid="60e123b6-6947-47f0-85cb-473647f73db1" Version="1.1" Url="https://ppdmzkw2/nak1/na_epersondata/V2/namnsokning" ThinkTime="0" Timeout="300" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="0" ExpectedResponseUrl="" ReportingName="" IgnoreHttpStatusCode="False">
<StringHttpBody ContentType="text/xml" InsertByteOrderMark="False">PABzAG8AYQBwAGUAbgB2ADoARQBuAHYAZQBsAG8AcABlACAAeABtAGwAbgBzADoAcwBvAGEAcABlAG4AdgA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AeABtAGwAcwBvAGEAcAAuAG8AcgBnAC8AcwBvAGEAcAAvAGUAbgB2AGUAbABvAHAAZQAvACIAIAB4AG0AbABuAHMAOgB4AHMAaQA9ACIAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAHcAMwAuAG8AcgBnAC8AMgAwADAAMQAvAFgATQBMAFMAYwBoAGUAbQBhAC0AaQBuAHMAdABhAG4AYwBlACIAIAB4AG0AbABuAHMAOgB2ADEAPQAiAGgAdAB0AHAAOgAvAC8AeABtAGwAcwAuAHMAawBhAHQAdABlAHYAZQByAGsAZQB0AC4AcwBlAC8AcwBlAC8AcwBrAGEAdAB0AGUAdgBlAHIAawBlAHQALwBmAG8AbABrAGIAbwBrAGYAbwByAGkAbgBnAC8AbgBhAC8AZQBwAGUAcgBzAG8AbgBkAGEAdABhAC8AVgAxACIAPgANAAoAIAAgADwAcwBvAGEAcABlAG4AdgA6AEgAZQBhAGQAZQByACAALwA+AA0ACgAgACAAPABzAG8AYQBwAGUAbgB2ADoAQgBvAGQAeQA+AA0ACgAgACAAIAAgADwAdgAxADoATgBhAG0AbgBzAG8AawBuAGkAbgBnAFIAZQBxAHUAZQBzAHQAPgANAAoAIAAgACAAIAAgACAAPAB2ADEAOgBCAGUAcwB0AGEAbABsAG4AaQBuAGcAPgANAAoAIAAgACAAIAAgACAAIAAgADwAdgAxADoATwByAGcATgByAD4AMQA2ADIAMAAyADEAMAAwADQANwA0ADgAPAAvAHYAMQA6AE8AcgBnAE4AcgA+AA0ACgAgACAAIAAgACAAIAAgACAAPAB2ADEAOgBCAGUAcwB0AGEAbABsAG4AaQBuAGcAcwBJAGQAPgAwADAAMAAwADAAMAA3ADkALQBGAE8AMAAxAC0AMAAwADAAMQA8AC8AdgAxADoAQgBlAHMAdABhAGwAbABuAGkAbgBnAHMASQBkAD4ADQAKACAAIAAgACAAIAAgADwALwB2ADEAOgBCAGUAcwB0AGEAbABsAG4AaQBuAGcAPgANAAoAIAAgACAAIAAgACAAPAB2ADEAOgBTAG8AawB2AGkAbABsAGsAbwByAE4AYQBtAG4APgANAAoAIAAgACAAIAAgACAAIAAgADwAdgAxADoAQQBkAHIAZQBzAHMAPgBNAEEARwBBAFMASQBOAFMARwBBAFQAQQBOACAANQAgAEEAIABMAEcASAAgADEAMAAwADMAPAAvAHYAMQA6AEEAZAByAGUAcwBzAD4ADQAKACAAIAAgACAAIAAgACAAIAA8AHYAMQA6AEUAZgB0AGUAcgBNAGUAbABsAGEAbgBOAGEAbQBuAD4ATgB1AHQAZQBtAGIAZQBpADwALwB2ADEAOgBFAGYAdABlAHIATQBlAGwAbABhAG4ATgBhAG0AbgA+AA0ACgAgACAAIAAgACAAIAAgACAAPAB2ADEAOgBGAG8AZABlAGwAcwBlAHQAaQBkAEYAcgBvAG0AIAB4AHMAaQA6AG4AaQBsAD0AIgB0AHIAdQBlACIAPgA8AC8AdgAxADoARgBvAGQAZQBsAHMAZQB0AGkAZABGAHIAbwBtAD4ADQAKACAAIAAgACAAIAAgACAAIAA8AHYAMQA6AEYAbwBkAGUAbABzAGUAdABpAGQAVABvAG0AIAB4AHMAaQA6AG4AaQBsAD0AIgB0AHIAdQBlACIAPgA8AC8AdgAxADoARgBvAGQAZQBsAHMAZQB0AGkAZABUAG8AbQA+AA0ACgAgACAAIAAgACAAIAAgACAAPAB2ADEAOgBGAG8AcgBuAGEAbQBuAD4AQQBiAGQAaQBrAGgAYQBkAGUAcgAgAE0AbwBoAGEAbQBlAGQAPAAvAHYAMQA6AEYAbwByAG4AYQBtAG4APgANAAoAIAAgACAAIAAgACAAIAAgADwAdgAxADoASwBvAG4AIAB4AHMAaQA6AG4AaQBsAD0AIgB0AHIAdQBlACIAPgA8AC8AdgAxADoASwBvAG4APgANAAoAIAAgACAAIAAgACAAIAAgADwAdgAxADoAUABvAHMAdABuAHUAbQBtAGUAcgBGAHIAbwBtACAAeABzAGkAOgBuAGkAbAA9ACIAdAByAHUAZQAiAD4APAAvAHYAMQA6AFAAbwBzAHQAbgB1AG0AbQBlAHIARgByAG8AbQA+AA0ACgAgACAAIAAgACAAIAAgACAAPAB2ADEAOgBQAG8AcwB0AG4AdQBtAG0AZQByAFQAbwBtACAAeABzAGkAOgBuAGkAbAA9ACIAdAByAHUAZQAiAD4APAAvAHYAMQA6AFAAbwBzAHQAbgB1AG0AbQBlAHIAVABvAG0APgANAAoAIAAgACAAIAAgACAAIAAgADwAdgAxADoAUABvAHMAdABvAHIAdAA+ADwALwB2ADEAOgBQAG8AcwB0AG8AcgB0AD4ADQAKACAAIAAgACAAIAAgADwALwB2ADEAOgBTAG8AawB2AGkAbABsAGsAbwByAE4AYQBtAG4APgANAAoAIAAgACAAIAA8AC8AdgAxADoATgBhAG0AbgBzAG8AawBuAGkAbgBnAFIAZQBxAHUAZQBzAHQAPgANAAoAIAAgADwALwBzAG8AYQBwAGUAbgB2ADoAQgBvAGQAeQA+AA0ACgA8AC8AcwBvAGEAcABlAG4AdgA6AEUAbgB2AGUAbABvAHAAZQA+AA==</StringHttpBody>
</Request>
</Items>
<WebTestPlugins>
<WebTestPlugin Classname="LIL_VSTT_Plugins.ServiceManagerWebTestPlugin, LIL_VSTT_Plugins, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null" DisplayName="Service Manager Config" Description="(C) Copyright 2015 LIGHTS IN LINE AB&#xD;&#xA;Sätter config värden i Service Manager instansen för hela testet.">
<RuleParameters>
<RuleParameter Name="exp100" Value="True" />
<RuleParameter Name="maxIdle" Value="100" />
<RuleParameter Name="keepAlive" Value="False" />
<RuleParameter Name="timeOut" Value="5000" />
<RuleParameter Name="interVal" Value="1000" />
<RuleParameter Name="useNagle" Value="False" />
<RuleParameter Name="useTls12" Value="True" />
</RuleParameters>
</WebTestPlugin>
<WebTestPlugin Classname="LIL_VSTT_Plugins.ClientCertificatePlugin, LIL_VSTT_Plugins, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null" DisplayName="Client Certificate" Description="(C) Copyright 2016 LIGHTS IN LINE AB&#xD;&#xA;Sätter webtestet att använda ett specifikt client cert för SSL. Certifikatet behöver inte installeras i certstore först.">
<RuleParameters>
<RuleParameter Name="pCertificatePath" Value="U:\projekt\2015\Folke - flapp\SoapUI\kommunA.p12" />
<RuleParameter Name="pCertificatePathParameter" Value="" />
<RuleParameter Name="pCertificatePassword" Value="3129445131123535" />
<RuleParameter Name="pCertificatePasswordParameter" Value="" />
<RuleParameter Name="pDebug" Value="False" />
<RuleParameter Name="pInstallTrusted" Value="True" />
<RuleParameter Name="pInstallUntrusted" Value="True" />
</RuleParameters>
</WebTestPlugin>
</WebTestPlugins>
</WebTest>
\ No newline at end of file