Add https client ceritificate mapping test (#74)
This commit is contained in:
parent
fc580eb0e9
commit
cc29517ef3
|
|
@ -48,4 +48,4 @@ src/AspNetCore/aspnetcore_msg.rc
|
||||||
src/AspNetCore/version.h
|
src/AspNetCore/version.h
|
||||||
.build
|
.build
|
||||||
|
|
||||||
AspNetCoreModule.VC.db
|
*.VC.*db
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
using AspNetCoreModule.Test.HttpClientHelper;
|
using AspNetCoreModule.Test.HttpClientHelper;
|
||||||
using Microsoft.Web.Administration;
|
using Microsoft.Web.Administration;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Management;
|
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
|
@ -260,6 +260,40 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EnableOneToOneClientCertificateMapping(string siteName, string userName, string password, string publicKey)
|
||||||
|
{
|
||||||
|
TestUtility.LogInformation("Enable one-to-one client certificate mapping authentication : " + siteName);
|
||||||
|
using (ServerManager serverManager = GetServerManager())
|
||||||
|
{
|
||||||
|
Configuration config = serverManager.GetApplicationHostConfiguration();
|
||||||
|
|
||||||
|
ConfigurationSection iisClientCertificateMappingAuthenticationSection = config.GetSection("system.webServer/security/authentication/iisClientCertificateMappingAuthentication", siteName);
|
||||||
|
|
||||||
|
// enable iisClientCertificateMappingAuthentication
|
||||||
|
ConfigurationElementCollection oneToOneMappingsCollection = iisClientCertificateMappingAuthenticationSection.GetCollection("oneToOneMappings");
|
||||||
|
iisClientCertificateMappingAuthenticationSection["enabled"] = true;
|
||||||
|
|
||||||
|
// add a new oneToOne mapping collection item
|
||||||
|
ConfigurationElement addElement = oneToOneMappingsCollection.CreateElement("add");
|
||||||
|
addElement["userName"] = userName;
|
||||||
|
addElement["password"] = password;
|
||||||
|
addElement["certificate"] = publicKey;
|
||||||
|
oneToOneMappingsCollection.Add(addElement);
|
||||||
|
|
||||||
|
// set sslFlags with SslNegotiateCert
|
||||||
|
ConfigurationSection accessSection = config.GetSection("system.webServer/security/access", siteName);
|
||||||
|
accessSection["sslFlags"] = "Ssl, SslNegotiateCert, SslRequireCert";
|
||||||
|
|
||||||
|
// disable other authentication to avoid any noise affected by other authentications
|
||||||
|
ConfigurationSection anonymousAuthenticationSection = config.GetSection("system.webServer/security/authentication/anonymousAuthentication", siteName);
|
||||||
|
anonymousAuthenticationSection["enabled"] = false;
|
||||||
|
ConfigurationSection windowsAuthenticationSection = config.GetSection("system.webServer/security/authentication/windowsAuthentication", siteName);
|
||||||
|
windowsAuthenticationSection["enabled"] = false;
|
||||||
|
|
||||||
|
serverManager.CommitChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SetCompression(string siteName, bool enabled)
|
public void SetCompression(string siteName, bool enabled)
|
||||||
{
|
{
|
||||||
TestUtility.LogInformation("Enable Compression : " + siteName);
|
TestUtility.LogInformation("Enable Compression : " + siteName);
|
||||||
|
|
@ -924,14 +958,205 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddBindingToSite(string siteName, string Ip, int Port, string host)
|
public string CreateSelfSignedCertificateWithMakeCert(string subjectName, string issuerName = null, string extendedKeyUsage = null)
|
||||||
|
{
|
||||||
|
string makecertExeFilePath = "makecert.exe";
|
||||||
|
var makecertExeFilePaths = new string[]
|
||||||
|
{
|
||||||
|
Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%"), "Windows Kits", "8.1", "bin", "x64", "makecert.exe"),
|
||||||
|
Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles%"), "Windows Kits", "8.1", "bin", "x86", "makecert.exe"),
|
||||||
|
Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%"), "Windows Kits", "8.0", "bin", "x64", "makecert.exe"),
|
||||||
|
Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles%"), "Windows Kits", "8.0", "bin", "x86", "makecert.exe"),
|
||||||
|
Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%"), "Windows SKDs", "Windows", "v7.1A", "bin", "x64", "makecert.exe"),
|
||||||
|
Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles%"), "Windows SKDs", "Windows", "v7.1A", "bin", "makecert.exe")
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (string item in makecertExeFilePaths)
|
||||||
|
{
|
||||||
|
if (File.Exists(item))
|
||||||
|
{
|
||||||
|
makecertExeFilePath = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string parameter;
|
||||||
|
string targetSSLStore = string.Empty;
|
||||||
|
if (issuerName == null)
|
||||||
|
{
|
||||||
|
// if issuer Name is null, you are going to create a root level certificate
|
||||||
|
parameter = "-r -pe -n \"CN = " + subjectName + "\" -b 12/22/2013 -e 12/23/2020 -ss root -sr localmachine -len 2048 -a sha256";
|
||||||
|
targetSSLStore = @"Cert:\LocalMachine\Root"; // => -ss root -sr localmachine
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if issuer Name is *not* null, you are going to create a child evel certificate from the given issuer certificate
|
||||||
|
switch (extendedKeyUsage)
|
||||||
|
{
|
||||||
|
// for web server certificate
|
||||||
|
case "1.3.6.1.5.5.7.3.1":
|
||||||
|
parameter = "-pe -n \"CN=" + subjectName + "\" -b 12/22/2013 -e 12/23/" + (System.DateTime.Now.Year + 10).ToString() + " -eku " + extendedKeyUsage + " -is root -ir localmachine -in \"" + issuerName + "\" -len 2048 -ss my -sr localmachine -a sha256";
|
||||||
|
targetSSLStore = @"Cert:\LocalMachine\My"; // => -ss my -sr localmachine
|
||||||
|
break;
|
||||||
|
|
||||||
|
// for client authentication
|
||||||
|
case "1.3.6.1.5.5.7.3.2":
|
||||||
|
parameter = "-pe -n \"CN=" + subjectName + "\" -eku " + extendedKeyUsage + " -is root -ir localmachine -in \"" + issuerName + "\" -ss my -sr currentuser -len 2048 -a sha256";
|
||||||
|
targetSSLStore = @"Cert:\CurrentUser\My"; // => -ss my -sr currentuser
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException(extendedKeyUsage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TestUtility.RunCommand(makecertExeFilePath, parameter);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
TestUtility.LogInformation("Failed to run makecert.exe. Makecert.exe is installed with Visual Studio or SDK. Please make sure setting PATH environment to include the directory path of the makecert.exe file");
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
string toolsPath = Path.Combine(InitializeTestMachine.GetSolutionDirectory(), "tools");
|
||||||
|
string powershellScript = Path.Combine(toolsPath, "certificate.ps1")
|
||||||
|
+ " -Command Get-CertificateThumbPrint" +
|
||||||
|
" -Subject " + subjectName +
|
||||||
|
" -TargetSSLStore \"" + targetSSLStore + "\"";
|
||||||
|
|
||||||
|
if (issuerName != null)
|
||||||
|
{
|
||||||
|
powershellScript += " -IssuerName " + issuerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
string output = TestUtility.RunPowershellScript(powershellScript);
|
||||||
|
if (output.Length != 40)
|
||||||
|
{
|
||||||
|
throw new System.ApplicationException("Failed to create a certificate, output: " + output);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateSelfSignedCertificate(string subjectName)
|
||||||
|
{
|
||||||
|
string toolsPath = Path.Combine(InitializeTestMachine.GetSolutionDirectory(), "tools");
|
||||||
|
string powershellScript = Path.Combine(toolsPath, "certificate.ps1")
|
||||||
|
+ " -Command Create-SelfSignedCertificate"
|
||||||
|
+ " -Subject " + subjectName;
|
||||||
|
|
||||||
|
string output = TestUtility.RunPowershellScript(powershellScript);
|
||||||
|
if (output.Length != 40)
|
||||||
|
{
|
||||||
|
throw new System.ApplicationException("Failed to create a certificate, output: " + output);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ExportCertificateTo(string thumbPrint, string sslStoreFrom = @"Cert:\LocalMachine\My", string sslStoreTo = @"Cert:\LocalMachine\Root", string pfxPassword = null)
|
||||||
|
{
|
||||||
|
string toolsPath = Path.Combine(InitializeTestMachine.GetSolutionDirectory(), "tools");
|
||||||
|
string powershellScript = Path.Combine(toolsPath, "certificate.ps1") +
|
||||||
|
" -Command Export-CertificateTo" +
|
||||||
|
" -TargetThumbPrint " + thumbPrint +
|
||||||
|
" -TargetSSLStore " + sslStoreFrom +
|
||||||
|
" -ExportToSSLStore " + sslStoreTo;
|
||||||
|
|
||||||
|
if (pfxPassword != null)
|
||||||
|
{
|
||||||
|
powershellScript += " -PfxPassword " + pfxPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
string output = TestUtility.RunPowershellScript(powershellScript);
|
||||||
|
if (output != string.Empty)
|
||||||
|
{
|
||||||
|
throw new System.ApplicationException("Failed to export a certificate to RootCA, output: " + output);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetCertificatePublicKey(string thumbPrint, string sslStore = @"Cert:\LocalMachine\My")
|
||||||
|
{
|
||||||
|
string toolsPath = Path.Combine(InitializeTestMachine.GetSolutionDirectory(), "tools");
|
||||||
|
string powershellScript = Path.Combine(toolsPath, "certificate.ps1") +
|
||||||
|
" -Command Get-CertificatePublicKey" +
|
||||||
|
" -TargetThumbPrint " + thumbPrint +
|
||||||
|
" -TargetSSLStore " + sslStore;
|
||||||
|
|
||||||
|
string output = TestUtility.RunPowershellScript(powershellScript);
|
||||||
|
if (output.Length < 500)
|
||||||
|
{
|
||||||
|
throw new System.ApplicationException("Failed to get certificate public key, output: " + output);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DeleteCertificate(string thumbPrint, string sslStore= @"Cert:\LocalMachine\My")
|
||||||
|
{
|
||||||
|
string toolsPath = Path.Combine(InitializeTestMachine.GetSolutionDirectory(), "tools");
|
||||||
|
string powershellScript = Path.Combine(toolsPath, "certificate.ps1") +
|
||||||
|
" -Command Delete-Certificate" +
|
||||||
|
" -TargetThumbPrint " + thumbPrint +
|
||||||
|
" -TargetSSLStore " + sslStore;
|
||||||
|
|
||||||
|
string output = TestUtility.RunPowershellScript(powershellScript);
|
||||||
|
if (output != string.Empty)
|
||||||
|
{
|
||||||
|
throw new System.ApplicationException("Failed to delete a certificate (thumbprint: " + thumbPrint + ", output: " + output);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSSLCertificate(int port, string hexIpAddress, string thumbPrint, string sslStore = @"Cert:\LocalMachine\My")
|
||||||
|
{
|
||||||
|
// Remove a certificate mapping if it exists
|
||||||
|
RemoveSSLCertificate(port, hexIpAddress);
|
||||||
|
|
||||||
|
// Configure certificate mapping with the newly created certificate
|
||||||
|
string toolsPath = Path.Combine(InitializeTestMachine.GetSolutionDirectory(), "tools");
|
||||||
|
string powershellScript = Path.Combine(toolsPath, "httpsys.ps1") +
|
||||||
|
" -Command Add-SslBinding" +
|
||||||
|
" -IpAddress " + hexIpAddress +
|
||||||
|
" -Port " + port.ToString() +
|
||||||
|
" –Thumbprint \"" + thumbPrint + "\"" +
|
||||||
|
" -TargetSSLStore " + sslStore;
|
||||||
|
|
||||||
|
string output = TestUtility.RunPowershellScript(powershellScript);
|
||||||
|
if (output != string.Empty)
|
||||||
|
{
|
||||||
|
throw new System.ApplicationException("Failed to configure certificate, output: " + output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveSSLCertificate(int port, string hexIpAddress, string sslStore = @"Cert:\LocalMachine\My")
|
||||||
|
{
|
||||||
|
string toolsPath = Path.Combine(InitializeTestMachine.GetSolutionDirectory(), "tools");
|
||||||
|
string powershellScript = Path.Combine(toolsPath, "httpsys.ps1") +
|
||||||
|
" -Command Get-SslBinding" +
|
||||||
|
" -IpAddress " + hexIpAddress +
|
||||||
|
" -Port " + port.ToString();
|
||||||
|
|
||||||
|
string output = TestUtility.RunPowershellScript(powershellScript);
|
||||||
|
if (output != string.Empty)
|
||||||
|
{
|
||||||
|
// Delete a certificate mapping if it exists
|
||||||
|
powershellScript = Path.Combine(toolsPath, "httpsys.ps1") + " -Command Delete-SslBinding -IpAddress " + hexIpAddress + " -Port " + port.ToString();
|
||||||
|
output = TestUtility.RunPowershellScript(powershellScript);
|
||||||
|
if (output != string.Empty)
|
||||||
|
{
|
||||||
|
throw new System.ApplicationException("Failed to delete certificate, output: " + output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddBindingToSite(string siteName, string ipAddress, int port, string host, string protocol = "http")
|
||||||
{
|
{
|
||||||
string bindingInfo = "";
|
string bindingInfo = "";
|
||||||
if (Ip == null)
|
if (ipAddress == null)
|
||||||
Ip = "*";
|
ipAddress = "*";
|
||||||
bindingInfo += Ip;
|
bindingInfo += ipAddress;
|
||||||
bindingInfo += ":";
|
bindingInfo += ":";
|
||||||
bindingInfo += Port;
|
bindingInfo += port;
|
||||||
bindingInfo += ":";
|
bindingInfo += ":";
|
||||||
if (host != null)
|
if (host != null)
|
||||||
bindingInfo += host;
|
bindingInfo += host;
|
||||||
|
|
@ -944,7 +1169,7 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
{
|
{
|
||||||
SiteCollection sites = serverManager.Sites;
|
SiteCollection sites = serverManager.Sites;
|
||||||
Binding b = sites[siteName].Bindings.CreateElement();
|
Binding b = sites[siteName].Bindings.CreateElement();
|
||||||
b.SetAttributeValue("protocol", "http");
|
b.SetAttributeValue("protocol", protocol);
|
||||||
b.SetAttributeValue("bindingInformation", bindingInfo);
|
b.SetAttributeValue("bindingInformation", bindingInfo);
|
||||||
|
|
||||||
sites[siteName].Bindings.Add(b);
|
sites[siteName].Bindings.Add(b);
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ using System.Security.AccessControl;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Management.Automation;
|
||||||
|
using System.Management.Automation.Runspaces;
|
||||||
|
|
||||||
namespace AspNetCoreModule.Test.Framework
|
namespace AspNetCoreModule.Test.Framework
|
||||||
{
|
{
|
||||||
|
|
@ -216,7 +219,7 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GiveWritePermissionTo(string folder, SecurityIdentifier sid)
|
public static void GiveWritePermissionTo(string folder, SecurityIdentifier sid)
|
||||||
{
|
{
|
||||||
DirectorySecurity fsecurity = Directory.GetAccessControl(folder);
|
DirectorySecurity fsecurity = Directory.GetAccessControl(folder);
|
||||||
|
|
@ -696,6 +699,48 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string RunPowershellScript(string scriptText)
|
||||||
|
{
|
||||||
|
IPEndPoint a = new IPEndPoint(0, 443);
|
||||||
|
|
||||||
|
// create Powershell runspace
|
||||||
|
Runspace runspace = RunspaceFactory.CreateRunspace();
|
||||||
|
|
||||||
|
// open it
|
||||||
|
runspace.Open();
|
||||||
|
|
||||||
|
// create a pipeline and feed it the script text
|
||||||
|
Pipeline pipeline = runspace.CreatePipeline();
|
||||||
|
pipeline.Commands.AddScript(scriptText);
|
||||||
|
|
||||||
|
// add an extra command to transform the script output objects into nicely formatted strings
|
||||||
|
// remove this line to get the actual objects that the script returns. For example, the script
|
||||||
|
// "Get-Process" returns a collection of System.Diagnostics.Process instances.
|
||||||
|
pipeline.Commands.Add("Out-String");
|
||||||
|
Collection<PSObject> results = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// execute the script
|
||||||
|
results = pipeline.Invoke();
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to run " + scriptText + " " + ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// close the runspace
|
||||||
|
runspace.Close();
|
||||||
|
|
||||||
|
// convert the script result into a single string
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
foreach (PSObject obj in results)
|
||||||
|
{
|
||||||
|
stringBuilder.AppendLine(obj.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringBuilder.ToString().Trim(new char[] { ' ', '\r', '\n' });
|
||||||
|
}
|
||||||
|
|
||||||
public static int RunCommand(string fileName, string arguments = null, bool checkStandardError = true, bool waitForExit=true)
|
public static int RunCommand(string fileName, string arguments = null, bool checkStandardError = true, bool waitForExit=true)
|
||||||
{
|
{
|
||||||
int pid = -1;
|
int pid = -1;
|
||||||
|
|
|
||||||
|
|
@ -101,21 +101,30 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uri GetHttpUri()
|
public Uri GetUri()
|
||||||
{
|
{
|
||||||
return new Uri("http://" + _testSite.HostName + ":" + _testSite.TcpPort.ToString() + URL);
|
return new Uri("http://" + _testSite.HostName + ":" + _testSite.TcpPort.ToString() + URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uri GetHttpUri(string subPath)
|
public Uri GetUri(string subPath, int port = -1, string protocol = "http")
|
||||||
{
|
{
|
||||||
string tempSubPath = subPath;
|
if (port == -1)
|
||||||
if (!tempSubPath.StartsWith("/"))
|
|
||||||
{
|
{
|
||||||
tempSubPath = "/" + tempSubPath;
|
port = _testSite.TcpPort;
|
||||||
}
|
}
|
||||||
return new Uri("http://" + _testSite.HostName + ":" + _testSite.TcpPort.ToString() + URL + tempSubPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
string tempSubPath = string.Empty;
|
||||||
|
if (subPath != null)
|
||||||
|
{
|
||||||
|
tempSubPath = subPath;
|
||||||
|
if (!tempSubPath.StartsWith("/"))
|
||||||
|
{
|
||||||
|
tempSubPath = "/" + tempSubPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Uri(protocol + "://" + _testSite.HostName + ":" + port.ToString() + URL + tempSubPath);
|
||||||
|
}
|
||||||
|
|
||||||
public string _appPoolName = null;
|
public string _appPoolName = null;
|
||||||
public string AppPoolName
|
public string AppPoolName
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,19 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string _postFix = null;
|
||||||
|
public string PostFix
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _postFix;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_postFix = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int _tcpPort = 8080;
|
public int _tcpPort = 8080;
|
||||||
public int TcpPort
|
public int TcpPort
|
||||||
{
|
{
|
||||||
|
|
@ -103,11 +116,12 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
//
|
//
|
||||||
string siteRootPath = string.Empty;
|
string siteRootPath = string.Empty;
|
||||||
string siteName = string.Empty;
|
string siteName = string.Empty;
|
||||||
|
string postfix = string.Empty;
|
||||||
|
|
||||||
// repeat three times until getting the valid temporary directory path
|
// repeat three times until getting the valid temporary directory path
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
string postfix = Path.GetRandomFileName();
|
postfix = Path.GetRandomFileName();
|
||||||
siteName = loggerPrefix.Replace(" ", "") + "_" + postfix;
|
siteName = loggerPrefix.Replace(" ", "") + "_" + postfix;
|
||||||
siteRootPath = Path.Combine(Environment.ExpandEnvironmentVariables("%SystemDrive%") + @"\", "inetpub", "ANCMTest", siteName);
|
siteRootPath = Path.Combine(Environment.ExpandEnvironmentVariables("%SystemDrive%") + @"\", "inetpub", "ANCMTest", siteName);
|
||||||
if (!Directory.Exists(siteRootPath))
|
if (!Directory.Exists(siteRootPath))
|
||||||
|
|
@ -174,6 +188,7 @@ namespace AspNetCoreModule.Test.Framework
|
||||||
// Initialize member variables
|
// Initialize member variables
|
||||||
_hostName = "localhost";
|
_hostName = "localhost";
|
||||||
_siteName = siteName;
|
_siteName = siteName;
|
||||||
|
_postFix = postfix;
|
||||||
_tcpPort = tcpPort;
|
_tcpPort = tcpPort;
|
||||||
|
|
||||||
RootAppContext = new TestWebApplication("/", Path.Combine(siteRootPath, "WebSite1"), this);
|
RootAppContext = new TestWebApplication("/", Path.Combine(siteRootPath, "WebSite1"), this);
|
||||||
|
|
|
||||||
|
|
@ -289,5 +289,28 @@ namespace AspNetCoreModule.Test
|
||||||
{
|
{
|
||||||
return DoCachingTest(appPoolBitness);
|
return DoCachingTest(appPoolBitness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[EnvironmentVariableTestCondition("IIS_VARIATIONS_ENABLED")]
|
||||||
|
[ConditionalTheory]
|
||||||
|
[OSSkipCondition(OperatingSystems.Linux)]
|
||||||
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
|
[InlineData(IISConfigUtility.AppPoolBitness.enable32Bit)]
|
||||||
|
[InlineData(IISConfigUtility.AppPoolBitness.noChange)]
|
||||||
|
public Task SendHTTPSRequestTest(IISConfigUtility.AppPoolBitness appPoolBitness)
|
||||||
|
{
|
||||||
|
return DoSendHTTPSRequestTest(appPoolBitness);
|
||||||
|
}
|
||||||
|
|
||||||
|
[EnvironmentVariableTestCondition("IIS_VARIATIONS_ENABLED")]
|
||||||
|
[ConditionalTheory]
|
||||||
|
[OSSkipCondition(OperatingSystems.Linux)]
|
||||||
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
|
[InlineData(IISConfigUtility.AppPoolBitness.enable32Bit, true)]
|
||||||
|
[InlineData(IISConfigUtility.AppPoolBitness.noChange, true)]
|
||||||
|
[InlineData(IISConfigUtility.AppPoolBitness.noChange, false)]
|
||||||
|
public Task ClientCertificateMappingTest(IISConfigUtility.AppPoolBitness appPoolBitness, bool useHTTPSMiddleWare)
|
||||||
|
{
|
||||||
|
return DoClientCertificateMappingTest(appPoolBitness, useHTTPSMiddleWare);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
DateTime startTime = DateTime.Now;
|
DateTime startTime = DateTime.Now;
|
||||||
|
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
Assert.Equal(backendProcess.ProcessName.ToLower().Replace(".exe", ""), testSite.AspNetCoreApp.GetProcessFileName().ToLower().Replace(".exe", ""));
|
Assert.Equal(backendProcess.ProcessName.ToLower().Replace(".exe", ""), testSite.AspNetCoreApp.GetProcessFileName().ToLower().Replace(".exe", ""));
|
||||||
|
|
@ -50,7 +50,7 @@ namespace AspNetCoreModule.Test
|
||||||
var httpClientHandler = new HttpClientHandler();
|
var httpClientHandler = new HttpClientHandler();
|
||||||
var httpClient = new HttpClient(httpClientHandler)
|
var httpClient = new HttpClient(httpClientHandler)
|
||||||
{
|
{
|
||||||
BaseAddress = testSite.AspNetCoreApp.GetHttpUri(),
|
BaseAddress = testSite.AspNetCoreApp.GetUri(),
|
||||||
Timeout = TimeSpan.FromSeconds(5),
|
Timeout = TimeSpan.FromSeconds(5),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ namespace AspNetCoreModule.Test
|
||||||
DateTime startTime = DateTime.Now;
|
DateTime startTime = DateTime.Now;
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
backendProcessId_old = backendProcessId;
|
backendProcessId_old = backendProcessId;
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
|
|
@ -99,7 +99,7 @@ namespace AspNetCoreModule.Test
|
||||||
DateTime startTime = DateTime.Now;
|
DateTime startTime = DateTime.Now;
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
backendProcessId_old = backendProcessId;
|
backendProcessId_old = backendProcessId;
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
|
|
@ -131,7 +131,7 @@ namespace AspNetCoreModule.Test
|
||||||
DateTime startTime = DateTime.Now;
|
DateTime startTime = DateTime.Now;
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
backendProcessId_old = backendProcessId;
|
backendProcessId_old = backendProcessId;
|
||||||
|
|
@ -163,7 +163,7 @@ namespace AspNetCoreModule.Test
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|
||||||
string urlForUrlRewrite = testSite.URLRewriteApp.URL + "/Rewrite2/" + testSite.AspNetCoreApp.URL + "/GetProcessId";
|
string urlForUrlRewrite = testSite.URLRewriteApp.URL + "/Rewrite2/" + testSite.AspNetCoreApp.URL + "/GetProcessId";
|
||||||
string backendProcessId = await GetResponse(testSite.RootAppContext.GetHttpUri(urlForUrlRewrite), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.RootAppContext.GetUri(urlForUrlRewrite), HttpStatusCode.OK);
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
backendProcessId_old = backendProcessId;
|
backendProcessId_old = backendProcessId;
|
||||||
|
|
@ -196,7 +196,7 @@ namespace AspNetCoreModule.Test
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
string urlForUrlRewrite = testSite.URLRewriteApp.URL + "/Rewrite2/" + testSite.AspNetCoreApp.URL + "/GetProcessId";
|
string urlForUrlRewrite = testSite.URLRewriteApp.URL + "/Rewrite2/" + testSite.AspNetCoreApp.URL + "/GetProcessId";
|
||||||
string backendProcessId = await GetResponse(testSite.RootAppContext.GetHttpUri(urlForUrlRewrite), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.RootAppContext.GetUri(urlForUrlRewrite), HttpStatusCode.OK);
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
backendProcessId_old = backendProcessId;
|
backendProcessId_old = backendProcessId;
|
||||||
|
|
@ -221,8 +221,8 @@ namespace AspNetCoreModule.Test
|
||||||
DateTime startTime = DateTime.Now;
|
DateTime startTime = DateTime.Now;
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|
||||||
string totalNumber = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetEnvironmentVariables"), HttpStatusCode.OK);
|
string totalNumber = await GetResponse(testSite.AspNetCoreApp.GetUri("GetEnvironmentVariables"), HttpStatusCode.OK);
|
||||||
Assert.True(totalNumber == (await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetEnvironmentVariables"), HttpStatusCode.OK)));
|
Assert.True(totalNumber == (await GetResponse(testSite.AspNetCoreApp.GetUri("GetEnvironmentVariables"), HttpStatusCode.OK)));
|
||||||
|
|
||||||
iisConfig.SetANCMConfig(
|
iisConfig.SetANCMConfig(
|
||||||
testSite.SiteName,
|
testSite.SiteName,
|
||||||
|
|
@ -237,7 +237,7 @@ namespace AspNetCoreModule.Test
|
||||||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||||
|
|
||||||
int expectedValue = Convert.ToInt32(totalNumber) + 1;
|
int expectedValue = Convert.ToInt32(totalNumber) + 1;
|
||||||
Assert.True(expectedValue.ToString() == (await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetEnvironmentVariables"), HttpStatusCode.OK)));
|
Assert.True(expectedValue.ToString() == (await GetResponse(testSite.AspNetCoreApp.GetUri("GetEnvironmentVariables"), HttpStatusCode.OK)));
|
||||||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "environmentVariable", new string[] { "ANCMTestBar", "bar" });
|
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "environmentVariable", new string[] { "ANCMTestBar", "bar" });
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|
||||||
|
|
@ -245,8 +245,8 @@ namespace AspNetCoreModule.Test
|
||||||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||||
|
|
||||||
expectedValue++;
|
expectedValue++;
|
||||||
Assert.True("foo" == (await GetResponse(testSite.AspNetCoreApp.GetHttpUri("ExpandEnvironmentVariablesANCMTestFoo"), HttpStatusCode.OK)));
|
Assert.True("foo" == (await GetResponse(testSite.AspNetCoreApp.GetUri("ExpandEnvironmentVariablesANCMTestFoo"), HttpStatusCode.OK)));
|
||||||
Assert.True("bar" == (await GetResponse(testSite.AspNetCoreApp.GetHttpUri("ExpandEnvironmentVariablesANCMTestBar"), HttpStatusCode.OK)));
|
Assert.True("bar" == (await GetResponse(testSite.AspNetCoreApp.GetUri("ExpandEnvironmentVariablesANCMTestBar"), HttpStatusCode.OK)));
|
||||||
}
|
}
|
||||||
|
|
||||||
testSite.AspNetCoreApp.RestoreFile("web.config");
|
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||||
|
|
@ -270,11 +270,11 @@ namespace AspNetCoreModule.Test
|
||||||
Thread.Sleep(1100);
|
Thread.Sleep(1100);
|
||||||
|
|
||||||
// verify 503
|
// verify 503
|
||||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri(), fileContent + "\r\n", HttpStatusCode.ServiceUnavailable);
|
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri(), fileContent + "\r\n", HttpStatusCode.ServiceUnavailable);
|
||||||
|
|
||||||
// rename app_offline.htm to _app_offline.htm and verify 200
|
// rename app_offline.htm to _app_offline.htm and verify 200
|
||||||
testSite.AspNetCoreApp.MoveFile("App_Offline.Htm", "_App_Offline.Htm");
|
testSite.AspNetCoreApp.MoveFile("App_Offline.Htm", "_App_Offline.Htm");
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
Assert.Equal(backendProcess.ProcessName.ToLower().Replace(".exe", ""), testSite.AspNetCoreApp.GetProcessFileName().ToLower().Replace(".exe", ""));
|
Assert.Equal(backendProcess.ProcessName.ToLower().Replace(".exe", ""), testSite.AspNetCoreApp.GetProcessFileName().ToLower().Replace(".exe", ""));
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
|
|
@ -305,11 +305,11 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
// verify 503
|
// verify 503
|
||||||
string urlForUrlRewrite = testSite.URLRewriteApp.URL + "/Rewrite2/" + testSite.AspNetCoreApp.URL + "/GetProcessId";
|
string urlForUrlRewrite = testSite.URLRewriteApp.URL + "/Rewrite2/" + testSite.AspNetCoreApp.URL + "/GetProcessId";
|
||||||
await VerifyResponseBody(testSite.RootAppContext.GetHttpUri(urlForUrlRewrite), fileContent + "\r\n", HttpStatusCode.ServiceUnavailable);
|
await VerifyResponseBody(testSite.RootAppContext.GetUri(urlForUrlRewrite), fileContent + "\r\n", HttpStatusCode.ServiceUnavailable);
|
||||||
|
|
||||||
// delete app_offline.htm and verify 200
|
// delete app_offline.htm and verify 200
|
||||||
testSite.AspNetCoreApp.DeleteFile("App_Offline.Htm");
|
testSite.AspNetCoreApp.DeleteFile("App_Offline.Htm");
|
||||||
string backendProcessId = await GetResponse(testSite.RootAppContext.GetHttpUri(urlForUrlRewrite), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.RootAppContext.GetUri(urlForUrlRewrite), HttpStatusCode.OK);
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
Assert.Equal(backendProcess.ProcessName.ToLower().Replace(".exe", ""), testSite.AspNetCoreApp.GetProcessFileName().ToLower().Replace(".exe", ""));
|
Assert.Equal(backendProcess.ProcessName.ToLower().Replace(".exe", ""), testSite.AspNetCoreApp.GetProcessFileName().ToLower().Replace(".exe", ""));
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
|
|
@ -333,7 +333,7 @@ namespace AspNetCoreModule.Test
|
||||||
new KeyValuePair<string, string>("TestData", testData),
|
new KeyValuePair<string, string>("TestData", testData),
|
||||||
};
|
};
|
||||||
var expectedResponseBody = "FirstName=Mickey&LastName=Mouse&TestData=" + testData;
|
var expectedResponseBody = "FirstName=Mickey&LastName=Mouse&TestData=" + testData;
|
||||||
await VerifyPostResponseBody(testSite.AspNetCoreApp.GetHttpUri("EchoPostData"), postFormData, expectedResponseBody, HttpStatusCode.OK);
|
await VerifyPostResponseBody(testSite.AspNetCoreApp.GetUri("EchoPostData"), postFormData, expectedResponseBody, HttpStatusCode.OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,7 +359,7 @@ namespace AspNetCoreModule.Test
|
||||||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "disableStartUpErrorPage", true);
|
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "disableStartUpErrorPage", true);
|
||||||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "processPath", errorMessageContainThis);
|
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "processPath", errorMessageContainThis);
|
||||||
|
|
||||||
var responseBody = await GetResponse(testSite.AspNetCoreApp.GetHttpUri(), HttpStatusCode.BadGateway);
|
var responseBody = await GetResponse(testSite.AspNetCoreApp.GetUri(), HttpStatusCode.BadGateway);
|
||||||
responseBody = responseBody.Replace("\r", "").Replace("\n", "").Trim();
|
responseBody = responseBody.Replace("\r", "").Replace("\n", "").Trim();
|
||||||
Assert.True(responseBody == curstomErrorMessage);
|
Assert.True(responseBody == curstomErrorMessage);
|
||||||
|
|
||||||
|
|
@ -376,7 +376,7 @@ namespace AspNetCoreModule.Test
|
||||||
// check JitDebugger before continuing
|
// check JitDebugger before continuing
|
||||||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||||
|
|
||||||
responseBody = await GetResponse(testSite.AspNetCoreApp.GetHttpUri(), HttpStatusCode.BadGateway);
|
responseBody = await GetResponse(testSite.AspNetCoreApp.GetUri(), HttpStatusCode.BadGateway);
|
||||||
Assert.True(responseBody.Contains("808681"));
|
Assert.True(responseBody.Contains("808681"));
|
||||||
|
|
||||||
// verify event error log
|
// verify event error log
|
||||||
|
|
@ -409,7 +409,7 @@ namespace AspNetCoreModule.Test
|
||||||
DateTime startTimeInsideLooping = DateTime.Now;
|
DateTime startTimeInsideLooping = DateTime.Now;
|
||||||
Thread.Sleep(50);
|
Thread.Sleep(50);
|
||||||
|
|
||||||
var statusCode = await GetResponseStatusCode(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"));
|
var statusCode = await GetResponseStatusCode(testSite.AspNetCoreApp.GetUri("GetProcessId"));
|
||||||
if (statusCode != HttpStatusCode.OK.ToString())
|
if (statusCode != HttpStatusCode.OK.ToString())
|
||||||
{
|
{
|
||||||
Assert.True(i >= valueOfRapidFailsPerMinute, i.ToString() + "is greater than or equals to " + valueOfRapidFailsPerMinute.ToString());
|
Assert.True(i >= valueOfRapidFailsPerMinute, i.ToString() + "is greater than or equals to " + valueOfRapidFailsPerMinute.ToString());
|
||||||
|
|
@ -418,7 +418,7 @@ namespace AspNetCoreModule.Test
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||||
backendProcessId_old = backendProcessId;
|
backendProcessId_old = backendProcessId;
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
|
|
@ -455,7 +455,7 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
int id = Convert.ToInt32(backendProcessId);
|
int id = Convert.ToInt32(backendProcessId);
|
||||||
if (!processIDs.Contains(id))
|
if (!processIDs.Contains(id))
|
||||||
{
|
{
|
||||||
|
|
@ -487,7 +487,7 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
int id = Convert.ToInt32(backendProcessId);
|
int id = Convert.ToInt32(backendProcessId);
|
||||||
if (!processIDs.Contains(id))
|
if (!processIDs.Contains(id))
|
||||||
{
|
{
|
||||||
|
|
@ -521,11 +521,11 @@ namespace AspNetCoreModule.Test
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
if (startupTimeLimit < startupDelay)
|
if (startupTimeLimit < startupDelay)
|
||||||
{
|
{
|
||||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetHttpUri("DoSleep3000"), HttpStatusCode.BadGateway);
|
await VerifyResponseStatus(testSite.AspNetCoreApp.GetUri("DoSleep3000"), HttpStatusCode.BadGateway);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri("DoSleep3000"), "Running", HttpStatusCode.OK);
|
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri("DoSleep3000"), "Running", HttpStatusCode.OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
testSite.AspNetCoreApp.RestoreFile("web.config");
|
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||||
|
|
@ -543,11 +543,11 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
if (requestTimeout.ToString() == "00:02:00")
|
if (requestTimeout.ToString() == "00:02:00")
|
||||||
{
|
{
|
||||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri("DoSleep65000"), "Running", HttpStatusCode.OK, timeout:70);
|
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri("DoSleep65000"), "Running", HttpStatusCode.OK, timeout:70);
|
||||||
}
|
}
|
||||||
else if (requestTimeout.ToString() == "00:01:00")
|
else if (requestTimeout.ToString() == "00:01:00")
|
||||||
{
|
{
|
||||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetHttpUri("DoSleep65000"), HttpStatusCode.BadGateway, 70);
|
await VerifyResponseStatus(testSite.AspNetCoreApp.GetUri("DoSleep65000"), HttpStatusCode.BadGateway, 70);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -573,8 +573,8 @@ namespace AspNetCoreModule.Test
|
||||||
new string[] { "ANCMTestShutdownDelay", "20000" }
|
new string[] { "ANCMTestShutdownDelay", "20000" }
|
||||||
);
|
);
|
||||||
|
|
||||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri(), "Running", HttpStatusCode.OK);
|
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri(), "Running", HttpStatusCode.OK);
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||||
|
|
||||||
// Set a new value such as 100 to make the backend process being recycled
|
// Set a new value such as 100 to make the backend process being recycled
|
||||||
|
|
@ -585,8 +585,8 @@ namespace AspNetCoreModule.Test
|
||||||
var difference = endTime - startTime;
|
var difference = endTime - startTime;
|
||||||
Assert.True(difference.Seconds >= expectedClosingTime);
|
Assert.True(difference.Seconds >= expectedClosingTime);
|
||||||
Assert.True(difference.Seconds < expectedClosingTime + 3);
|
Assert.True(difference.Seconds < expectedClosingTime + 3);
|
||||||
Assert.True(backendProcessId != await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK));
|
Assert.True(backendProcessId != await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK));
|
||||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri(), "Running", HttpStatusCode.OK);
|
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri(), "Running", HttpStatusCode.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
testSite.AspNetCoreApp.RestoreFile("web.config");
|
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||||
|
|
@ -605,7 +605,7 @@ namespace AspNetCoreModule.Test
|
||||||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "stdoutLogEnabled", true);
|
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "stdoutLogEnabled", true);
|
||||||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "stdoutLogFile", @".\logs\stdout");
|
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "stdoutLogFile", @".\logs\stdout");
|
||||||
|
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
string logPath = testSite.AspNetCoreApp.GetDirectoryPathWith("logs");
|
string logPath = testSite.AspNetCoreApp.GetDirectoryPathWith("logs");
|
||||||
Assert.False(Directory.Exists(logPath));
|
Assert.False(Directory.Exists(logPath));
|
||||||
Assert.True(TestUtility.RetryHelper((arg1, arg2, arg3) => VerifyApplicationEventLog(arg1, arg2, arg3), 1004, startTime, @"logs\stdout"));
|
Assert.True(TestUtility.RetryHelper((arg1, arg2, arg3) => VerifyApplicationEventLog(arg1, arg2, arg3), 1004, startTime, @"logs\stdout"));
|
||||||
|
|
@ -615,7 +615,7 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
// verify the log file is not created because backend process is not recycled
|
// verify the log file is not created because backend process is not recycled
|
||||||
Assert.True(Directory.GetFiles(logPath).Length == 0);
|
Assert.True(Directory.GetFiles(logPath).Length == 0);
|
||||||
Assert.True(backendProcessId == (await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK)));
|
Assert.True(backendProcessId == (await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK)));
|
||||||
|
|
||||||
// reset web.config to recycle backend process and give write permission to the Users local group to which IIS workerprocess identity belongs
|
// reset web.config to recycle backend process and give write permission to the Users local group to which IIS workerprocess identity belongs
|
||||||
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
|
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
|
||||||
|
|
@ -630,7 +630,7 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "stdoutLogEnabled", true);
|
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "stdoutLogEnabled", true);
|
||||||
|
|
||||||
Assert.True(backendProcessId != (await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK)));
|
Assert.True(backendProcessId != (await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK)));
|
||||||
|
|
||||||
// Verify log file is created now after backend process is recycled
|
// Verify log file is created now after backend process is recycled
|
||||||
Assert.True(TestUtility.RetryHelper(p => { return Directory.GetFiles(p).Length > 0 ? true : false; }, logPath));
|
Assert.True(TestUtility.RetryHelper(p => { return Directory.GetFiles(p).Length > 0 ? true : false; }, logPath));
|
||||||
|
|
@ -647,7 +647,7 @@ namespace AspNetCoreModule.Test
|
||||||
using (var iisConfig = new IISConfigUtility(ServerType.IIS))
|
using (var iisConfig = new IISConfigUtility(ServerType.IIS))
|
||||||
{
|
{
|
||||||
string arguments = argumentsPrefix + testSite.AspNetCoreApp.GetArgumentFileName();
|
string arguments = argumentsPrefix + testSite.AspNetCoreApp.GetArgumentFileName();
|
||||||
string tempProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string tempProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
var tempBackendProcess = Process.GetProcessById(Convert.ToInt32(tempProcessId));
|
var tempBackendProcess = Process.GetProcessById(Convert.ToInt32(tempProcessId));
|
||||||
|
|
||||||
// replace $env with the actual test value
|
// replace $env with the actual test value
|
||||||
|
|
@ -669,7 +669,7 @@ namespace AspNetCoreModule.Test
|
||||||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
Assert.True(TestUtility.RetryHelper((arg1, arg2) => VerifyANCMStartEvent(arg1, arg2), startTime, backendProcessId));
|
Assert.True(TestUtility.RetryHelper((arg1, arg2) => VerifyANCMStartEvent(arg1, arg2), startTime, backendProcessId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -685,7 +685,7 @@ namespace AspNetCoreModule.Test
|
||||||
{
|
{
|
||||||
string result = string.Empty;
|
string result = string.Empty;
|
||||||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "forwardWindowsAuthToken", enabledForwardWindowsAuthToken);
|
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "forwardWindowsAuthToken", enabledForwardWindowsAuthToken);
|
||||||
string requestHeaders = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("DumpRequestHeaders"), HttpStatusCode.OK);
|
string requestHeaders = await GetResponse(testSite.AspNetCoreApp.GetUri("DumpRequestHeaders"), HttpStatusCode.OK);
|
||||||
Assert.False(requestHeaders.ToUpper().Contains("MS-ASPNETCORE-WINAUTHTOKEN"));
|
Assert.False(requestHeaders.ToUpper().Contains("MS-ASPNETCORE-WINAUTHTOKEN"));
|
||||||
|
|
||||||
iisConfig.EnableWindowsAuthentication(testSite.SiteName);
|
iisConfig.EnableWindowsAuthentication(testSite.SiteName);
|
||||||
|
|
@ -696,13 +696,13 @@ namespace AspNetCoreModule.Test
|
||||||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|
||||||
requestHeaders = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("DumpRequestHeaders"), HttpStatusCode.OK);
|
requestHeaders = await GetResponse(testSite.AspNetCoreApp.GetUri("DumpRequestHeaders"), HttpStatusCode.OK);
|
||||||
if (enabledForwardWindowsAuthToken)
|
if (enabledForwardWindowsAuthToken)
|
||||||
{
|
{
|
||||||
string expectedHeaderName = "MS-ASPNETCORE-WINAUTHTOKEN";
|
string expectedHeaderName = "MS-ASPNETCORE-WINAUTHTOKEN";
|
||||||
Assert.True(requestHeaders.ToUpper().Contains(expectedHeaderName));
|
Assert.True(requestHeaders.ToUpper().Contains(expectedHeaderName));
|
||||||
|
|
||||||
result = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("ImpersonateMiddleware"), HttpStatusCode.OK);
|
result = await GetResponse(testSite.AspNetCoreApp.GetUri("ImpersonateMiddleware"), HttpStatusCode.OK);
|
||||||
bool compare = false;
|
bool compare = false;
|
||||||
|
|
||||||
string expectedValue1 = "ImpersonateMiddleware-UserName = " + Environment.ExpandEnvironmentVariables("%USERDOMAIN%") + "\\" + Environment.ExpandEnvironmentVariables("%USERNAME%");
|
string expectedValue1 = "ImpersonateMiddleware-UserName = " + Environment.ExpandEnvironmentVariables("%USERDOMAIN%") + "\\" + Environment.ExpandEnvironmentVariables("%USERNAME%");
|
||||||
|
|
@ -723,7 +723,7 @@ namespace AspNetCoreModule.Test
|
||||||
{
|
{
|
||||||
Assert.False(requestHeaders.ToUpper().Contains("MS-ASPNETCORE-WINAUTHTOKEN"));
|
Assert.False(requestHeaders.ToUpper().Contains("MS-ASPNETCORE-WINAUTHTOKEN"));
|
||||||
|
|
||||||
result = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("ImpersonateMiddleware"), HttpStatusCode.OK);
|
result = await GetResponse(testSite.AspNetCoreApp.GetUri("ImpersonateMiddleware"), HttpStatusCode.OK);
|
||||||
Assert.True(result.Contains("ImpersonateMiddleware-UserName = NoAuthentication"));
|
Assert.True(result.Contains("ImpersonateMiddleware-UserName = NoAuthentication"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -740,10 +740,10 @@ namespace AspNetCoreModule.Test
|
||||||
{
|
{
|
||||||
|
|
||||||
// allocating 1024,000 KB
|
// allocating 1024,000 KB
|
||||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetHttpUri("MemoryLeak1024000"), HttpStatusCode.OK);
|
await VerifyResponseStatus(testSite.AspNetCoreApp.GetUri("MemoryLeak1024000"), HttpStatusCode.OK);
|
||||||
|
|
||||||
// get backend process id
|
// get backend process id
|
||||||
string pocessIdBackendProcess = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string pocessIdBackendProcess = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
|
|
||||||
// get process id of IIS worker process (w3wp.exe)
|
// get process id of IIS worker process (w3wp.exe)
|
||||||
string userName = testSite.SiteName;
|
string userName = testSite.SiteName;
|
||||||
|
|
@ -777,7 +777,7 @@ namespace AspNetCoreModule.Test
|
||||||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "rapidFailsPerMinute", 100);
|
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "rapidFailsPerMinute", 100);
|
||||||
Thread.Sleep(3000);
|
Thread.Sleep(3000);
|
||||||
|
|
||||||
await VerifyResponseStatus(testSite.RootAppContext.GetHttpUri("small.htm"), HttpStatusCode.OK);
|
await VerifyResponseStatus(testSite.RootAppContext.GetUri("small.htm"), HttpStatusCode.OK);
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
int x = Convert.ToInt32(TestUtility.GetProcessWMIAttributeValue("w3wp.exe", "Handle", userName));
|
int x = Convert.ToInt32(TestUtility.GetProcessWMIAttributeValue("w3wp.exe", "Handle", userName));
|
||||||
|
|
||||||
|
|
@ -788,14 +788,14 @@ namespace AspNetCoreModule.Test
|
||||||
// check JitDebugger before continuing
|
// check JitDebugger before continuing
|
||||||
foundVSJit = TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
foundVSJit = TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||||
|
|
||||||
await VerifyResponseStatus(testSite.RootAppContext.GetHttpUri("small.htm"), HttpStatusCode.OK);
|
await VerifyResponseStatus(testSite.RootAppContext.GetUri("small.htm"), HttpStatusCode.OK);
|
||||||
Thread.Sleep(3000);
|
Thread.Sleep(3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
int y = Convert.ToInt32(TestUtility.GetProcessWMIAttributeValue("w3wp.exe", "Handle", userName));
|
int y = Convert.ToInt32(TestUtility.GetProcessWMIAttributeValue("w3wp.exe", "Handle", userName));
|
||||||
Assert.True(x == y && foundVSJit == false, "worker process is not recycled after 30 seconds");
|
Assert.True(x == y && foundVSJit == false, "worker process is not recycled after 30 seconds");
|
||||||
|
|
||||||
string backupPocessIdBackendProcess = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backupPocessIdBackendProcess = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
string newPocessIdBackendProcess = backupPocessIdBackendProcess;
|
string newPocessIdBackendProcess = backupPocessIdBackendProcess;
|
||||||
|
|
||||||
// Verify IIS recycling happens while there is memory leak
|
// Verify IIS recycling happens while there is memory leak
|
||||||
|
|
@ -805,9 +805,9 @@ namespace AspNetCoreModule.Test
|
||||||
foundVSJit = TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
foundVSJit = TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||||
|
|
||||||
// allocating 2048,000 KB
|
// allocating 2048,000 KB
|
||||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetHttpUri("MemoryLeak2048000"), HttpStatusCode.OK);
|
await VerifyResponseStatus(testSite.AspNetCoreApp.GetUri("MemoryLeak2048000"), HttpStatusCode.OK);
|
||||||
|
|
||||||
newPocessIdBackendProcess = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
newPocessIdBackendProcess = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
if (foundVSJit || backupPocessIdBackendProcess != newPocessIdBackendProcess)
|
if (foundVSJit || backupPocessIdBackendProcess != newPocessIdBackendProcess)
|
||||||
{
|
{
|
||||||
// worker process is recycled expectedly and backend process is recycled together
|
// worker process is recycled expectedly and backend process is recycled together
|
||||||
|
|
@ -834,7 +834,7 @@ namespace AspNetCoreModule.Test
|
||||||
z = Convert.ToInt32(TestUtility.GetProcessWMIAttributeValue("w3wp.exe", "Handle", userName));
|
z = Convert.ToInt32(TestUtility.GetProcessWMIAttributeValue("w3wp.exe", "Handle", userName));
|
||||||
Assert.True(x != z, "worker process is recycled");
|
Assert.True(x != z, "worker process is recycled");
|
||||||
|
|
||||||
newPocessIdBackendProcess = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
newPocessIdBackendProcess = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
Assert.True(backupPocessIdBackendProcess != newPocessIdBackendProcess, "backend process is recycled");
|
Assert.True(backupPocessIdBackendProcess != newPocessIdBackendProcess, "backend process is recycled");
|
||||||
}
|
}
|
||||||
testSite.AspNetCoreApp.RestoreFile("web.config");
|
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||||
|
|
@ -876,29 +876,29 @@ namespace AspNetCoreModule.Test
|
||||||
string result = string.Empty;
|
string result = string.Empty;
|
||||||
if (!useCompressionMiddleWare && !enableIISCompression)
|
if (!useCompressionMiddleWare && !enableIISCompression)
|
||||||
{
|
{
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
Assert.True(result.Contains("foohtm"), "verify response body");
|
Assert.True(result.Contains("foohtm"), "verify response body");
|
||||||
Assert.False(result.Contains("Content-Encoding"), "verify response header");
|
Assert.False(result.Contains("Content-Encoding"), "verify response header");
|
||||||
|
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri("pdir/bar.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri("pdir/bar.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
Assert.True(result.Contains("barhtm"), "verify response body");
|
Assert.True(result.Contains("barhtm"), "verify response body");
|
||||||
Assert.False(result.Contains("Content-Encoding"), "verify response header");
|
Assert.False(result.Contains("Content-Encoding"), "verify response header");
|
||||||
|
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri(), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri(), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
Assert.True(result.Contains("defaulthtm"), "verify response body");
|
Assert.True(result.Contains("defaulthtm"), "verify response body");
|
||||||
Assert.False(result.Contains("Content-Encoding"), "verify response header");
|
Assert.False(result.Contains("Content-Encoding"), "verify response header");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
Assert.True(result.Contains("foohtm"), "verify response body");
|
Assert.True(result.Contains("foohtm"), "verify response body");
|
||||||
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||||
|
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri("pdir/bar.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri("pdir/bar.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
Assert.True(result.Contains("barhtm"), "verify response body");
|
Assert.True(result.Contains("barhtm"), "verify response body");
|
||||||
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||||
|
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri(), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri(), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
Assert.True(result.Contains("defaulthtm"), "verify response body");
|
Assert.True(result.Contains("defaulthtm"), "verify response body");
|
||||||
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||||
}
|
}
|
||||||
|
|
@ -937,20 +937,20 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
string result = string.Empty;
|
string result = string.Empty;
|
||||||
|
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
string headerValue = GetHeaderValue(result, "MyCustomHeader");
|
string headerValue = GetHeaderValue(result, "MyCustomHeader");
|
||||||
Assert.True(result.Contains("foohtm"), "verify response body");
|
Assert.True(result.Contains("foohtm"), "verify response body");
|
||||||
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
|
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
string headerValue2 = GetHeaderValue(result, "MyCustomHeader");
|
string headerValue2 = GetHeaderValue(result, "MyCustomHeader");
|
||||||
Assert.True(result.Contains("foohtm"), "verify response body");
|
Assert.True(result.Contains("foohtm"), "verify response body");
|
||||||
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||||
Assert.Equal(headerValue, headerValue2);
|
Assert.Equal(headerValue, headerValue2);
|
||||||
|
|
||||||
Thread.Sleep(12000);
|
Thread.Sleep(12000);
|
||||||
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetHttpUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri("foo.htm"), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
Assert.True(result.Contains("foohtm"), "verify response body");
|
Assert.True(result.Contains("foohtm"), "verify response body");
|
||||||
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||||
string headerValue3 = GetHeaderValue(result, "MyCustomHeader");
|
string headerValue3 = GetHeaderValue(result, "MyCustomHeader");
|
||||||
|
|
@ -959,23 +959,184 @@ namespace AspNetCoreModule.Test
|
||||||
testSite.AspNetCoreApp.RestoreFile("web.config");
|
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task DoSendHTTPSRequestTest(IISConfigUtility.AppPoolBitness appPoolBitness)
|
||||||
|
{
|
||||||
|
using (var testSite = new TestWebSite(appPoolBitness, "DoSendHTTPSRequestTest"))
|
||||||
|
{
|
||||||
|
using (var iisConfig = new IISConfigUtility(ServerType.IIS))
|
||||||
|
{
|
||||||
|
string hostName = "";
|
||||||
|
string subjectName = "localhost";
|
||||||
|
string ipAddress = "*";
|
||||||
|
string hexIPAddress = "0x00";
|
||||||
|
int sslPort = 46300;
|
||||||
|
|
||||||
|
// Add https binding and get https uri information
|
||||||
|
iisConfig.AddBindingToSite(testSite.SiteName, ipAddress, sslPort, hostName, "https");
|
||||||
|
|
||||||
|
// Create a self signed certificate
|
||||||
|
string thumbPrint = iisConfig.CreateSelfSignedCertificate(subjectName);
|
||||||
|
|
||||||
|
// Export the self signed certificate to rootCA
|
||||||
|
iisConfig.ExportCertificateTo(thumbPrint, sslStoreTo:@"Cert:\LocalMachine\Root");
|
||||||
|
|
||||||
|
// Configure http.sys ssl certificate mapping to IP:Port endpoint with the newly created self signed certificage
|
||||||
|
iisConfig.SetSSLCertificate(sslPort, hexIPAddress, thumbPrint);
|
||||||
|
|
||||||
|
// Verify http request
|
||||||
|
string result = string.Empty;
|
||||||
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri(), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
|
Assert.True(result.Contains("Running"), "verify response body");
|
||||||
|
|
||||||
|
// Verify https request
|
||||||
|
Uri targetHttpsUri = testSite.AspNetCoreApp.GetUri(null, sslPort, protocol: "https");
|
||||||
|
result = await GetResponseAndHeaders(targetHttpsUri, new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.OK);
|
||||||
|
Assert.True(result.Contains("Running"), "verify response body");
|
||||||
|
|
||||||
|
// Remove the SSL Certificate mapping
|
||||||
|
iisConfig.RemoveSSLCertificate(sslPort, hexIPAddress);
|
||||||
|
|
||||||
|
// Remove the newly created self signed certificate
|
||||||
|
iisConfig.DeleteCertificate(thumbPrint);
|
||||||
|
|
||||||
|
// Remove the exported self signed certificate on rootCA
|
||||||
|
iisConfig.DeleteCertificate(thumbPrint, @"Cert:\LocalMachine\Root");
|
||||||
|
}
|
||||||
|
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task DoClientCertificateMappingTest(IISConfigUtility.AppPoolBitness appPoolBitness, bool useHTTPSMiddleWare)
|
||||||
|
{
|
||||||
|
using (var testSite = new TestWebSite(appPoolBitness, "DoClientCertificateMappingTest"))
|
||||||
|
{
|
||||||
|
using (var iisConfig = new IISConfigUtility(ServerType.IIS))
|
||||||
|
{
|
||||||
|
string hostName = "";
|
||||||
|
string rootCN = "ANCMTest" + testSite.PostFix;
|
||||||
|
string webServerCN = "localhost";
|
||||||
|
string kestrelServerCN = "localhost";
|
||||||
|
string clientCN = "ANCMClient-" + testSite.PostFix;
|
||||||
|
|
||||||
|
string ipAddress = "*";
|
||||||
|
string hexIPAddress = "0x00";
|
||||||
|
int sslPort = 46300;
|
||||||
|
|
||||||
|
// Add https binding and get https uri information
|
||||||
|
iisConfig.AddBindingToSite(testSite.SiteName, ipAddress, sslPort, hostName, "https");
|
||||||
|
|
||||||
|
// Create a root certificate
|
||||||
|
string thumbPrintForRoot = iisConfig.CreateSelfSignedCertificateWithMakeCert(rootCN);
|
||||||
|
|
||||||
|
// Create a certificate for web server setting its issuer with the root certificate subject name
|
||||||
|
string thumbPrintForWebServer = iisConfig.CreateSelfSignedCertificateWithMakeCert(webServerCN, rootCN, extendedKeyUsage: "1.3.6.1.5.5.7.3.1");
|
||||||
|
string thumbPrintForKestrel = null;
|
||||||
|
|
||||||
|
// Create a certificate for client authentication setting its issuer with the root certificate subject name
|
||||||
|
string thumbPrintForClientAuthentication = iisConfig.CreateSelfSignedCertificateWithMakeCert(clientCN, rootCN, extendedKeyUsage: "1.3.6.1.5.5.7.3.2");
|
||||||
|
|
||||||
|
// Configure http.sys ssl certificate mapping to IP:Port endpoint with the newly created self signed certificage
|
||||||
|
iisConfig.SetSSLCertificate(sslPort, hexIPAddress, thumbPrintForWebServer);
|
||||||
|
|
||||||
|
// Create a new local administrator user
|
||||||
|
string userName = "tempuser" + TestUtility.RandomString(5);
|
||||||
|
string password = "AncmTest123!";
|
||||||
|
string temp = TestUtility.RunPowershellScript("( Get-LocalUser -Name " + userName + " 2> $null ).Name");
|
||||||
|
if (temp == userName)
|
||||||
|
{
|
||||||
|
temp = TestUtility.RunPowershellScript("net localgroup administrators /Delete " + userName);
|
||||||
|
temp = TestUtility.RunPowershellScript("net user " + userName + " /Delete");
|
||||||
|
}
|
||||||
|
temp = TestUtility.RunPowershellScript("net user " + userName + " " + password + " /ADD");
|
||||||
|
temp = TestUtility.RunPowershellScript("net localgroup administrators /Add " + userName);
|
||||||
|
|
||||||
|
// Get public key of the client certificate and Configure OnetToOneClientCertificateMapping the public key and disable anonymous authentication and set SSL flags for Client certificate authentication
|
||||||
|
string publicKey = iisConfig.GetCertificatePublicKey(thumbPrintForClientAuthentication, @"Cert:\CurrentUser\My");
|
||||||
|
iisConfig.EnableOneToOneClientCertificateMapping(testSite.SiteName, ".\\" + userName, password, publicKey);
|
||||||
|
|
||||||
|
// Configure kestrel SSL test environment
|
||||||
|
if (useHTTPSMiddleWare)
|
||||||
|
{
|
||||||
|
// set startup class
|
||||||
|
string startupClass = "StartupHTTPS";
|
||||||
|
iisConfig.SetANCMConfig(
|
||||||
|
testSite.SiteName,
|
||||||
|
testSite.AspNetCoreApp.Name,
|
||||||
|
"environmentVariable",
|
||||||
|
new string[] { "ANCMTestStartupClassName", startupClass }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create a certificate for Kestrel web server and export to TestResources\testcert.pfx
|
||||||
|
// NOTE: directory name "TestResources", file name "testcert.pfx" and password "testPassword" should be matched to AspnetCoreModule.TestSites.Standard web application
|
||||||
|
thumbPrintForKestrel = iisConfig.CreateSelfSignedCertificateWithMakeCert(kestrelServerCN, rootCN, extendedKeyUsage: "1.3.6.1.5.5.7.3.1");
|
||||||
|
testSite.AspNetCoreApp.CreateDirectory("TestResources");
|
||||||
|
string pfxFilePath = Path.Combine(testSite.AspNetCoreApp.GetDirectoryPathWith("TestResources"), "testcert.pfx");
|
||||||
|
iisConfig.ExportCertificateTo(thumbPrintForKestrel, sslStoreFrom: "Cert:\\LocalMachine\\My", sslStoreTo: pfxFilePath, pfxPassword: "testPassword");
|
||||||
|
Assert.True(File.Exists(pfxFilePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify http request with using client certificate
|
||||||
|
Uri targetHttpsUri = testSite.AspNetCoreApp.GetUri(null, sslPort, protocol: "https");
|
||||||
|
string statusCode = TestUtility.RunPowershellScript("( invoke-webrequest " + targetHttpsUri.OriginalString + " -CertificateThumbprint " + thumbPrintForClientAuthentication + ").StatusCode");
|
||||||
|
Assert.Equal("200", statusCode);
|
||||||
|
|
||||||
|
// Verify https request with client certificate includes the certificate header "MS-ASPNETCORE-CLIENTCERT"
|
||||||
|
Uri targetHttpsUriForDumpRequestHeaders = testSite.AspNetCoreApp.GetUri("DumpRequestHeaders", sslPort, protocol: "https");
|
||||||
|
string outputRawContent = TestUtility.RunPowershellScript("( invoke-webrequest " + targetHttpsUriForDumpRequestHeaders.OriginalString + " -CertificateThumbprint " + thumbPrintForClientAuthentication + ").RawContent.ToString()");
|
||||||
|
string expectedHeaderName = "MS-ASPNETCORE-CLIENTCERT";
|
||||||
|
Assert.True(outputRawContent.Contains(expectedHeaderName));
|
||||||
|
|
||||||
|
// Get the value of MS-ASPNETCORE-CLIENTCERT request header again and verify it is matched to its configured public key
|
||||||
|
Uri targetHttpsUriForCLIENTCERTRequestHeader = testSite.AspNetCoreApp.GetUri("GetRequestHeaderValueMS-ASPNETCORE-CLIENTCERT", sslPort, protocol: "https");
|
||||||
|
outputRawContent = TestUtility.RunPowershellScript("( invoke-webrequest " + targetHttpsUriForCLIENTCERTRequestHeader.OriginalString + " -CertificateThumbprint " + thumbPrintForClientAuthentication + ").RawContent.ToString()");
|
||||||
|
Assert.True(outputRawContent.Contains(publicKey));
|
||||||
|
|
||||||
|
// Verify non-https request returns 403.4 error
|
||||||
|
string result = string.Empty;
|
||||||
|
result = await GetResponseAndHeaders(testSite.AspNetCoreApp.GetUri(), new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.Forbidden);
|
||||||
|
Assert.True(result.Contains("403.4"));
|
||||||
|
|
||||||
|
// Verify https request without using client certificate returns 403.7
|
||||||
|
result = await GetResponseAndHeaders(targetHttpsUri, new string[] { "Accept-Encoding", "gzip" }, HttpStatusCode.Forbidden);
|
||||||
|
Assert.True(result.Contains("403.7"));
|
||||||
|
|
||||||
|
// Clean up user
|
||||||
|
temp = TestUtility.RunPowershellScript("net localgroup administrators /Delete " + userName);
|
||||||
|
temp = TestUtility.RunPowershellScript("net user " + userName + " /Delete");
|
||||||
|
|
||||||
|
// Remove the SSL Certificate mapping
|
||||||
|
iisConfig.RemoveSSLCertificate(sslPort, hexIPAddress);
|
||||||
|
|
||||||
|
// Clean up certificates
|
||||||
|
iisConfig.DeleteCertificate(thumbPrintForRoot, @"Cert:\LocalMachine\Root");
|
||||||
|
iisConfig.DeleteCertificate(thumbPrintForWebServer, @"Cert:\LocalMachine\My");
|
||||||
|
if (useHTTPSMiddleWare)
|
||||||
|
{
|
||||||
|
iisConfig.DeleteCertificate(thumbPrintForKestrel, @"Cert:\LocalMachine\My");
|
||||||
|
}
|
||||||
|
iisConfig.DeleteCertificate(thumbPrintForClientAuthentication, @"Cert:\CurrentUser\My");
|
||||||
|
}
|
||||||
|
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task DoWebSocketTest(IISConfigUtility.AppPoolBitness appPoolBitness, string testData)
|
public static async Task DoWebSocketTest(IISConfigUtility.AppPoolBitness appPoolBitness, string testData)
|
||||||
{
|
{
|
||||||
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketTest"))
|
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketTest"))
|
||||||
{
|
{
|
||||||
DateTime startTime = DateTime.Now;
|
DateTime startTime = DateTime.Now;
|
||||||
|
|
||||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri(), "Running", HttpStatusCode.OK);
|
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri(), "Running", HttpStatusCode.OK);
|
||||||
|
|
||||||
// Get Process ID
|
// Get Process ID
|
||||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||||
|
|
||||||
// Verify WebSocket without setting subprotocol
|
// Verify WebSocket without setting subprotocol
|
||||||
await VerifyResponseBodyContain(testSite.WebSocketApp.GetHttpUri("echo.aspx"), new string[] { "Socket Open" }, HttpStatusCode.OK); // echo.aspx has hard coded path for the websocket server
|
await VerifyResponseBodyContain(testSite.WebSocketApp.GetUri("echo.aspx"), new string[] { "Socket Open" }, HttpStatusCode.OK); // echo.aspx has hard coded path for the websocket server
|
||||||
|
|
||||||
// Verify WebSocket subprotocol
|
// Verify WebSocket subprotocol
|
||||||
await VerifyResponseBodyContain(testSite.WebSocketApp.GetHttpUri("echoSubProtocol.aspx"), new string[] { "Socket Open", "mywebsocketsubprotocol" }, HttpStatusCode.OK); // echoSubProtocol.aspx has hard coded path for the websocket server
|
await VerifyResponseBodyContain(testSite.WebSocketApp.GetUri("echoSubProtocol.aspx"), new string[] { "Socket Open", "mywebsocketsubprotocol" }, HttpStatusCode.OK); // echoSubProtocol.aspx has hard coded path for the websocket server
|
||||||
|
|
||||||
// Verify process creation ANCM event log
|
// Verify process creation ANCM event log
|
||||||
Assert.True(TestUtility.RetryHelper((arg1, arg2) => VerifyANCMStartEvent(arg1, arg2), startTime, backendProcessId));
|
Assert.True(TestUtility.RetryHelper((arg1, arg2) => VerifyANCMStartEvent(arg1, arg2), startTime, backendProcessId));
|
||||||
|
|
@ -983,7 +1144,7 @@ namespace AspNetCoreModule.Test
|
||||||
// Verify websocket
|
// Verify websocket
|
||||||
using (WebSocketClientHelper websocketClient = new WebSocketClientHelper())
|
using (WebSocketClientHelper websocketClient = new WebSocketClientHelper())
|
||||||
{
|
{
|
||||||
var frameReturned = websocketClient.Connect(testSite.AspNetCoreApp.GetHttpUri("websocket"), true, true);
|
var frameReturned = websocketClient.Connect(testSite.AspNetCoreApp.GetUri("websocket"), true, true);
|
||||||
Assert.True(frameReturned.Content.Contains("Connection: Upgrade"));
|
Assert.True(frameReturned.Content.Contains("Connection: Upgrade"));
|
||||||
Assert.True(frameReturned.Content.Contains("HTTP/1.1 101 Switching Protocols"));
|
Assert.True(frameReturned.Content.Contains("HTTP/1.1 101 Switching Protocols"));
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|
@ -996,7 +1157,7 @@ namespace AspNetCoreModule.Test
|
||||||
}
|
}
|
||||||
|
|
||||||
// send a simple request again and verify the response body
|
// send a simple request again and verify the response body
|
||||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri(), "Running", HttpStatusCode.OK);
|
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri(), "Running", HttpStatusCode.OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1129,7 +1290,7 @@ namespace AspNetCoreModule.Test
|
||||||
|
|
||||||
private static async Task CheckChunkedAsync(HttpClient client, TestWebApplication webApp)
|
private static async Task CheckChunkedAsync(HttpClient client, TestWebApplication webApp)
|
||||||
{
|
{
|
||||||
var response = await client.GetAsync(webApp.GetHttpUri("chunked"));
|
var response = await client.GetAsync(webApp.GetUri("chunked"));
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -1256,14 +1417,14 @@ namespace AspNetCoreModule.Test
|
||||||
string responseStatus = "NotInitialized";
|
string responseStatus = "NotInitialized";
|
||||||
|
|
||||||
var httpClientHandler = new HttpClientHandler();
|
var httpClientHandler = new HttpClientHandler();
|
||||||
httpClientHandler.UseDefaultCredentials = true;
|
httpClientHandler.UseDefaultCredentials = true;
|
||||||
|
|
||||||
var httpClient = new HttpClient(httpClientHandler)
|
var httpClient = new HttpClient(httpClientHandler)
|
||||||
{
|
{
|
||||||
BaseAddress = uri,
|
BaseAddress = uri,
|
||||||
Timeout = TimeSpan.FromSeconds(timeout),
|
Timeout = TimeSpan.FromSeconds(timeout),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (requestHeaders != null)
|
if (requestHeaders != null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < requestHeaders.Length; i=i+2)
|
for (int i = 0; i < requestHeaders.Length; i=i+2)
|
||||||
|
|
@ -1293,7 +1454,7 @@ namespace AspNetCoreModule.Test
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
response = await TestUtility.RetryRequest(() =>
|
response = await TestUtility.RetryRequest(() =>
|
||||||
{
|
{
|
||||||
return httpClient.PostAsync(string.Empty, postHttpContent);
|
return httpClient.PostAsync(string.Empty, postHttpContent);
|
||||||
}, TestUtility.Logger, retryCount: numberOfRetryCount);
|
}, TestUtility.Logger, retryCount: numberOfRetryCount);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@
|
||||||
"Microsoft.Extensions.Logging.Console": "1.2.0-*",
|
"Microsoft.Extensions.Logging.Console": "1.2.0-*",
|
||||||
"Microsoft.Extensions.PlatformAbstractions": "1.2.0-*",
|
"Microsoft.Extensions.PlatformAbstractions": "1.2.0-*",
|
||||||
"Microsoft.Net.Http.Headers": "1.1.0-*",
|
"Microsoft.Net.Http.Headers": "1.1.0-*",
|
||||||
"xunit": "2.2.0-*"
|
"xunit": "2.2.0-*",
|
||||||
|
"System.Management.Automation.dll": "10.0.10586"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"net451": {
|
"net451": {
|
||||||
|
|
@ -28,7 +29,7 @@
|
||||||
"System.Net.Http.WebRequest": "",
|
"System.Net.Http.WebRequest": "",
|
||||||
"System.Runtime": "",
|
"System.Runtime": "",
|
||||||
"System.ServiceProcess": "",
|
"System.ServiceProcess": "",
|
||||||
"System.Xml": ""
|
"System.Xml": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,20 @@
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Https;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Net.Http.Server;
|
using Microsoft.Net.Http.Server;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace AspnetCoreModule.TestSites.Standard
|
namespace AspnetCoreModule.TestSites.Standard
|
||||||
{
|
{
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
|
private static X509Certificate2 _x509Certificate2;
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var config = new ConfigurationBuilder()
|
var config = new ConfigurationBuilder()
|
||||||
|
|
@ -22,7 +26,33 @@ namespace AspnetCoreModule.TestSites.Standard
|
||||||
IWebHostBuilder builder = null;
|
IWebHostBuilder builder = null;
|
||||||
if (!string.IsNullOrEmpty(startUpClassString))
|
if (!string.IsNullOrEmpty(startUpClassString))
|
||||||
{
|
{
|
||||||
if (startUpClassString == "StartupCompressionCaching")
|
if (startUpClassString == "StartupHTTPS")
|
||||||
|
{
|
||||||
|
// load .\testresources\testcert.pfx
|
||||||
|
string pfxPassword = "testPassword";
|
||||||
|
if (File.Exists(@".\TestResources\testcert.pfx"))
|
||||||
|
{
|
||||||
|
_x509Certificate2 = new X509Certificate2(@".\TestResources\testcert.pfx", pfxPassword);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception(@"Certificate file not found: .\TestResources\testcert.pfx of which password should " + pfxPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder = new WebHostBuilder()
|
||||||
|
.UseConfiguration(config)
|
||||||
|
.UseIISIntegration()
|
||||||
|
.UseKestrel(options =>
|
||||||
|
{
|
||||||
|
HttpsConnectionFilterOptions httpsoptions = new HttpsConnectionFilterOptions();
|
||||||
|
httpsoptions.ServerCertificate = _x509Certificate2;
|
||||||
|
httpsoptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
|
||||||
|
httpsoptions.CheckCertificateRevocation = false;
|
||||||
|
options.UseHttps(httpsoptions);
|
||||||
|
})
|
||||||
|
.UseStartup<Startup>();
|
||||||
|
}
|
||||||
|
else if (startUpClassString == "StartupCompressionCaching")
|
||||||
{
|
{
|
||||||
builder = new WebHostBuilder()
|
builder = new WebHostBuilder()
|
||||||
.UseConfiguration(config)
|
.UseConfiguration(config)
|
||||||
|
|
@ -111,8 +141,8 @@ namespace AspnetCoreModule.TestSites.Standard
|
||||||
}
|
}
|
||||||
|
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
host.Run();
|
host.Run();
|
||||||
|
|
||||||
if (Startup.SleeptimeWhileClosing != 0)
|
if (Startup.SleeptimeWhileClosing != 0)
|
||||||
{
|
{
|
||||||
Thread.Sleep(Startup.SleeptimeWhileClosing);
|
Thread.Sleep(Startup.SleeptimeWhileClosing);
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,16 @@
|
||||||
"anonymousAuthentication": true,
|
"anonymousAuthentication": true,
|
||||||
"iisExpress": {
|
"iisExpress": {
|
||||||
"applicationUrl": "http://localhost:39982/",
|
"applicationUrl": "http://localhost:39982/",
|
||||||
"sslPort": 0
|
"sslPort": 44375
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"IIS Express": {
|
"IIS Express": {
|
||||||
"commandName": "IISExpress",
|
"commandName": "IISExpress",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "https://localhost:44375/",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ANCMTestStartupClassName": "StartupCompression",
|
"ANCMTestStartupClassName": "StartupHTTPS",
|
||||||
"ASPNET_ENVIRONMENT": "HelloWorld"
|
"ASPNET_ENVIRONMENT": "HelloWorld"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,397 @@
|
||||||
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
<##############################################################################
|
||||||
|
Example
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Create a new root certificate on "Cert:\LocalMachine\My" and export it to "Cert:\LocalMachine\Root"
|
||||||
|
# FYI, you can do the same thing with one of the following commands:
|
||||||
|
# %sdxroot\tools\amd64\MakeCert.exe -r -pe -n "CN=ANCMTest_Root" -b 12/22/2013 -e 12/23/2020 -ss root -sr localmachine -len 2048 -a sha256
|
||||||
|
# $thumbPrint = (New-SelfSignedCertificate -DnsName "ANCMTest_Root", "ANCMTest_Roo3" -CertStoreLocation "cert:\LocalMachine\My").Thumbprint
|
||||||
|
###############################################################################
|
||||||
|
$rootSubject = "ANCMTest_Root"
|
||||||
|
$thumbPrint = .\certificate.ps1 -Command Create-SelfSignedCertificate -Subject $rootSubject
|
||||||
|
.\certificate.ps1 -Command Export-CertificateTo -TargetThumbPrint $thumbPrint -TargetSSLStore "Cert:\LocalMachine\My" -ExportToSSLStore "Cert:\LocalMachine\Root"
|
||||||
|
.\certificate.ps1 -Command Get-CertificateThumbPrint -Subject $rootSubject -TargetSSLStore "Cert:\LocalMachine\Root"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Create a new certificate setting issuer with the root certicate's subject name on "Cert:\LocalMachine\My" and export it to "Cert:\LocalMachine\Root"
|
||||||
|
# FYI, you can do the same thing with one of the following commands:
|
||||||
|
# %sdxroot\tools\amd64\MakeCert.exe -pe -n "CN=ANCMTestWebServer" -b 12/22/2013 -e 12/23/2020 -eku 1.3.6.1.5.5.7.3.1 -is root -ir localmachine -in $rootSubject -len 2048 -ss my -sr localmachine -a sha256
|
||||||
|
# %sdxroot\tools\amd64\MakeCert.exe -pe -n "CN=ANCMTest_Client" -eku 1.3.6.1.5.5.7.3.2 -is root -ir localmachine -in ANCMTest_Root -ss my -sr currentuser -len 2048 -a sha256
|
||||||
|
###############################################################################
|
||||||
|
$childSubject = "ANCMTest_Client"
|
||||||
|
$thumbPrint2 = .\certificate.ps1 -Command Create-SelfSignedCertificate -Subject $childSubject -IssuerName $rootSubject
|
||||||
|
("Result: $thumbPrint2")
|
||||||
|
.\certificate.ps1 -Command Export-CertificateTo -TargetThumbPrint $thumbPrint2 -TargetSSLStore "Cert:\LocalMachine\My" -ExportToSSLStore "Cert:\CurrentUser\My"
|
||||||
|
|
||||||
|
.\certificate.ps1 -Command Export-CertificateTo -TargetThumbPrint F97AB75DCF1C62547E4B5E7025D60001892A6A60 -ExportToSSLStore C:\gitroot\AspNetCoreModule\tools\test.pfx -PfxPassword test
|
||||||
|
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
.\certificate.ps1 -Command Delete-Certificate -TargetThumbPrint $thumbPrint2 -TargetSSLStore "Cert:\LocalMachine\My"
|
||||||
|
.\certificate.ps1 -Command Delete-Certificate -TargetThumbPrint $thumbPrint2 -TargetSSLStore "Cert:\CurrentUser\Root"
|
||||||
|
.\certificate.ps1 -Command Delete-Certificate -TargetThumbPrint $thumbPrint -TargetSSLStore "Cert:\LocalMachine\My"
|
||||||
|
.\certificate.ps1 -Command Delete-Certificate -TargetThumbPrint $thumbPrint -TargetSSLStore "Cert:\LocalMachine\Root"
|
||||||
|
|
||||||
|
###############################################################################>
|
||||||
|
|
||||||
|
|
||||||
|
Param(
|
||||||
|
[parameter(Mandatory=$true , Position=0)]
|
||||||
|
[ValidateSet("Create-SelfSignedCertificate",
|
||||||
|
"Delete-Certificate",
|
||||||
|
"Export-CertificateTo",
|
||||||
|
"Get-CertificateThumbPrint",
|
||||||
|
"Get-CertificatePublicKey")]
|
||||||
|
[string]
|
||||||
|
$Command,
|
||||||
|
|
||||||
|
[parameter()]
|
||||||
|
[string]
|
||||||
|
$Subject,
|
||||||
|
|
||||||
|
[parameter()]
|
||||||
|
[string]
|
||||||
|
$IssuerName,
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[string]
|
||||||
|
$FriendlyName = "",
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[string[]]
|
||||||
|
$AlternativeNames = "",
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[string]
|
||||||
|
$TargetSSLStore = "",
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[string]
|
||||||
|
$ExportToSSLStore = "",
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[string]
|
||||||
|
$PfxPassword = "",
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[string]
|
||||||
|
$TargetThumbPrint = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
function Create-SelfSignedCertificate($_subject, $_friendlyName, $_alternativeNames, $_issuerName) {
|
||||||
|
|
||||||
|
if (-not $_subject)
|
||||||
|
{
|
||||||
|
return ("Error!!! _subject is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# $_issuerName should be set with the value subject and its certificate path will be root path
|
||||||
|
if (-not $_issuerName)
|
||||||
|
{
|
||||||
|
$_issuerName = $_subject
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create $subjectDn and $issuerDn
|
||||||
|
$subjectDn = new-object -com "X509Enrollment.CX500DistinguishedName"
|
||||||
|
$subjectDn.Encode( "CN=" + $_subject, $subjectDn.X500NameFlags.X500NameFlags.XCN_CERT_NAME_STR_NONE)
|
||||||
|
$issuerDn = new-object -com "X509Enrollment.CX500DistinguishedName"
|
||||||
|
$issuerDn.Encode("CN=" + $_issuerName, $subjectDn.X500NameFlags.X500NameFlags.XCN_CERT_NAME_STR_NONE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create a new Private Key
|
||||||
|
$key = new-object -com "X509Enrollment.CX509PrivateKey"
|
||||||
|
$key.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider"
|
||||||
|
# XCN_AT_SIGNATURE, The key can be used for signing
|
||||||
|
$key.KeySpec = 2
|
||||||
|
$key.Length = 2048
|
||||||
|
# MachineContext 0: Current User, 1: Local Machine
|
||||||
|
$key.MachineContext = 1
|
||||||
|
$key.Create()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create a cert object with the newly created private key
|
||||||
|
$cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate"
|
||||||
|
$cert.InitializeFromPrivateKey(2, $key, "")
|
||||||
|
$cert.Subject = $subjectDn
|
||||||
|
$cert.Issuer = $issuerDn
|
||||||
|
$cert.NotBefore = (get-date).AddMinutes(-10)
|
||||||
|
$cert.NotAfter = $cert.NotBefore.AddYears(2)
|
||||||
|
|
||||||
|
#Use Sha256
|
||||||
|
$hashAlgorithm = New-Object -ComObject X509Enrollment.CObjectId
|
||||||
|
$hashAlgorithm.InitializeFromAlgorithmName(1,0,0,"SHA256")
|
||||||
|
$cert.HashAlgorithm = $hashAlgorithm
|
||||||
|
|
||||||
|
#
|
||||||
|
# Key usage should be set for non-root certificate
|
||||||
|
if ($_issuerName -ne $_subject)
|
||||||
|
{
|
||||||
|
#
|
||||||
|
# Extended key usage
|
||||||
|
$clientAuthOid = New-Object -ComObject "X509Enrollment.CObjectId"
|
||||||
|
$clientAuthOid.InitializeFromValue("1.3.6.1.5.5.7.3.2")
|
||||||
|
$serverAuthOid = new-object -com "X509Enrollment.CObjectId"
|
||||||
|
$serverAuthOid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
|
||||||
|
$ekuOids = new-object -com "X509Enrollment.CObjectIds.1"
|
||||||
|
$ekuOids.add($clientAuthOid)
|
||||||
|
$ekuOids.add($serverAuthOid)
|
||||||
|
$ekuExt = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage"
|
||||||
|
$ekuExt.InitializeEncode($ekuOids)
|
||||||
|
$cert.X509Extensions.Add($ekuext)
|
||||||
|
|
||||||
|
#
|
||||||
|
#Set Key usage
|
||||||
|
$keyUsage = New-Object -com "X509Enrollment.cx509extensionkeyusage"
|
||||||
|
# XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE
|
||||||
|
$flags = 0x20
|
||||||
|
# XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE
|
||||||
|
$flags = $flags -bor 0x80
|
||||||
|
$keyUsage.InitializeEncode($flags)
|
||||||
|
$cert.X509Extensions.Add($keyUsage)
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Subject alternative names
|
||||||
|
if ($_alternativeNames -ne $null) {
|
||||||
|
$names = new-object -com "X509Enrollment.CAlternativeNames"
|
||||||
|
$altNames = new-object -com "X509Enrollment.CX509ExtensionAlternativeNames"
|
||||||
|
foreach ($n in $_alternativeNames) {
|
||||||
|
$name = new-object -com "X509Enrollment.CAlternativeName"
|
||||||
|
# Dns Alternative Name
|
||||||
|
$name.InitializeFromString(3, $n)
|
||||||
|
$names.Add($name)
|
||||||
|
}
|
||||||
|
$altNames.InitializeEncode($names)
|
||||||
|
$cert.X509Extensions.Add($altNames)
|
||||||
|
}
|
||||||
|
|
||||||
|
$cert.Encode()
|
||||||
|
|
||||||
|
#$locator = $(New-Object "System.Guid").ToString()
|
||||||
|
$locator = [guid]::NewGuid().ToString()
|
||||||
|
$enrollment = new-object -com "X509Enrollment.CX509Enrollment"
|
||||||
|
$enrollment.CertificateFriendlyName = $locator
|
||||||
|
$enrollment.InitializeFromRequest($cert)
|
||||||
|
$certdata = $enrollment.CreateRequest(0)
|
||||||
|
$enrollment.InstallResponse(2, $certdata, 0, "")
|
||||||
|
|
||||||
|
# Wait for certificate to be populated
|
||||||
|
$end = $(Get-Date).AddSeconds(1)
|
||||||
|
do {
|
||||||
|
$Certificates = Get-ChildItem Cert:\LocalMachine\My
|
||||||
|
foreach ($item in $Certificates)
|
||||||
|
{
|
||||||
|
if ($item.FriendlyName -eq $locator)
|
||||||
|
{
|
||||||
|
$CACertificate = $item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ($CACertificate -eq $null -and $(Get-Date) -lt $end)
|
||||||
|
|
||||||
|
$thumbPrint = ""
|
||||||
|
if ($CACertificate -and $CACertificate.Thumbprint)
|
||||||
|
{
|
||||||
|
$thumbPrint = $CACertificate.Thumbprint.Trim()
|
||||||
|
}
|
||||||
|
return $thumbPrint
|
||||||
|
}
|
||||||
|
|
||||||
|
function Delete-Certificate($_targetThumbPrint, $_targetSSLStore = $TargetSSLStore) {
|
||||||
|
|
||||||
|
if (-not $_targetThumbPrint)
|
||||||
|
{
|
||||||
|
return ("Error!!! _targetThumbPrint is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path "$_targetSSLStore\$_targetThumbPrint")
|
||||||
|
{
|
||||||
|
Remove-Item "$_targetSSLStore\$_targetThumbPrint" -Force -Confirm:$false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path "$_targetSSLStore\$_targetThumbPrint")
|
||||||
|
{
|
||||||
|
return ("Error!!! Failed to delete a certificate of $_targetThumbPrint")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Export-CertificateTo($_targetThumbPrint, $_exportToSSLStore, $_password)
|
||||||
|
{
|
||||||
|
if (-not $_targetThumbPrint)
|
||||||
|
{
|
||||||
|
return ("Error!!! _targetThumbPrint is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path "$TargetSSLStore\$_targetThumbPrint"))
|
||||||
|
{
|
||||||
|
return ("Error!!! Export failed. Can't find target certificate: $TargetSSLStore\$_targetThumbPrint")
|
||||||
|
}
|
||||||
|
|
||||||
|
$cert = Get-Item "$TargetSSLStore\$_targetThumbPrint"
|
||||||
|
$tempExportFile = "$env:temp\_tempCertificate.cer"
|
||||||
|
if (Test-Path $tempExportFile)
|
||||||
|
{
|
||||||
|
Remove-Item $tempExportFile -Force -Confirm:$false
|
||||||
|
}
|
||||||
|
|
||||||
|
# if _exportToSSLStore points to a .pfx file
|
||||||
|
if ($exportToSSLStore.ToLower().EndsWith(".pfx"))
|
||||||
|
{
|
||||||
|
if (-not $_password)
|
||||||
|
{
|
||||||
|
return ("Error!!! _password is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
$securedPassword = ConvertTo-SecureString -String $_password -Force –AsPlainText
|
||||||
|
$exportedPfxFile = Export-PfxCertificate -FilePath $_exportToSSLStore -Cert $TargetSSLStore\$_targetThumbPrint -Password $securedPassword
|
||||||
|
if ( ($exportedPfxFile -ne $null) -and (Test-Path $exportedPfxFile.FullName) )
|
||||||
|
{
|
||||||
|
# Succeeded to export to .pfx file
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ("Error!!! Can't export $TargetSSLStore\$_targetThumbPrint to $tempExportFile")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-Certificate -Cert $cert -FilePath $tempExportFile | Out-Null
|
||||||
|
if (-not (Test-Path $tempExportFile))
|
||||||
|
{
|
||||||
|
return ("Error!!! Can't export $TargetSSLStore\$_targetThumbPrint to $tempExportFile")
|
||||||
|
}
|
||||||
|
|
||||||
|
# clean up destination SSL store
|
||||||
|
Delete-Certificate $_targetThumbPrint $_exportToSSLStore
|
||||||
|
if (Test-Path "$_exportToSSLStore\$_targetThumbPrint")
|
||||||
|
{
|
||||||
|
return ("Error!!! Can't delete already existing one $_exportToSSLStore\$_targetThumbPrint")
|
||||||
|
}
|
||||||
|
|
||||||
|
Import-Certificate -CertStoreLocation $_exportToSSLStore -FilePath $tempExportFile | Out-Null
|
||||||
|
if (-not (Test-Path "$_exportToSSLStore\$_targetThumbPrint"))
|
||||||
|
{
|
||||||
|
return ("Error!!! Can't copy $TargetSSLStore\$_targetThumbPrint to $_exportToSSLStore")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-CertificateThumbPrint($_subject, $_issuerName, $_targetSSLStore)
|
||||||
|
{
|
||||||
|
if (-not $_subject)
|
||||||
|
{
|
||||||
|
return ("Error!!! _subject is required")
|
||||||
|
}
|
||||||
|
if (-not $_targetSSLStore)
|
||||||
|
{
|
||||||
|
return ("Error!!! _targetSSLStore is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path "$_targetSSLStore"))
|
||||||
|
{
|
||||||
|
return ("Error!!! Can't find target store")
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetCertificate = $null
|
||||||
|
|
||||||
|
$Certificates = Get-ChildItem $_targetSSLStore
|
||||||
|
foreach ($item in $Certificates)
|
||||||
|
{
|
||||||
|
$findItem = $false
|
||||||
|
# check subject name first
|
||||||
|
if ($item.Subject.ToLower() -eq "CN=$_subject".ToLower())
|
||||||
|
{
|
||||||
|
$findItem = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
# check issuerName as well
|
||||||
|
if ($_issuerName -and $item.Issuer.ToLower() -ne "CN=$_issuerName".ToLower())
|
||||||
|
{
|
||||||
|
$findItem = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($findItem)
|
||||||
|
{
|
||||||
|
$targetCertificate = $item
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = ""
|
||||||
|
if ($targetCertificate)
|
||||||
|
{
|
||||||
|
$result = $targetCertificate.Thumbprint
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
("Error!!! Can't find target certificate")
|
||||||
|
}
|
||||||
|
return $result
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-CertificatePublicKey($_targetThumbPrint)
|
||||||
|
{
|
||||||
|
if (-not $_targetThumbPrint)
|
||||||
|
{
|
||||||
|
return ("Error!!! _targetThumbPrint is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path "$TargetSSLStore\$_targetThumbPrint"))
|
||||||
|
{
|
||||||
|
return ("Error!!! Can't find target certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
$cert = Get-Item "$TargetSSLStore\$_targetThumbPrint"
|
||||||
|
$byteArray = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
|
||||||
|
$publicKey = [System.Convert]::ToBase64String($byteArray).Trim()
|
||||||
|
|
||||||
|
return $publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
# Error handling and initializing default values
|
||||||
|
if (-not $TargetSSLStore)
|
||||||
|
{
|
||||||
|
$TargetSSLStore = "Cert:\LocalMachine\My"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($Command -eq "Create-SelfSignedCertificate")
|
||||||
|
{
|
||||||
|
return ("Error!!! Create-SelfSignedCertificate should use default value for -TargetSSLStore if -Issuer is not provided")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $ExportToSSLStore)
|
||||||
|
{
|
||||||
|
$ExportToSSLStore = "Cert:\LocalMachine\Root"
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($Command)
|
||||||
|
{
|
||||||
|
"Create-SelfSignedCertificate"
|
||||||
|
{
|
||||||
|
return Create-SelfSignedCertificate $Subject $FriendlyName $AlternativeNames $IssuerName
|
||||||
|
}
|
||||||
|
"Delete-Certificate"
|
||||||
|
{
|
||||||
|
return Delete-Certificate $TargetThumbPrint
|
||||||
|
}
|
||||||
|
"Export-CertificateTo"
|
||||||
|
{
|
||||||
|
return Export-CertificateTo $TargetThumbPrint $ExportToSSLStore $PfxPassword
|
||||||
|
}
|
||||||
|
"Get-CertificateThumbPrint"
|
||||||
|
{
|
||||||
|
return Get-CertificateThumbPrint $Subject $IssuerName $TargetSSLStore
|
||||||
|
}
|
||||||
|
"Get-CertificatePublicKey"
|
||||||
|
{
|
||||||
|
return Get-CertificatePublicKey $TargetThumbPrint
|
||||||
|
}
|
||||||
|
default
|
||||||
|
{
|
||||||
|
throw "Unknown command"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,394 @@
|
||||||
|
# Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Example
|
||||||
|
# $result = .\httpsys.ps1 -Command Get-SslBinding -IpAddress "0x00" -Port 46300
|
||||||
|
# .\httpsys.ps1 -Command Add-SslBinding -IpAddress "0x00" -Port 46300 –Thumbprint $result.CertificateHash
|
||||||
|
# .\httpsys.ps1 -Command Delete-SslBinding -IpAddress "0x00" -Port 46300
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
Param (
|
||||||
|
[parameter(Mandatory=$true , Position=0)]
|
||||||
|
[ValidateSet("Add-SslBinding",
|
||||||
|
"Delete-SslBinding",
|
||||||
|
"Get-SslBinding")]
|
||||||
|
[string]
|
||||||
|
$Command,
|
||||||
|
|
||||||
|
[parameter()]
|
||||||
|
[string]
|
||||||
|
$IpAddress,
|
||||||
|
|
||||||
|
[parameter()]
|
||||||
|
[string]
|
||||||
|
$Port,
|
||||||
|
|
||||||
|
[parameter()]
|
||||||
|
[string]
|
||||||
|
$Thumbprint,
|
||||||
|
|
||||||
|
[parameter()]
|
||||||
|
[string]
|
||||||
|
$TargetSSLStore,
|
||||||
|
|
||||||
|
[parameter()]
|
||||||
|
[string]
|
||||||
|
$AppId,
|
||||||
|
|
||||||
|
[parameter()]
|
||||||
|
[System.Net.IPEndPoint]
|
||||||
|
$IpEndPoint
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# adjust parameter variables
|
||||||
|
if (-not $IpEndPoint)
|
||||||
|
{
|
||||||
|
if ($IpAddress -and $Port)
|
||||||
|
{
|
||||||
|
$IpEndPoint = New-Object "System.Net.IPEndPoint" -ArgumentList $IpAddress,$Port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $TargetSSLStore)
|
||||||
|
{
|
||||||
|
$TargetSSLStore = "Cert:\LocalMachine\My"
|
||||||
|
}
|
||||||
|
|
||||||
|
$StoreName = ($TargetSSLStore.Split("\") | Select-Object -Last 1).Trim()
|
||||||
|
|
||||||
|
$Certificate = Get-Item "$TargetSSLStore\$Thumbprint"
|
||||||
|
|
||||||
|
if (-not $AppId)
|
||||||
|
{
|
||||||
|
# Assign a random GUID for $AppId
|
||||||
|
$AppId = [guid]::NewGuid()
|
||||||
|
}
|
||||||
|
|
||||||
|
$cs = '
|
||||||
|
namespace Microsoft.IIS.Administration.Setup {
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Net;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Text;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
public class Http {
|
||||||
|
public const int HTTP_INITIALIZE_CONFIG = 2;
|
||||||
|
public const int HTTP_SERVICE_CONFIG_SSLCERT_INFO = 1;
|
||||||
|
|
||||||
|
[DllImport("httpapi.dll", CharSet = CharSet.Auto, PreserveSig = true)]
|
||||||
|
public static extern uint HttpDeleteServiceConfiguration(IntPtr ServiceHandle, int ConfigId, ref HTTP_SERVICE_CONFIG_SSL_SET pConfigInformation, int ConfigInformationLength, IntPtr pOverlapped);
|
||||||
|
|
||||||
|
[DllImport("httpapi.dll", CharSet = CharSet.Auto, PreserveSig = true)]
|
||||||
|
public static extern uint HttpInitialize(HTTPAPI_VERSION version, uint flags, IntPtr pReserved);
|
||||||
|
|
||||||
|
[DllImport("httpapi.dll", EntryPoint = "HttpQueryServiceConfiguration",
|
||||||
|
CharSet = CharSet.Unicode, ExactSpelling = true,
|
||||||
|
CallingConvention = CallingConvention.StdCall)]
|
||||||
|
public static extern uint HttpQueryServiceConfiguration(
|
||||||
|
IntPtr serviceHandle,
|
||||||
|
HTTP_SERVICE_CONFIG_ID configID,
|
||||||
|
ref HTTP_SERVICE_CONFIG_SSL_QUERY pInputConfigInfo,
|
||||||
|
UInt32 InputConfigInfoLength,
|
||||||
|
IntPtr pOutputConfigInfo,
|
||||||
|
UInt32 OutputConfigInfoLength,
|
||||||
|
[In, Out] ref UInt32 pReturnLength,
|
||||||
|
IntPtr pOverlapped
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("httpapi.dll", CharSet = CharSet.Auto, PreserveSig = true)]
|
||||||
|
public static extern uint HttpSetServiceConfiguration(IntPtr ServiceHandle, int ConfigId, ref HTTP_SERVICE_CONFIG_SSL_SET pConfigInformation, int ConfigInformationLength, IntPtr pOverlapped);
|
||||||
|
|
||||||
|
[DllImport("httpapi.dll", CharSet = CharSet.Auto, PreserveSig = true)]
|
||||||
|
public static extern uint HttpTerminate(uint flags, IntPtr pReserved);
|
||||||
|
|
||||||
|
public static HTTP_SERVICE_CONFIG_SSL_SET MarshalConfigSslSet(IntPtr ptr) {
|
||||||
|
return (HTTP_SERVICE_CONFIG_SSL_SET)Marshal.PtrToStructure(ptr, typeof(HTTP_SERVICE_CONFIG_SSL_SET));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum HTTP_SERVICE_CONFIG_ID {
|
||||||
|
HttpServiceConfigIPListenList,
|
||||||
|
HttpServiceConfigSSLCertInfo,
|
||||||
|
HttpServiceConfigUrlAclInfo,
|
||||||
|
HttpServiceConfigMax
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum HTTP_SERVICE_CONFIG_QUERY_TYPE {
|
||||||
|
HttpServiceConfigQueryExact,
|
||||||
|
HttpServiceConfigQueryNext,
|
||||||
|
HttpServiceConfigQueryMax
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct HTTPAPI_VERSION {
|
||||||
|
public ushort HttpApiMajorVersion;
|
||||||
|
public ushort HttpApiMinorVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||||
|
public struct HTTP_SERVICE_CONFIG_SSL_KEY {
|
||||||
|
public IntPtr pIpPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||||
|
public struct HTTP_SERVICE_CONFIG_SSL_QUERY {
|
||||||
|
public HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc;
|
||||||
|
public IntPtr KeyDesc;
|
||||||
|
public Int32 dwToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct HTTP_SERVICE_CONFIG_SSL_SET {
|
||||||
|
public IntPtr KeyDesc;
|
||||||
|
public uint SslHashLength;
|
||||||
|
public IntPtr pSslHash;
|
||||||
|
public Guid AppId;
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string pSslCertStoreName;
|
||||||
|
public int DefaultCertCheckMode;
|
||||||
|
public int DefaultRevocationFreshnessTime;
|
||||||
|
public int DefaultRecovationUrlRetrievalTimeout;
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string pDefaultSslCtlIdentifier;
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string pDefaultSslCtlStoreName;
|
||||||
|
public int DefaultFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'
|
||||||
|
|
||||||
|
$SUCCESS = 0
|
||||||
|
function InitializeInterop() {
|
||||||
|
try {
|
||||||
|
[Microsoft.IIS.Administration.Setup.Http] | Out-Null
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Add-Type $cs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetIpEndpointBytes($_ipEndpoint) {
|
||||||
|
$socketAddress = $_ipEndpoint.Serialize()
|
||||||
|
$ipBytes = [System.Array]::CreateInstance([System.Byte], $socketAddress.Size)
|
||||||
|
for ($i = 0; $i -lt $socketAddress.Size; $i++) {
|
||||||
|
$ipBytes[$i] = $socketAddress[$i]
|
||||||
|
}
|
||||||
|
return $ipBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetBindingInfo($sslConfig) {
|
||||||
|
$hash = [System.Array]::CreateInstance([System.Byte], [int]($sslConfig.SslHashLength))
|
||||||
|
[System.Runtime.InteropServices.Marshal]::Copy($sslConfig.pSslHash, $hash, 0, $sslConfig.SslHashLength)
|
||||||
|
|
||||||
|
$socketAddressLength = 16
|
||||||
|
$sa = [System.Array]::CreateInstance([System.Byte], $socketAddressLength)
|
||||||
|
[System.Runtime.InteropServices.Marshal]::Copy($sslConfig.KeyDesc, $sa, 0, $socketAddressLength)
|
||||||
|
$socketAddress = New-Object "System.Net.SocketAddress" -ArgumentList ([System.Net.Sockets.AddressFamily]::InterNetwork, $socketAddressLength)
|
||||||
|
for ($i = 0; $i -lt $sa.Length; $i++) {
|
||||||
|
$socketAddress[$i] = $sa[$i]
|
||||||
|
}
|
||||||
|
|
||||||
|
$ep = New-Object "System.Net.IPEndPoint" -ArgumentList ([ipaddress]::Any, 0)
|
||||||
|
$endpoint = [System.Net.IPEndPoint]$ep.Create($socketAddress)
|
||||||
|
|
||||||
|
$ret = @{}
|
||||||
|
$ret.CertificateHash = [System.BitConverter]::ToString($hash).Replace("-", "")
|
||||||
|
$ret.AppId = $sslConfig.AppId
|
||||||
|
$ret.IpEndpoint = $endpoint
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function InitializeHttpSys() {
|
||||||
|
$v = New-Object "Microsoft.IIS.Administration.Setup.HTTPAPI_VERSION"
|
||||||
|
$V.HttpApiMajorVersion = 1
|
||||||
|
$v.HttpApiMinorVersion = 0
|
||||||
|
|
||||||
|
$result = [Microsoft.IIS.Administration.Setup.Http]::HttpInitialize($v, [Microsoft.IIS.Administration.Setup.Http]::HTTP_INITIALIZE_CONFIG, [System.IntPtr]::Zero)
|
||||||
|
|
||||||
|
if ($result -ne $SUCCESS) {
|
||||||
|
Write-Warning "Error initializing Http API"
|
||||||
|
throw [System.ComponentModel.Win32Exception] $([System.int32]$result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result
|
||||||
|
}
|
||||||
|
|
||||||
|
function TerminateHttpSys() {
|
||||||
|
return [Microsoft.IIS.Administration.Setup.Http]::HttpTerminate([Microsoft.IIS.Administration.Setup.Http]::HTTP_INITIALIZE_CONFIG, [System.IntPtr]::Zero)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-SslBinding($_ipEndpoint, $_certificate, $_appId) {
|
||||||
|
if ($_ipEndpoint -eq $null) {
|
||||||
|
throw "Ip Endpoint required."
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_certificate -eq $null) {
|
||||||
|
throw "Certificate required."
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($appId -eq $null) {
|
||||||
|
throw "App id required."
|
||||||
|
}
|
||||||
|
|
||||||
|
<# FYI, [System.Guid]::Parse() is not supported in lower version of powershell
|
||||||
|
if (-not($_appId -is [System.Guid])) {
|
||||||
|
$_appId = [System.Guid]::Parse($_appId)
|
||||||
|
}
|
||||||
|
#>
|
||||||
|
|
||||||
|
setSslConfiguration $_ipEndpoint $_certificate $_appId
|
||||||
|
}
|
||||||
|
|
||||||
|
function Delete-SslBinding($_ipEndpoint) {
|
||||||
|
|
||||||
|
if ($_ipEndpoint -eq $null) {
|
||||||
|
throw "Ip Endpoint required."
|
||||||
|
}
|
||||||
|
|
||||||
|
setSslConfiguration $_ipEndpoint $null $([System.Guid]::Empty)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-SslBinding($_ipEndpoint) {
|
||||||
|
|
||||||
|
if ($_ipEndpoint -eq $null) {
|
||||||
|
throw "Ip Endpoint required."
|
||||||
|
}
|
||||||
|
|
||||||
|
$bufferSize = 4096
|
||||||
|
try {
|
||||||
|
InitializeHttpSys| Out-Null
|
||||||
|
|
||||||
|
$ipBytes = [System.Byte[]]$(GetIpEndpointBytes($_ipEndpoint))
|
||||||
|
$hIp = [System.Runtime.InteropServices.GCHandle]::Alloc($ipBytes, [System.Runtime.InteropServices.GCHandleType]::Pinned)
|
||||||
|
$pIp = $hIp.AddrOfPinnedObject()
|
||||||
|
|
||||||
|
$queryParam = New-Object "Microsoft.IIS.Administration.Setup.HTTP_SERVICE_CONFIG_SSL_QUERY"
|
||||||
|
$queryParam.QueryDesc = [Microsoft.IIS.Administration.Setup.HTTP_SERVICE_CONFIG_QUERY_TYPE]::HttpServiceConfigQueryExact
|
||||||
|
$queryParam.dwToken = 0
|
||||||
|
$queryParam.KeyDesc = $pIp
|
||||||
|
|
||||||
|
$returnLen = 0
|
||||||
|
$pReturnSet = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($bufferSize)
|
||||||
|
|
||||||
|
$result = [Microsoft.IIS.Administration.Setup.Http]::HttpQueryServiceConfiguration(
|
||||||
|
[System.IntPtr]::Zero,
|
||||||
|
[Microsoft.IIS.Administration.Setup.HTTP_SERVICE_CONFIG_ID]::HttpServiceConfigSSLCertInfo,
|
||||||
|
[ref] $queryParam,
|
||||||
|
[uint32]([System.Runtime.InteropServices.Marshal]::SizeOf($queryParam)),
|
||||||
|
$pReturnSet,
|
||||||
|
$bufferSize,
|
||||||
|
[ref] $returnLen,
|
||||||
|
[System.IntPtr]::Zero)
|
||||||
|
|
||||||
|
if ($result -eq 2) {
|
||||||
|
# File not found
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
if ($result -ne $SUCCESS) {
|
||||||
|
Write-Warning "Error reading Ssl Cert Configuration"
|
||||||
|
throw [System.ComponentModel.Win32Exception] $([System.int32]$result)
|
||||||
|
}
|
||||||
|
$sslConfig = [Microsoft.IIS.Administration.Setup.Http]::MarshalConfigSslSet($pReturnSet)
|
||||||
|
return GetBindingInfo $sslConfig
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ($hIp -ne $null) {
|
||||||
|
$hIp.Free()
|
||||||
|
$hIp = $null
|
||||||
|
}
|
||||||
|
if ($pReturnSet -ne [System.IntPtr]::Zero) {
|
||||||
|
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($pReturnSet)
|
||||||
|
$pReturnSet = [System.IntPtr]::Zero
|
||||||
|
}
|
||||||
|
TerminateHttpSys | Out-Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSslConfiguration($_ipEndpoint, $_certificate, $_appId) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
InitializeHttpSys| Out-Null
|
||||||
|
|
||||||
|
$sslSet = New-Object "Microsoft.IIS.Administration.Setup.HTTP_SERVICE_CONFIG_SSL_SET"
|
||||||
|
$sslSetSize = [System.Runtime.InteropServices.Marshal]::SizeOf($sslSet)
|
||||||
|
|
||||||
|
$ipBytes = [System.Byte[]]$(GetIpEndpointBytes($_ipEndpoint))
|
||||||
|
$hIp = [System.Runtime.InteropServices.GCHandle]::Alloc($ipBytes, [System.Runtime.InteropServices.GCHandleType]::Pinned)
|
||||||
|
$pIp = $hIp.AddrOfPinnedObject()
|
||||||
|
|
||||||
|
$sslSet.KeyDesc = $pIp # IntPtr
|
||||||
|
$sslSet.SslHashLength = 0
|
||||||
|
$sslSet.pSslHash = [System.IntPtr]::Zero
|
||||||
|
$sslSet.pSslCertStoreName = [System.IntPtr]::Zero
|
||||||
|
$sslSet.AppId = $_appId
|
||||||
|
|
||||||
|
if ($_certificate -ne $null) {
|
||||||
|
# Create binding
|
||||||
|
|
||||||
|
$certBytes = $_certificate.GetCertHash()
|
||||||
|
$hCertBytes = [System.Runtime.InteropServices.GCHandle]::Alloc($certBytes, [System.Runtime.InteropServices.GCHandleType]::Pinned)
|
||||||
|
$pCertBytes = $hCertBytes.AddrOfPinnedObject()
|
||||||
|
|
||||||
|
$sslSet.SslHashLength = 20
|
||||||
|
$sslSet.pSslHash = $pCertBytes
|
||||||
|
$sslSet.pSslCertStoreName = $StoreName
|
||||||
|
|
||||||
|
$result = [Microsoft.IIS.Administration.Setup.Http]::HttpSetServiceConfiguration([System.IntPtr]::Zero,
|
||||||
|
[Microsoft.IIS.Administration.Setup.Http]::HTTP_SERVICE_CONFIG_SSLCERT_INFO,
|
||||||
|
[ref]$sslSet,
|
||||||
|
$sslSetSize,
|
||||||
|
[System.IntPtr]::Zero)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#Delete binding
|
||||||
|
$result = [Microsoft.IIS.Administration.Setup.Http]::HttpDeleteServiceConfiguration([System.IntPtr]::Zero,
|
||||||
|
[Microsoft.IIS.Administration.Setup.Http]::HTTP_SERVICE_CONFIG_SSLCERT_INFO,
|
||||||
|
[ref]$sslSet,
|
||||||
|
$sslSetSize,
|
||||||
|
[System.IntPtr]::Zero)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result -ne $SUCCESS) {
|
||||||
|
Write-Warning "Error setting Ssl Cert Configuration"
|
||||||
|
throw [System.ComponentModel.Win32Exception] $([System.int32]$result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ($hIp -ne $null) {
|
||||||
|
$hIp.Free()
|
||||||
|
$hIp = $null
|
||||||
|
}
|
||||||
|
if ($hCertBytes -ne $null) {
|
||||||
|
$hCertBytes.Free()
|
||||||
|
$hCertBytes = $null
|
||||||
|
}
|
||||||
|
TerminateHttpSys| Out-Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeInterop
|
||||||
|
switch ($Command)
|
||||||
|
{
|
||||||
|
"Add-SslBinding"
|
||||||
|
{
|
||||||
|
return Add-SslBinding $IpEndPoint $Certificate $AppId
|
||||||
|
}
|
||||||
|
"Delete-SslBinding"
|
||||||
|
{
|
||||||
|
return Delete-SslBinding $IpEndpoint
|
||||||
|
}
|
||||||
|
"Get-SslBinding"
|
||||||
|
{
|
||||||
|
return Get-SslBinding $IpEndpoint
|
||||||
|
}
|
||||||
|
default
|
||||||
|
{
|
||||||
|
throw "Unknown command"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue