Esempio n. 1
0
        public static void GenerateAspNetHttpsCertificate()
        {
            var manager = new CertificateManager();
            var now     = DateTimeOffset.Now;

            manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), isInteractive: false);
        }
Esempio n. 2
0
        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());
        }
Esempio n. 3
0
        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));
            }
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
        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);
            }
        }
Esempio n. 7
0
        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;
            }
        }