Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static class CertificateGenerator
public static void GenerateAspNetHttpsCertificate()
{
var manager = CertificateManager.Instance;
var now = DateTimeOffset.Now;
var now = DateTimeOffset.UtcNow;
manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), isInteractive: false);
}
}
34 changes: 34 additions & 0 deletions src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,40 @@ public void ListCertificates_AlwaysReturnsTheCertificate_WithHighestVersion()
e.RawData[0] == 2);
}

[Fact]
public void CreateAspNetCoreHttpsDevelopmentCertificate_UsesUtcTime_NotLocalTime()
{
// This test verifies that the certificate NotBefore time is based on UTC, not local timezone
// This prevents issues where certificates appear "not yet valid" in different timezones

try
{
_fixture.CleanupCertificates();

// Use a known UTC time as the basis for the certificate
var utcNow = new DateTimeOffset(2024, 1, 15, 12, 0, 0, TimeSpan.Zero); // UTC noon
var utcExpiry = utcNow.AddYears(1);

// Create certificate with UTC-based times
var certificate = _manager.CreateAspNetCoreHttpsDevelopmentCertificate(utcNow, utcExpiry);

// Verify that NotBefore matches the UTC time we provided, not a local time
// The certificate should be immediately valid at the specified UTC time
var expectedNotBefore = utcNow.UtcDateTime;
var actualNotBefore = certificate.NotBefore.ToUniversalTime();

// Allow for some minor timing differences (within 1 second)
var timeDifference = Math.Abs((expectedNotBefore - actualNotBefore).TotalSeconds);
Assert.True(timeDifference < 1,
$"Certificate NotBefore should match UTC time. Expected: {expectedNotBefore:yyyy-MM-dd HH:mm:ss} UTC, " +
$"Actual: {actualNotBefore:yyyy-MM-dd HH:mm:ss} UTC, Difference: {timeDifference:F2} seconds");
}
finally
{
_fixture.CleanupCertificates();
}
}

[ConditionalFact]
[OSSkipCondition(OperatingSystems.Windows, SkipReason = "UnixFileMode is not supported on Windows.")]
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "https://github.com/dotnet/aspnetcore/issues/6720")]
Expand Down
2 changes: 1 addition & 1 deletion src/Tools/dotnet-dev-certs/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ private static int CheckHttpsCertificateJsonOutput(IReporter reporter)

private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption noPassword, CommandOption trust, CommandOption exportFormat, IReporter reporter)
{
var now = DateTimeOffset.Now;
var now = DateTimeOffset.UtcNow;
var manager = CertificateManager.Instance;

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
Expand Down
Loading