Add https client ceritificate mapping test (#74)
This commit is contained in:
Родитель
fc580eb0e9
Коммит
cc29517ef3
|
@ -48,4 +48,4 @@ src/AspNetCore/aspnetcore_msg.rc
|
|||
src/AspNetCore/version.h
|
||||
.build
|
||||
|
||||
AspNetCoreModule.VC.db
|
||||
*.VC.*db
|
|
@ -4,8 +4,8 @@
|
|||
using AspNetCoreModule.Test.HttpClientHelper;
|
||||
using Microsoft.Web.Administration;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Management;
|
||||
using System.ServiceProcess;
|
||||
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)
|
||||
{
|
||||
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 = "";
|
||||
if (Ip == null)
|
||||
Ip = "*";
|
||||
bindingInfo += Ip;
|
||||
if (ipAddress == null)
|
||||
ipAddress = "*";
|
||||
bindingInfo += ipAddress;
|
||||
bindingInfo += ":";
|
||||
bindingInfo += Port;
|
||||
bindingInfo += port;
|
||||
bindingInfo += ":";
|
||||
if (host != null)
|
||||
bindingInfo += host;
|
||||
|
@ -944,7 +1169,7 @@ namespace AspNetCoreModule.Test.Framework
|
|||
{
|
||||
SiteCollection sites = serverManager.Sites;
|
||||
Binding b = sites[siteName].Bindings.CreateElement();
|
||||
b.SetAttributeValue("protocol", "http");
|
||||
b.SetAttributeValue("protocol", protocol);
|
||||
b.SetAttributeValue("bindingInformation", bindingInfo);
|
||||
|
||||
sites[siteName].Bindings.Add(b);
|
||||
|
|
|
@ -16,6 +16,9 @@ using System.Security.AccessControl;
|
|||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
|
||||
namespace AspNetCoreModule.Test.Framework
|
||||
{
|
||||
|
@ -216,7 +219,7 @@ namespace AspNetCoreModule.Test.Framework
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static void GiveWritePermissionTo(string folder, SecurityIdentifier sid)
|
||||
{
|
||||
DirectorySecurity fsecurity = Directory.GetAccessControl(folder);
|
||||
|
@ -696,6 +699,48 @@ namespace AspNetCoreModule.Test.Framework
|
|||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public Uri GetHttpUri(string subPath)
|
||||
public Uri GetUri(string subPath, int port = -1, string protocol = "http")
|
||||
{
|
||||
string tempSubPath = subPath;
|
||||
if (!tempSubPath.StartsWith("/"))
|
||||
if (port == -1)
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
@ -103,11 +116,12 @@ namespace AspNetCoreModule.Test.Framework
|
|||
//
|
||||
string siteRootPath = string.Empty;
|
||||
string siteName = string.Empty;
|
||||
string postfix = string.Empty;
|
||||
|
||||
// repeat three times until getting the valid temporary directory path
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
string postfix = Path.GetRandomFileName();
|
||||
postfix = Path.GetRandomFileName();
|
||||
siteName = loggerPrefix.Replace(" ", "") + "_" + postfix;
|
||||
siteRootPath = Path.Combine(Environment.ExpandEnvironmentVariables("%SystemDrive%") + @"\", "inetpub", "ANCMTest", siteName);
|
||||
if (!Directory.Exists(siteRootPath))
|
||||
|
@ -174,6 +188,7 @@ namespace AspNetCoreModule.Test.Framework
|
|||
// Initialize member variables
|
||||
_hostName = "localhost";
|
||||
_siteName = siteName;
|
||||
_postFix = postfix;
|
||||
_tcpPort = tcpPort;
|
||||
|
||||
RootAppContext = new TestWebApplication("/", Path.Combine(siteRootPath, "WebSite1"), this);
|
||||
|
|
|
@ -289,5 +289,28 @@ namespace AspNetCoreModule.Test
|
|||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||
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 httpClient = new HttpClient(httpClientHandler)
|
||||
{
|
||||
BaseAddress = testSite.AspNetCoreApp.GetHttpUri(),
|
||||
BaseAddress = testSite.AspNetCoreApp.GetUri(),
|
||||
Timeout = TimeSpan.FromSeconds(5),
|
||||
};
|
||||
|
||||
|
@ -73,7 +73,7 @@ namespace AspNetCoreModule.Test
|
|||
DateTime startTime = DateTime.Now;
|
||||
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);
|
||||
backendProcessId_old = backendProcessId;
|
||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||
|
@ -99,7 +99,7 @@ namespace AspNetCoreModule.Test
|
|||
DateTime startTime = DateTime.Now;
|
||||
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);
|
||||
backendProcessId_old = backendProcessId;
|
||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||
|
@ -131,7 +131,7 @@ namespace AspNetCoreModule.Test
|
|||
DateTime startTime = DateTime.Now;
|
||||
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));
|
||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||
backendProcessId_old = backendProcessId;
|
||||
|
@ -163,7 +163,7 @@ namespace AspNetCoreModule.Test
|
|||
Thread.Sleep(500);
|
||||
|
||||
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));
|
||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||
backendProcessId_old = backendProcessId;
|
||||
|
@ -196,7 +196,7 @@ namespace AspNetCoreModule.Test
|
|||
Thread.Sleep(1000);
|
||||
|
||||
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));
|
||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||
backendProcessId_old = backendProcessId;
|
||||
|
@ -221,8 +221,8 @@ namespace AspNetCoreModule.Test
|
|||
DateTime startTime = DateTime.Now;
|
||||
Thread.Sleep(500);
|
||||
|
||||
string totalNumber = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetEnvironmentVariables"), HttpStatusCode.OK);
|
||||
Assert.True(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.GetUri("GetEnvironmentVariables"), HttpStatusCode.OK)));
|
||||
|
||||
iisConfig.SetANCMConfig(
|
||||
testSite.SiteName,
|
||||
|
@ -237,7 +237,7 @@ namespace AspNetCoreModule.Test
|
|||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||
|
||||
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" });
|
||||
Thread.Sleep(500);
|
||||
|
||||
|
@ -245,8 +245,8 @@ namespace AspNetCoreModule.Test
|
|||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||
|
||||
expectedValue++;
|
||||
Assert.True("foo" == (await GetResponse(testSite.AspNetCoreApp.GetHttpUri("ExpandEnvironmentVariablesANCMTestFoo"), HttpStatusCode.OK)));
|
||||
Assert.True("bar" == (await GetResponse(testSite.AspNetCoreApp.GetHttpUri("ExpandEnvironmentVariablesANCMTestBar"), HttpStatusCode.OK)));
|
||||
Assert.True("foo" == (await GetResponse(testSite.AspNetCoreApp.GetUri("ExpandEnvironmentVariablesANCMTestFoo"), HttpStatusCode.OK)));
|
||||
Assert.True("bar" == (await GetResponse(testSite.AspNetCoreApp.GetUri("ExpandEnvironmentVariablesANCMTestBar"), HttpStatusCode.OK)));
|
||||
}
|
||||
|
||||
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||
|
@ -270,11 +270,11 @@ namespace AspNetCoreModule.Test
|
|||
Thread.Sleep(1100);
|
||||
|
||||
// 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
|
||||
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));
|
||||
Assert.Equal(backendProcess.ProcessName.ToLower().Replace(".exe", ""), testSite.AspNetCoreApp.GetProcessFileName().ToLower().Replace(".exe", ""));
|
||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||
|
@ -305,11 +305,11 @@ namespace AspNetCoreModule.Test
|
|||
|
||||
// verify 503
|
||||
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
|
||||
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));
|
||||
Assert.Equal(backendProcess.ProcessName.ToLower().Replace(".exe", ""), testSite.AspNetCoreApp.GetProcessFileName().ToLower().Replace(".exe", ""));
|
||||
Assert.NotEqual(backendProcessId_old, backendProcessId);
|
||||
|
@ -333,7 +333,7 @@ namespace AspNetCoreModule.Test
|
|||
new KeyValuePair<string, string>("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, "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();
|
||||
Assert.True(responseBody == curstomErrorMessage);
|
||||
|
||||
|
@ -376,7 +376,7 @@ namespace AspNetCoreModule.Test
|
|||
// check JitDebugger before continuing
|
||||
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"));
|
||||
|
||||
// verify event error log
|
||||
|
@ -409,7 +409,7 @@ namespace AspNetCoreModule.Test
|
|||
DateTime startTimeInsideLooping = DateTime.Now;
|
||||
Thread.Sleep(50);
|
||||
|
||||
var statusCode = await GetResponseStatusCode(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"));
|
||||
var statusCode = await GetResponseStatusCode(testSite.AspNetCoreApp.GetUri("GetProcessId"));
|
||||
if (statusCode != HttpStatusCode.OK.ToString())
|
||||
{
|
||||
Assert.True(i >= valueOfRapidFailsPerMinute, i.ToString() + "is greater than or equals to " + valueOfRapidFailsPerMinute.ToString());
|
||||
|
@ -418,7 +418,7 @@ namespace AspNetCoreModule.Test
|
|||
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);
|
||||
backendProcessId_old = backendProcessId;
|
||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||
|
@ -455,7 +455,7 @@ namespace AspNetCoreModule.Test
|
|||
|
||||
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);
|
||||
if (!processIDs.Contains(id))
|
||||
{
|
||||
|
@ -487,7 +487,7 @@ namespace AspNetCoreModule.Test
|
|||
|
||||
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);
|
||||
if (!processIDs.Contains(id))
|
||||
{
|
||||
|
@ -521,11 +521,11 @@ namespace AspNetCoreModule.Test
|
|||
Thread.Sleep(500);
|
||||
if (startupTimeLimit < startupDelay)
|
||||
{
|
||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetHttpUri("DoSleep3000"), HttpStatusCode.BadGateway);
|
||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetUri("DoSleep3000"), HttpStatusCode.BadGateway);
|
||||
}
|
||||
else
|
||||
{
|
||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri("DoSleep3000"), "Running", HttpStatusCode.OK);
|
||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri("DoSleep3000"), "Running", HttpStatusCode.OK);
|
||||
}
|
||||
}
|
||||
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||
|
@ -543,11 +543,11 @@ namespace AspNetCoreModule.Test
|
|||
|
||||
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")
|
||||
{
|
||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetHttpUri("DoSleep65000"), HttpStatusCode.BadGateway, 70);
|
||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetUri("DoSleep65000"), HttpStatusCode.BadGateway, 70);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -573,8 +573,8 @@ namespace AspNetCoreModule.Test
|
|||
new string[] { "ANCMTestShutdownDelay", "20000" }
|
||||
);
|
||||
|
||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri(), "Running", HttpStatusCode.OK);
|
||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK);
|
||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri(), "Running", HttpStatusCode.OK);
|
||||
string backendProcessId = await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK);
|
||||
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
|
||||
|
||||
// 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;
|
||||
Assert.True(difference.Seconds >= expectedClosingTime);
|
||||
Assert.True(difference.Seconds < expectedClosingTime + 3);
|
||||
Assert.True(backendProcessId != await GetResponse(testSite.AspNetCoreApp.GetHttpUri("GetProcessId"), HttpStatusCode.OK));
|
||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri(), "Running", HttpStatusCode.OK);
|
||||
Assert.True(backendProcessId != await GetResponse(testSite.AspNetCoreApp.GetUri("GetProcessId"), HttpStatusCode.OK));
|
||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri(), "Running", HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
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, "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");
|
||||
Assert.False(Directory.Exists(logPath));
|
||||
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
|
||||
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
|
||||
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
|
||||
|
@ -630,7 +630,7 @@ namespace AspNetCoreModule.Test
|
|||
|
||||
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
|
||||
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))
|
||||
{
|
||||
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));
|
||||
|
||||
// replace $env with the actual test value
|
||||
|
@ -669,7 +669,7 @@ namespace AspNetCoreModule.Test
|
|||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -685,7 +685,7 @@ namespace AspNetCoreModule.Test
|
|||
{
|
||||
string result = string.Empty;
|
||||
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"));
|
||||
|
||||
iisConfig.EnableWindowsAuthentication(testSite.SiteName);
|
||||
|
@ -696,13 +696,13 @@ namespace AspNetCoreModule.Test
|
|||
TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||
Thread.Sleep(500);
|
||||
|
||||
requestHeaders = await GetResponse(testSite.AspNetCoreApp.GetHttpUri("DumpRequestHeaders"), HttpStatusCode.OK);
|
||||
requestHeaders = await GetResponse(testSite.AspNetCoreApp.GetUri("DumpRequestHeaders"), HttpStatusCode.OK);
|
||||
if (enabledForwardWindowsAuthToken)
|
||||
{
|
||||
string expectedHeaderName = "MS-ASPNETCORE-WINAUTHTOKEN";
|
||||
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;
|
||||
|
||||
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"));
|
||||
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
@ -740,10 +740,10 @@ namespace AspNetCoreModule.Test
|
|||
{
|
||||
|
||||
// allocating 1024,000 KB
|
||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetHttpUri("MemoryLeak1024000"), HttpStatusCode.OK);
|
||||
await VerifyResponseStatus(testSite.AspNetCoreApp.GetUri("MemoryLeak1024000"), HttpStatusCode.OK);
|
||||
|
||||
// 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)
|
||||
string userName = testSite.SiteName;
|
||||
|
@ -777,7 +777,7 @@ namespace AspNetCoreModule.Test
|
|||
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "rapidFailsPerMinute", 100);
|
||||
Thread.Sleep(3000);
|
||||
|
||||
await VerifyResponseStatus(testSite.RootAppContext.GetHttpUri("small.htm"), HttpStatusCode.OK);
|
||||
await VerifyResponseStatus(testSite.RootAppContext.GetUri("small.htm"), HttpStatusCode.OK);
|
||||
Thread.Sleep(1000);
|
||||
int x = Convert.ToInt32(TestUtility.GetProcessWMIAttributeValue("w3wp.exe", "Handle", userName));
|
||||
|
||||
|
@ -788,14 +788,14 @@ namespace AspNetCoreModule.Test
|
|||
// check JitDebugger before continuing
|
||||
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);
|
||||
}
|
||||
|
||||
int y = Convert.ToInt32(TestUtility.GetProcessWMIAttributeValue("w3wp.exe", "Handle", userName));
|
||||
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;
|
||||
|
||||
// Verify IIS recycling happens while there is memory leak
|
||||
|
@ -805,9 +805,9 @@ namespace AspNetCoreModule.Test
|
|||
foundVSJit = TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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));
|
||||
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");
|
||||
}
|
||||
testSite.AspNetCoreApp.RestoreFile("web.config");
|
||||
|
@ -876,29 +876,29 @@ namespace AspNetCoreModule.Test
|
|||
string result = string.Empty;
|
||||
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.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.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.False(result.Contains("Content-Encoding"), "verify response header");
|
||||
}
|
||||
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.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.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.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||
}
|
||||
|
@ -937,20 +937,20 @@ namespace AspNetCoreModule.Test
|
|||
|
||||
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");
|
||||
Assert.True(result.Contains("foohtm"), "verify response body");
|
||||
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||
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");
|
||||
Assert.True(result.Contains("foohtm"), "verify response body");
|
||||
Assert.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||
Assert.Equal(headerValue, headerValue2);
|
||||
|
||||
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.Equal("gzip", GetHeaderValue(result, "Content-Encoding"));
|
||||
string headerValue3 = GetHeaderValue(result, "MyCustomHeader");
|
||||
|
@ -959,23 +959,184 @@ namespace AspNetCoreModule.Test
|
|||
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)
|
||||
{
|
||||
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketTest"))
|
||||
{
|
||||
DateTime startTime = DateTime.Now;
|
||||
|
||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetHttpUri(), "Running", HttpStatusCode.OK);
|
||||
await VerifyResponseBody(testSite.AspNetCoreApp.GetUri(), "Running", HttpStatusCode.OK);
|
||||
|
||||
// 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
|
||||
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
|
||||
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
|
||||
Assert.True(TestUtility.RetryHelper((arg1, arg2) => VerifyANCMStartEvent(arg1, arg2), startTime, backendProcessId));
|
||||
|
@ -983,7 +1144,7 @@ namespace AspNetCoreModule.Test
|
|||
// Verify websocket
|
||||
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("HTTP/1.1 101 Switching Protocols"));
|
||||
Thread.Sleep(500);
|
||||
|
@ -996,7 +1157,7 @@ namespace AspNetCoreModule.Test
|
|||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
var response = await client.GetAsync(webApp.GetHttpUri("chunked"));
|
||||
var response = await client.GetAsync(webApp.GetUri("chunked"));
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
try
|
||||
{
|
||||
|
@ -1256,14 +1417,14 @@ namespace AspNetCoreModule.Test
|
|||
string responseStatus = "NotInitialized";
|
||||
|
||||
var httpClientHandler = new HttpClientHandler();
|
||||
httpClientHandler.UseDefaultCredentials = true;
|
||||
httpClientHandler.UseDefaultCredentials = true;
|
||||
|
||||
var httpClient = new HttpClient(httpClientHandler)
|
||||
{
|
||||
BaseAddress = uri,
|
||||
Timeout = TimeSpan.FromSeconds(timeout),
|
||||
};
|
||||
|
||||
|
||||
if (requestHeaders != null)
|
||||
{
|
||||
for (int i = 0; i < requestHeaders.Length; i=i+2)
|
||||
|
@ -1293,7 +1454,7 @@ namespace AspNetCoreModule.Test
|
|||
else
|
||||
{
|
||||
response = await TestUtility.RetryRequest(() =>
|
||||
{
|
||||
{
|
||||
return httpClient.PostAsync(string.Empty, postHttpContent);
|
||||
}, TestUtility.Logger, retryCount: numberOfRetryCount);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
"Microsoft.Extensions.Logging.Console": "1.2.0-*",
|
||||
"Microsoft.Extensions.PlatformAbstractions": "1.2.0-*",
|
||||
"Microsoft.Net.Http.Headers": "1.1.0-*",
|
||||
"xunit": "2.2.0-*"
|
||||
"xunit": "2.2.0-*",
|
||||
"System.Management.Automation.dll": "10.0.10586"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
|
@ -28,7 +29,7 @@
|
|||
"System.Net.Http.WebRequest": "",
|
||||
"System.Runtime": "",
|
||||
"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.
|
||||
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Https;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Net.Http.Server;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
|
||||
namespace AspnetCoreModule.TestSites.Standard
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
private static X509Certificate2 _x509Certificate2;
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var config = new ConfigurationBuilder()
|
||||
|
@ -22,7 +26,33 @@ namespace AspnetCoreModule.TestSites.Standard
|
|||
IWebHostBuilder builder = null;
|
||||
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()
|
||||
.UseConfiguration(config)
|
||||
|
@ -111,8 +141,8 @@ namespace AspnetCoreModule.TestSites.Standard
|
|||
}
|
||||
|
||||
var host = builder.Build();
|
||||
|
||||
host.Run();
|
||||
|
||||
if (Startup.SleeptimeWhileClosing != 0)
|
||||
{
|
||||
Thread.Sleep(Startup.SleeptimeWhileClosing);
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:39982/",
|
||||
"sslPort": 0
|
||||
"sslPort": 44375
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "https://localhost:44375/",
|
||||
"environmentVariables": {
|
||||
"ANCMTestStartupClassName": "StartupCompression",
|
||||
"ANCMTestStartupClassName": "StartupHTTPS",
|
||||
"ASPNET_ENVIRONMENT": "HelloWorld"
|
||||
}
|
||||
},
|
||||
|
|
Двоичный файл не отображается.
|
@ -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"
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче