diff --git a/samples/NativeIISSample/Properties/launchSettings.json b/samples/NativeIISSample/Properties/launchSettings.json index f62697de39..246b7a0b47 100644 --- a/samples/NativeIISSample/Properties/launchSettings.json +++ b/samples/NativeIISSample/Properties/launchSettings.json @@ -14,8 +14,8 @@ "commandLineArgs": "$(IISExpressArguments)", "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", + "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", + "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", "ANCM_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", @@ -29,9 +29,9 @@ "commandLineArgs": "$(IISArguments)", "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", - "ANCM_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", + "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", + "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", + "ASPNETCORE_MODULE_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", "LAUNCHER_PATH": "$(DotNetPath)", diff --git a/test/Common.FunctionalTests/ClientCertificateFixture.cs b/test/Common.FunctionalTests/ClientCertificateFixture.cs index 4979865e8b..40b6f2265e 100644 --- a/test/Common.FunctionalTests/ClientCertificateFixture.cs +++ b/test/Common.FunctionalTests/ClientCertificateFixture.cs @@ -11,68 +11,57 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests public class ClientCertificateFixture : IDisposable { private X509Certificate2 _certificate; + private const string _certIssuerPrefix = "CN=IISIntegrationTest_Root"; - public X509Certificate2 Certificate + public X509Certificate2 GetOrCreateCertificate() { - get + if (_certificate != null) { - if (_certificate != null) - { - return _certificate; - } + return _certificate; + } - using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) - { - store.Open(OpenFlags.ReadWrite); + using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) + { + store.Open(OpenFlags.ReadWrite); + var parentKey = CreateKeyMaterial(2048); - foreach (var cert in store.Certificates) - { - if (cert.Issuer != "CN=IISIntegrationTest_Root") - { - continue; - } - _certificate = cert; - store.Close(); - return cert; - } + // Create a cert name with a random guid to avoid name conflicts + var parentRequest = new CertificateRequest( + _certIssuerPrefix + Guid.NewGuid().ToString(), + parentKey, HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); - var parentKey = CreateKeyMaterial(2048); + parentRequest.CertificateExtensions.Add( + new X509BasicConstraintsExtension( + certificateAuthority: true, + hasPathLengthConstraint: false, + pathLengthConstraint: 0, + critical: true)); - // On first run of the test, creates the certificate in the trusted root certificate authorities. - var parentRequest = new CertificateRequest("CN=IISIntegrationTest_Root", parentKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + parentRequest.CertificateExtensions.Add( + new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation, critical: true)); - parentRequest.CertificateExtensions.Add( - new X509BasicConstraintsExtension( - certificateAuthority: true, - hasPathLengthConstraint: false, - pathLengthConstraint: 0, - critical: true)); + parentRequest.CertificateExtensions.Add( + new X509SubjectKeyIdentifierExtension(parentRequest.PublicKey, false)); - parentRequest.CertificateExtensions.Add( - new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation, critical: true)); + var notBefore = DateTimeOffset.Now.AddDays(-1); + var notAfter = DateTimeOffset.Now.AddYears(5); - parentRequest.CertificateExtensions.Add( - new X509SubjectKeyIdentifierExtension(parentRequest.PublicKey, false)); + var parentCert = parentRequest.CreateSelfSigned(notBefore, notAfter); - var notBefore = DateTimeOffset.Now.AddDays(-1); - var notAfter = DateTimeOffset.Now.AddYears(5); + // Need to export/import the certificate to associate the private key with the cert. + var imported = parentCert; - var parentCert = parentRequest.CreateSelfSigned(notBefore, notAfter); + var export = parentCert.Export(X509ContentType.Pkcs12, ""); + imported = new X509Certificate2(export, "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); + Array.Clear(export, 0, export.Length); - // Need to export/import the certificate to associate the private key with the cert. - var imported = parentCert; + // Add the cert to the cert store + _certificate = imported; - var export = parentCert.Export(X509ContentType.Pkcs12, ""); - imported = new X509Certificate2(export, "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); - Array.Clear(export, 0, export.Length); - - // Add the cert to the cert store - _certificate = imported; - - store.Add(certificate: imported); - store.Close(); - return imported; - } + store.Add(certificate: imported); + store.Close(); + return imported; } } @@ -86,7 +75,17 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) { store.Open(OpenFlags.ReadWrite); - store.Remove(Certificate); + store.Remove(_certificate); + + // Remove any extra certs that were left by previous tests. + for (var i = store.Certificates.Count - 1; i >= 0; i--) + { + var cert = store.Certificates[i]; + if (cert.Issuer.StartsWith(_certIssuerPrefix)) + { + store.Remove(cert); + } + } store.Close(); } } diff --git a/test/Common.FunctionalTests/ClientCertificateTests.cs b/test/Common.FunctionalTests/ClientCertificateTests.cs index 289fb18c2f..43ccc83eff 100644 --- a/test/Common.FunctionalTests/ClientCertificateTests.cs +++ b/test/Common.FunctionalTests/ClientCertificateTests.cs @@ -1,7 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Net.Http; +using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; @@ -9,6 +11,7 @@ using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting.Common; using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging; using Xunit; namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests @@ -54,31 +57,51 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests deploymentParameters.ApplicationBaseUriHint = $"https://localhost:{port}/"; deploymentParameters.AddHttpsToServerConfig(); - var deploymentResult = await DeployAsync(deploymentParameters); var handler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (a, b, c, d) => true, ClientCertificateOptions = ClientCertificateOption.Manual, }; + X509Certificate2 cert = null; if (sendClientCert) { - Assert.NotNull(_certFixture.Certificate); - handler.ClientCertificates.Add(_certFixture.Certificate); + cert = _certFixture.GetOrCreateCertificate(); + handler.ClientCertificates.Add(cert); } + var deploymentResult = await DeployAsync(deploymentParameters); + var client = deploymentResult.CreateClient(handler); var response = await client.GetAsync("GetClientCert"); var responseText = await response.Content.ReadAsStringAsync(); - if (sendClientCert) + try { - Assert.Equal($"Enabled;{_certFixture.Certificate.GetCertHashString()}", responseText); + if (sendClientCert) + { + Assert.Equal($"Enabled;{cert.GetCertHashString()}", responseText); + } + else + { + Assert.Equal("Disabled", responseText); + } } - else + catch (Exception ex) { - Assert.Equal("Disabled", responseText); + Logger.LogError($"Certificate is invalid. Issuer name: {cert.Issuer}"); + using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) + { + Logger.LogError($"List of current certificates in root store:"); + store.Open(OpenFlags.ReadWrite); + foreach (var otherCert in store.Certificates) + { + Logger.LogError(otherCert.Issuer); + } + store.Close(); + } + throw ex; } } }