Add support for detecting when the user cancels the trust prompt and a mode to check for the validity and trust of existing certificates

This commit is contained in:
Javier Calvarro Nelson 2017-11-10 12:45:58 -08:00
parent 1cc289cf1d
commit eac0e2d03b
2 changed files with 54 additions and 8 deletions

View File

@ -1,14 +1,14 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Package Versions"> <PropertyGroup Label="Package Versions">
<InternalAspNetCoreSdkPackageVersion>2.1.0-preview1-15549</InternalAspNetCoreSdkPackageVersion> <InternalAspNetCoreSdkPackageVersion>2.1.0-preview1-15549</InternalAspNetCoreSdkPackageVersion>
<MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>2.1.0-preview1-27478</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion> <MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>2.1.0-preview1-27561</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview1-27478</MicrosoftAspNetCoreTestingPackageVersion> <MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview1-27560</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.1.0-preview1-27478</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion> <MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.1.0-preview1-27560</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>2.1.0-preview1-27478</MicrosoftExtensionsConfigurationUserSecretsPackageVersion> <MicrosoftExtensionsConfigurationUserSecretsPackageVersion>2.1.0-preview1-27560</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsProcessSourcesPackageVersion>2.1.0-preview1-27478</MicrosoftExtensionsProcessSourcesPackageVersion> <MicrosoftExtensionsProcessSourcesPackageVersion>2.1.0-preview1-27560</MicrosoftExtensionsProcessSourcesPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion> <MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETTestSdkPackageVersion>15.3.0</MicrosoftNETTestSdkPackageVersion> <MicrosoftNETTestSdkPackageVersion>15.3.0</MicrosoftNETTestSdkPackageVersion>
<SystemDataSqlClientPackageVersion>4.4.0</SystemDataSqlClientPackageVersion> <SystemDataSqlClientPackageVersion>4.4.0</SystemDataSqlClientPackageVersion>

View File

@ -2,12 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Certificates.Generation; using Microsoft.AspNetCore.Certificates.Generation;
using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Tools.Internal; using Microsoft.Extensions.Tools.Internal;
@ -22,6 +20,9 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools
private const int ErrorSavingTheCertificate = 2; private const int ErrorSavingTheCertificate = 2;
private const int ErrorExportingTheCertificate = 3; private const int ErrorExportingTheCertificate = 3;
private const int ErrorTrustingTheCertificate = 4; private const int ErrorTrustingTheCertificate = 4;
private const int ErrorUserCancelledTrustPrompt = 5;
private const int ErrorNoValidCertificateFound = 6;
private const int ErrorCertificateNotTrusted = 7;
public static readonly TimeSpan HttpsCertificateValidity = TimeSpan.FromDays(365); public static readonly TimeSpan HttpsCertificateValidity = TimeSpan.FromDays(365);
@ -44,6 +45,11 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools
"Password to use when exporting the certificate with the private key into a pfx file", "Password to use when exporting the certificate with the private key into a pfx file",
CommandOptionType.SingleValue); CommandOptionType.SingleValue);
var check = c.Option(
"-c|--check",
"Check for the existence of the certificate but do not perform any action",
CommandOptionType.NoValue);
CommandOption trust = null; CommandOption trust = null;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{ {
@ -65,6 +71,10 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools
c.OnExecute(() => c.OnExecute(() =>
{ {
var reporter = new ConsoleReporter(PhysicalConsole.Singleton, verbose.HasValue(), quiet.HasValue()); var reporter = new ConsoleReporter(PhysicalConsole.Singleton, verbose.HasValue(), quiet.HasValue());
if (check.HasValue())
{
return CheckHttpsCertificate(check, trust, reporter);
}
return EnsureHttpsCertificate(exportPath, password, trust, reporter); return EnsureHttpsCertificate(exportPath, password, trust, reporter);
}); });
}); });
@ -85,6 +95,39 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools
} }
} }
private static int CheckHttpsCertificate(CommandOption check, CommandOption trust, IReporter reporter)
{
var now = DateTimeOffset.Now;
var certificateManager = new CertificateManager();
var certificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true);
if (certificates.Count == 0)
{
reporter.Verbose("No valid certificate found.");
return ErrorNoValidCertificateFound;
}
else
{
reporter.Verbose("A valid certificate was found.");
}
if (trust != null && trust.HasValue())
{
var trustedCertificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, isValid: true, requireExportable: false);
if (!certificates.Any(c => certificateManager.IsTrusted(c)))
{
reporter.Verbose($@"The following certificates were found, but none of them is trusted:
{string.Join(Environment.NewLine, certificates.Select(c => $"{c.Subject} - {c.Thumbprint}"))}");
return ErrorCertificateNotTrusted;
}
else
{
reporter.Verbose("A trusted certificate was found.");
}
}
return Success;
}
private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption trust, IReporter reporter) private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption trust, IReporter reporter)
{ {
var now = DateTimeOffset.Now; var now = DateTimeOffset.Now;
@ -135,6 +178,9 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools
case EnsureCertificateResult.FailedToTrustTheCertificate: case EnsureCertificateResult.FailedToTrustTheCertificate:
reporter.Warn("There was an error trusting HTTPS developer certificate."); reporter.Warn("There was an error trusting HTTPS developer certificate.");
return ErrorTrustingTheCertificate; return ErrorTrustingTheCertificate;
case EnsureCertificateResult.UserCancelledTrustStep:
reporter.Warn("The user cancelled the trust step.");
return ErrorUserCancelledTrustPrompt;
default: default:
reporter.Error("Something went wrong. The HTTPS developer certificate could not be created."); reporter.Error("Something went wrong. The HTTPS developer certificate could not be created.");
return CriticalError; return CriticalError;