[automated] Merge branch 'release/2.1' => 'release/3.1' (#18396)

* [Platform] Detect and fix certificates with potentially inaccessible keys on Mac OS (2.1) (#17560)

* [Https] Detects and fixes HTTPS certificates where the key is not guaranteed to be accessible across security partitions

* Fix dotnet dev-certs https --check

* Update logic for detecting missing certs

* Fix security command

* Update warning logic

* Check that the key is accessible in Kestrel

* Add correct link to docs

* Update src/Tools/dotnet-dev-certs/src/Program.cs

Co-Authored-By: Daniel Roth <daroth@microsoft.com>

* Update src/Tools/dotnet-dev-certs/src/Program.cs

Co-Authored-By: Daniel Roth <daroth@microsoft.com>

* Add test for 2.1

* Update src/Tools/dotnet-dev-certs/src/Program.cs

Co-Authored-By: Chris Ross <Tratcher@Outlook.com>

* Address feedback

* Fix non-interctive path

* Fix tests

* Remove a couple of test from an unshipped product

* Check only for certificates considered valid

* Switch the exception being caught, remove invalid test

Co-authored-by: Daniel Roth <daroth@microsoft.com>
Co-authored-by: Chris Ross <Tratcher@Outlook.com>

* Fix patchconfig merge (#18389)

* Fix flaky HubConnectionHandler test (#18391)

Co-authored-by: Javier Calvarro Nelson <jacalvar@microsoft.com>
Co-authored-by: Daniel Roth <daroth@microsoft.com>
Co-authored-by: Chris Ross <Tratcher@Outlook.com>
Co-authored-by: Brennan <brecon@microsoft.com>
This commit is contained in:
dotnet-maestro-bot 2020-01-17 08:30:12 -08:00 committed by Artak
parent d839d4c2bc
commit 2dc908d502
5 changed files with 33 additions and 13 deletions

View File

@ -40,5 +40,10 @@ namespace Microsoft.AspNetCore.Testing
importPfxMutex?.ReleaseMutex(); importPfxMutex?.ReleaseMutex();
} }
} }
public static X509Certificate2 GetTestCertificate(string certName, string password)
{
return new X509Certificate2(GetCertPath(certName), password);
}
} }
} }

View File

@ -7,6 +7,7 @@ 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.Runtime.InteropServices.ComTypes;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Text; using System.Text;
@ -740,12 +741,12 @@ namespace Microsoft.AspNetCore.Certificates.Generation
DateTimeOffset notBefore, DateTimeOffset notBefore,
DateTimeOffset notAfter, DateTimeOffset notAfter,
CertificatePurpose purpose, CertificatePurpose purpose,
string path, string path = null,
bool trust, bool trust = false,
bool includePrivateKey, bool includePrivateKey = false,
string password, string password = null,
string subject, string subjectOverride = null,
bool isInteractive) bool isInteractive = true)
{ {
if (purpose == CertificatePurpose.All) if (purpose == CertificatePurpose.All)
{ {
@ -757,12 +758,12 @@ namespace Microsoft.AspNetCore.Certificates.Generation
var certificates = ListCertificates(purpose, StoreName.My, StoreLocation.CurrentUser, isValid: true, requireExportable: true, result.Diagnostics).Concat( var certificates = ListCertificates(purpose, StoreName.My, StoreLocation.CurrentUser, isValid: true, requireExportable: true, result.Diagnostics).Concat(
ListCertificates(purpose, StoreName.My, StoreLocation.LocalMachine, isValid: true, requireExportable: true, result.Diagnostics)); ListCertificates(purpose, StoreName.My, StoreLocation.LocalMachine, isValid: true, requireExportable: true, result.Diagnostics));
var filteredCertificates = subject == null ? certificates : certificates.Where(c => c.Subject == subject); var filteredCertificates = subjectOverride == null ? certificates : certificates.Where(c => c.Subject == subjectOverride);
if (subject != null) if (subjectOverride != null)
{ {
var excludedCertificates = certificates.Except(filteredCertificates); var excludedCertificates = certificates.Except(filteredCertificates);
result.Diagnostics.Debug($"Filtering found certificates to those with a subject equal to '{subject}'"); result.Diagnostics.Debug($"Filtering found certificates to those with a subject equal to '{subjectOverride}'");
result.Diagnostics.Debug(result.Diagnostics.DescribeCertificates(filteredCertificates)); result.Diagnostics.Debug(result.Diagnostics.DescribeCertificates(filteredCertificates));
result.Diagnostics.Debug($"Listing certificates excluded from consideration."); result.Diagnostics.Debug($"Listing certificates excluded from consideration.");
result.Diagnostics.Debug(result.Diagnostics.DescribeCertificates(excludedCertificates)); result.Diagnostics.Debug(result.Diagnostics.DescribeCertificates(excludedCertificates));
@ -825,7 +826,7 @@ namespace Microsoft.AspNetCore.Certificates.Generation
case CertificatePurpose.All: case CertificatePurpose.All:
throw new InvalidOperationException("The certificate must have a specific purpose."); throw new InvalidOperationException("The certificate must have a specific purpose.");
case CertificatePurpose.HTTPS: case CertificatePurpose.HTTPS:
certificate = CreateAspNetCoreHttpsDevelopmentCertificate(notBefore, notAfter, subject, result.Diagnostics); certificate = CreateAspNetCoreHttpsDevelopmentCertificate(notBefore, notAfter, subjectOverride, result.Diagnostics);
break; break;
default: default:
throw new InvalidOperationException("The certificate must have a purpose."); throw new InvalidOperationException("The certificate must have a purpose.");
@ -853,6 +854,11 @@ namespace Microsoft.AspNetCore.Certificates.Generation
{ {
MakeCertificateKeyAccessibleAcrossPartitions(certificate); MakeCertificateKeyAccessibleAcrossPartitions(certificate);
} }
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && isInteractive)
{
MakeCertificateKeyAccessibleAcrossPartitions(certificate);
}
} }
if (path != null) if (path != null)
{ {
@ -894,10 +900,11 @@ namespace Microsoft.AspNetCore.Certificates.Generation
return result; return result;
} }
private void MakeCertificateKeyAccessibleAcrossPartitions(X509Certificate2 certificate) { private void MakeCertificateKeyAccessibleAcrossPartitions(X509Certificate2 certificate)
{
if (OtherNonAspNetCoreHttpsCertificatesPresent()) if (OtherNonAspNetCoreHttpsCertificatesPresent())
{ {
throw new InvalidOperationException("Unable to make HTTPS ceritificate key trusted across security partitions."); throw new InvalidOperationException("Unable to make HTTPS certificate key trusted across security partitions.");
} }
using (var process = Process.Start(MacOSSetPartitionKeyPermissionsCommandLine, MacOSSetPartitionKeyPermissionsCommandLineArguments)) using (var process = Process.Start(MacOSSetPartitionKeyPermissionsCommandLine, MacOSSetPartitionKeyPermissionsCommandLineArguments))
{ {

View File

@ -15,3 +15,4 @@ namespace Microsoft.AspNetCore.Certificates.Generation
FailedToMakeKeyAccessible, FailedToMakeKeyAccessible,
} }
} }

View File

@ -194,6 +194,13 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools
var now = DateTimeOffset.Now; var now = DateTimeOffset.Now;
var manager = new CertificateManager(); 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) 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 + 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 +