Skip to content

Commit 2dc908d

Browse files
dotnet-maestro-botjaviercndanroth27TratcherBrennanConroy
authored andcommitted
[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 <[email protected]> * Update src/Tools/dotnet-dev-certs/src/Program.cs Co-Authored-By: Daniel Roth <[email protected]> * Add test for 2.1 * Update src/Tools/dotnet-dev-certs/src/Program.cs Co-Authored-By: Chris Ross <[email protected]> * 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 <[email protected]> Co-authored-by: Chris Ross <[email protected]> * Fix patchconfig merge (#18389) * Fix flaky HubConnectionHandler test (#18391) Co-authored-by: Javier Calvarro Nelson <[email protected]> Co-authored-by: Daniel Roth <[email protected]> Co-authored-by: Chris Ross <[email protected]> Co-authored-by: Brennan <[email protected]>
1 parent d839d4c commit 2dc908d

File tree

5 files changed

+33
-13
lines changed

5 files changed

+33
-13
lines changed

src/Servers/Kestrel/Core/src/CoreStrings.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,4 +620,4 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
620620
<data name="BadDeveloperCertificateState" xml:space="preserve">
621621
<value>The ASP.NET Core developer certificate is in an invalid state. To fix this issue, run the following commands 'dotnet dev-certs https --clean' and 'dotnet dev-certs https' to remove all existing ASP.NET Core development certificates and create a new untrusted developer certificate. On macOS or Windows, use 'dotnet dev-certs https --trust' to trust the new certificate.</value>
622622
</data>
623-
</root>
623+
</root>

src/Servers/Kestrel/shared/test/TestResources.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,10 @@ public static X509Certificate2 GetTestCertificate(string certName = "testCert.pf
4040
importPfxMutex?.ReleaseMutex();
4141
}
4242
}
43+
44+
public static X509Certificate2 GetTestCertificate(string certName, string password)
45+
{
46+
return new X509Certificate2(GetCertPath(certName), password);
47+
}
4348
}
4449
}

src/Shared/CertificateGeneration/CertificateManager.cs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.IO;
88
using System.Linq;
99
using System.Runtime.InteropServices;
10+
using System.Runtime.InteropServices.ComTypes;
1011
using System.Security.Cryptography;
1112
using System.Security.Cryptography.X509Certificates;
1213
using System.Text;
@@ -740,12 +741,12 @@ public DetailedEnsureCertificateResult EnsureValidCertificateExists(
740741
DateTimeOffset notBefore,
741742
DateTimeOffset notAfter,
742743
CertificatePurpose purpose,
743-
string path,
744-
bool trust,
745-
bool includePrivateKey,
746-
string password,
747-
string subject,
748-
bool isInteractive)
744+
string path = null,
745+
bool trust = false,
746+
bool includePrivateKey = false,
747+
string password = null,
748+
string subjectOverride = null,
749+
bool isInteractive = true)
749750
{
750751
if (purpose == CertificatePurpose.All)
751752
{
@@ -757,12 +758,12 @@ public DetailedEnsureCertificateResult EnsureValidCertificateExists(
757758
var certificates = ListCertificates(purpose, StoreName.My, StoreLocation.CurrentUser, isValid: true, requireExportable: true, result.Diagnostics).Concat(
758759
ListCertificates(purpose, StoreName.My, StoreLocation.LocalMachine, isValid: true, requireExportable: true, result.Diagnostics));
759760

760-
var filteredCertificates = subject == null ? certificates : certificates.Where(c => c.Subject == subject);
761-
if (subject != null)
761+
var filteredCertificates = subjectOverride == null ? certificates : certificates.Where(c => c.Subject == subjectOverride);
762+
if (subjectOverride != null)
762763
{
763764
var excludedCertificates = certificates.Except(filteredCertificates);
764765

765-
result.Diagnostics.Debug($"Filtering found certificates to those with a subject equal to '{subject}'");
766+
result.Diagnostics.Debug($"Filtering found certificates to those with a subject equal to '{subjectOverride}'");
766767
result.Diagnostics.Debug(result.Diagnostics.DescribeCertificates(filteredCertificates));
767768
result.Diagnostics.Debug($"Listing certificates excluded from consideration.");
768769
result.Diagnostics.Debug(result.Diagnostics.DescribeCertificates(excludedCertificates));
@@ -825,7 +826,7 @@ public DetailedEnsureCertificateResult EnsureValidCertificateExists(
825826
case CertificatePurpose.All:
826827
throw new InvalidOperationException("The certificate must have a specific purpose.");
827828
case CertificatePurpose.HTTPS:
828-
certificate = CreateAspNetCoreHttpsDevelopmentCertificate(notBefore, notAfter, subject, result.Diagnostics);
829+
certificate = CreateAspNetCoreHttpsDevelopmentCertificate(notBefore, notAfter, subjectOverride, result.Diagnostics);
829830
break;
830831
default:
831832
throw new InvalidOperationException("The certificate must have a purpose.");
@@ -853,6 +854,11 @@ public DetailedEnsureCertificateResult EnsureValidCertificateExists(
853854
{
854855
MakeCertificateKeyAccessibleAcrossPartitions(certificate);
855856
}
857+
858+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && isInteractive)
859+
{
860+
MakeCertificateKeyAccessibleAcrossPartitions(certificate);
861+
}
856862
}
857863
if (path != null)
858864
{
@@ -894,10 +900,11 @@ public DetailedEnsureCertificateResult EnsureValidCertificateExists(
894900
return result;
895901
}
896902

897-
private void MakeCertificateKeyAccessibleAcrossPartitions(X509Certificate2 certificate) {
903+
private void MakeCertificateKeyAccessibleAcrossPartitions(X509Certificate2 certificate)
904+
{
898905
if (OtherNonAspNetCoreHttpsCertificatesPresent())
899906
{
900-
throw new InvalidOperationException("Unable to make HTTPS ceritificate key trusted across security partitions.");
907+
throw new InvalidOperationException("Unable to make HTTPS certificate key trusted across security partitions.");
901908
}
902909
using (var process = Process.Start(MacOSSetPartitionKeyPermissionsCommandLine, MacOSSetPartitionKeyPermissionsCommandLineArguments))
903910
{

src/Shared/CertificateGeneration/EnsureCertificateResult.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ internal enum EnsureCertificateResult
1515
FailedToMakeKeyAccessible,
1616
}
1717
}
18+

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@ private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOptio
194194
var now = DateTimeOffset.Now;
195195
var manager = new CertificateManager();
196196

197+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && manager.HasValidCertificateWithInnaccessibleKeyAcrossPartitions() || manager.GetHttpsCertificates().Count == 0)
198+
{
199+
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 +
200+
"'sudo security set-key-partition-list -D localhost -S unsigned:,teamid:UBF8T346G9'" + Environment.NewLine +
201+
"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");
202+
}
203+
197204
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && manager.HasValidCertificateWithInnaccessibleKeyAcrossPartitions() || manager.GetHttpsCertificates().Count == 0)
198205
{
199206
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 +

0 commit comments

Comments
 (0)