public static void GenerateAspNetHttpsCertificate() { var manager = new CertificateManager(); var now = DateTimeOffset.Now; manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), isInteractive: false); }
public void EnsureCreateHttpsCertificate_DoesNotCreateACertificate_WhenThereIsAnExistingHttpsCertificates() { // Arrange const string CertificateName = nameof(EnsureCreateHttpsCertificate_DoesNotCreateACertificate_WhenThereIsAnExistingHttpsCertificates) + ".pfx"; var certificatePassword = Guid.NewGuid().ToString(); var manager = new CertificateManager(); manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject); } DateTimeOffset now = DateTimeOffset.UtcNow; now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: false, subject: TestCertificateSubject); var httpsCertificate = manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false).Single(c => c.Subject == TestCertificateSubject); // Act var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), CertificateName, trust: false, includePrivateKey: true, password: certificatePassword, subject: TestCertificateSubject); // Assert Assert.Equal(EnsureCertificateResult.ValidCertificatePresent, result); Assert.True(File.Exists(CertificateName)); var exportedCertificate = new X509Certificate2(File.ReadAllBytes(CertificateName), certificatePassword); Assert.NotNull(exportedCertificate); Assert.True(exportedCertificate.HasPrivateKey); Assert.Equal(httpsCertificate.GetCertHashString(), exportedCertificate.GetCertHashString()); }
public void EnsureAspNetCoreHttpsDevelopmentCertificate_CanRemoveCertificates() { var manager = new CertificateManager(); DateTimeOffset now = DateTimeOffset.UtcNow; now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: true, subject: TestCertificateSubject); manager.CleanupHttpsCertificates(TestCertificateSubject); Assert.Empty(manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false).Where(c => c.Subject == TestCertificateSubject)); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Assert.Empty(manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, isValid: false).Where(c => c.Subject == TestCertificateSubject)); } }
public void EnsureAspNetCoreHttpsDevelopmentCertificate_ReturnsCorrectResult_WhenUserCancelsTrustStepOnWindows() { var manager = new CertificateManager(); manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject); } DateTimeOffset now = DateTimeOffset.UtcNow; now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); var trustFailed = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: true, subject: TestCertificateSubject); Assert.Equal(EnsureCertificateResult.UserCancelledTrustStep, trustFailed); }
private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption trust, IReporter reporter) { var now = DateTimeOffset.Now; var manager = new CertificateManager(); if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && trust?.HasValue() == true) { reporter.Warn("Trusting the HTTPS development certificate was requested. If the certificate is not " + "already trusted we will run the following command:" + Environment.NewLine + "'sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <<certificate>>'" + Environment.NewLine + "This command might prompt you for your password to install the certificate " + "on the system keychain."); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && trust?.HasValue() == true) { reporter.Warn("Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed " + "if the certificate was not previously trusted. Click yes on the prompt to trust the certificate."); } var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate( now, now.Add(HttpsCertificateValidity), exportPath.Value(), trust == null ? false : trust.HasValue(), password.HasValue(), password.Value()); switch (result) { case EnsureCertificateResult.Succeeded: reporter.Output("The HTTPS developer certificate was generated successfully."); if (exportPath.Value() != null) { reporter.Verbose($"The certificate was exported to {Path.GetFullPath(exportPath.Value())}"); } return(Success); case EnsureCertificateResult.ValidCertificatePresent: reporter.Output("A valid HTTPS certificate is already present."); if (exportPath.Value() != null) { reporter.Verbose($"The certificate was exported to {Path.GetFullPath(exportPath.Value())}"); } return(Success); case EnsureCertificateResult.ErrorCreatingTheCertificate: reporter.Error("There was an error creating the HTTPS developer certificate."); return(ErrorCreatingTheCertificate); case EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore: reporter.Error("There was an error saving the HTTPS developer certificate to the current user personal certificate store."); return(ErrorSavingTheCertificate); case EnsureCertificateResult.ErrorExportingTheCertificate: reporter.Warn("There was an error exporting HTTPS developer certificate to a file."); return(ErrorExportingTheCertificate); case EnsureCertificateResult.FailedToTrustTheCertificate: reporter.Warn("There was an error trusting HTTPS developer certificate."); return(ErrorTrustingTheCertificate); case EnsureCertificateResult.UserCancelledTrustStep: reporter.Warn("The user cancelled the trust step."); return(ErrorUserCancelledTrustPrompt); default: reporter.Error("Something went wrong. The HTTPS developer certificate could not be created."); return(CriticalError); } }
private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption trust, IReporter reporter) { var now = DateTimeOffset.Now; var manager = new CertificateManager(); if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && manager.HasValidCertificateWithInnaccessibleKeyAcrossPartitions() || manager.GetHttpsCertificates().Count == 0) { reporter.Warn($"A valid HTTPS certificate with a key accessible across security partitions was not found. The following command will run to fix it:" + Environment.NewLine + "'sudo security set-key-partition-list -D localhost -S unsigned:,teamid:UBF8T346G9'" + Environment.NewLine + "This command will make the certificate key accessible across security partitions and might prompt you for your password. For more information see: https://aka.ms/aspnetcore/2.1/troubleshootcertissues"); } if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && manager.HasValidCertificateWithInnaccessibleKeyAcrossPartitions() || manager.GetHttpsCertificates().Count == 0) { reporter.Warn($"A valid HTTPS certificate with a key accessible across security partitions was not found. The following command will run to fix it:" + Environment.NewLine + "'sudo security set-key-partition-list -D localhost -S unsigned:,teamid:UBF8T346G9'" + Environment.NewLine + "This command will make the certificate key accessible across security partitions and might prompt you for your password. For more information see: https://aka.ms/aspnetcore/3.1/troubleshootcertissues"); } if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && trust?.HasValue() == true) { reporter.Warn("Trusting the HTTPS development certificate was requested. If the certificate is not " + "already trusted we will run the following command:" + Environment.NewLine + "'sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <<certificate>>'" + Environment.NewLine + "This command might prompt you for your password to install the certificate " + "on the system keychain."); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && trust?.HasValue() == true) { reporter.Warn("Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed " + "if the certificate was not previously trusted. Click yes on the prompt to trust the certificate."); } var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate( now, now.Add(HttpsCertificateValidity), exportPath.Value(), trust == null ? false : trust.HasValue(), password.HasValue(), password.Value()); reporter.Verbose(string.Join(Environment.NewLine, result.Diagnostics.Messages)); switch (result.ResultCode) { case EnsureCertificateResult.Succeeded: reporter.Output("The HTTPS developer certificate was generated successfully."); if (exportPath.Value() != null) { reporter.Verbose($"The certificate was exported to {Path.GetFullPath(exportPath.Value())}"); } return(Success); case EnsureCertificateResult.ValidCertificatePresent: reporter.Output("A valid HTTPS certificate is already present."); if (exportPath.Value() != null) { reporter.Verbose($"The certificate was exported to {Path.GetFullPath(exportPath.Value())}"); } return(Success); case EnsureCertificateResult.ErrorCreatingTheCertificate: reporter.Error("There was an error creating the HTTPS developer certificate."); return(ErrorCreatingTheCertificate); case EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore: reporter.Error("There was an error saving the HTTPS developer certificate to the current user personal certificate store."); return(ErrorSavingTheCertificate); case EnsureCertificateResult.ErrorExportingTheCertificate: reporter.Warn("There was an error exporting HTTPS developer certificate to a file."); return(ErrorExportingTheCertificate); case EnsureCertificateResult.FailedToTrustTheCertificate: reporter.Warn("There was an error trusting HTTPS developer certificate."); return(ErrorTrustingTheCertificate); case EnsureCertificateResult.UserCancelledTrustStep: reporter.Warn("The user cancelled the trust step."); return(ErrorUserCancelledTrustPrompt); default: reporter.Error("Something went wrong. The HTTPS developer certificate could not be created."); return(CriticalError); } }
public void EnsureCreateHttpsCertificate_CreatesACertificate_WhenThereAreNoHttpsCertificates() { try { // Arrange const string CertificateName = nameof(EnsureCreateHttpsCertificate_CreatesACertificate_WhenThereAreNoHttpsCertificates) + ".cer"; var manager = new CertificateManager(); manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject); } // Act DateTimeOffset now = DateTimeOffset.UtcNow; now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), CertificateName, trust: false, subject: TestCertificateSubject); // Assert Assert.Equal(EnsureCertificateResult.Succeeded, result); Assert.True(File.Exists(CertificateName)); var exportedCertificate = new X509Certificate2(File.ReadAllBytes(CertificateName)); Assert.NotNull(exportedCertificate); Assert.False(exportedCertificate.HasPrivateKey); var httpsCertificates = manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false); var httpsCertificate = Assert.Single(httpsCertificates, c => c.Subject == TestCertificateSubject); Assert.True(httpsCertificate.HasPrivateKey); Assert.Equal(TestCertificateSubject, httpsCertificate.Subject); Assert.Equal(TestCertificateSubject, httpsCertificate.Issuer); Assert.Equal("sha256RSA", httpsCertificate.SignatureAlgorithm.FriendlyName); Assert.Equal("1.2.840.113549.1.1.11", httpsCertificate.SignatureAlgorithm.Value); Assert.Equal(now.LocalDateTime, httpsCertificate.NotBefore); Assert.Equal(now.AddYears(1).LocalDateTime, httpsCertificate.NotAfter); Assert.Contains( httpsCertificate.Extensions.OfType <X509Extension>(), e => e is X509BasicConstraintsExtension basicConstraints && basicConstraints.Critical == true && basicConstraints.CertificateAuthority == false && basicConstraints.HasPathLengthConstraint == false && basicConstraints.PathLengthConstraint == 0); Assert.Contains( httpsCertificate.Extensions.OfType <X509Extension>(), e => e is X509KeyUsageExtension keyUsage && keyUsage.Critical == true && keyUsage.KeyUsages == X509KeyUsageFlags.KeyEncipherment); Assert.Contains( httpsCertificate.Extensions.OfType <X509Extension>(), e => e is X509EnhancedKeyUsageExtension enhancedKeyUsage && enhancedKeyUsage.Critical == true && enhancedKeyUsage.EnhancedKeyUsages.OfType <Oid>().Single() is Oid keyUsage && keyUsage.Value == "1.3.6.1.5.5.7.3.1"); // Subject alternative name Assert.Contains( httpsCertificate.Extensions.OfType <X509Extension>(), e => e.Critical == true && e.Oid.Value == "2.5.29.17"); // ASP.NET HTTPS Development certificate extension Assert.Contains( httpsCertificate.Extensions.OfType <X509Extension>(), e => e.Critical == false && e.Oid.Value == "1.3.6.1.4.1.311.84.1.1" && Encoding.ASCII.GetString(e.RawData) == "ASP.NET Core HTTPS development certificate"); Assert.Equal(httpsCertificate.GetCertHashString(), exportedCertificate.GetCertHashString()); } catch (Exception e) { Output.WriteLine(e.Message); ListCertificates(Output); throw; } }