private void CheckByThumbprint(X509Store store, string thumbprint, int warningThreshold) { X509Certificate2Collection certificates = store.Certificates.Find( X509FindType.FindByThumbprint, thumbprint, validOnly: false); X509Certificate2 certificate; if (certificates.Count == 0) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { if (!TryFindCertificate("/var/lib/sfcerts", thumbprint, out certificate) && !TryFindCertificate("/var/lib/waagent", thumbprint, out certificate)) { NotFoundWarnings.Add( $"Could not find requested certificate with thumbprint: {thumbprint} in /var/lib/sfcerts, /var/lib/waagent, and LocalMachine/Root"); return; } } else { NotFoundWarnings.Add( $"Could not find requested certificate with thumbprint: {thumbprint} in LocalMachine/My"); return; } } else { certificate = certificates[0]; } DateTime expiry = certificate.NotAfter; // Expiration time in local time (not UTC) TimeSpan timeUntilExpiry = expiry.Subtract(DateTime.Now); var message = HowToUpdateCnCertsSfLinkHtml; if (IsSelfSignedCertificate(certificate)) { message = HowToUpdateSelfSignedCertSfLinkHtml; } if (timeUntilExpiry.TotalMilliseconds < 0) { ExpiredWarnings.Add($"Certificate Expired on {expiry.ToShortDateString()}: " + $"Thumbprint: {certificate.Thumbprint} " + $"Issuer {certificate.Issuer}, " + $"Subject: {certificate.Subject}{Environment.NewLine}{message}"); } else if (timeUntilExpiry.TotalDays < warningThreshold) { ExpiringWarnings.Add($"Certificate Expiring on {expiry.ToShortDateString()}: " + $"Thumbprint: {certificate.Thumbprint} " + $"Issuer {certificate.Issuer}, " + $"Subject: {certificate.Subject}{Environment.NewLine}{message}"); } }
private void CheckLatestBySubjectName(X509Store store, string subjectName, int warningThreshold) { var certificates = store.Certificates.Find(X509FindType.FindBySubjectName, subjectName, false); X509Certificate2 newestCertificate = null; var newestNotAfter = DateTime.MinValue; if (certificates.Count == 0) { NotFoundWarnings.Add($"Could not find requested certificate with common name: {subjectName} in LocalMachine/My"); return; } var message = HowToUpdateCnCertsSfLinkHtml; foreach (var certificate in certificates) { if (certificate.NotAfter > newestNotAfter) { newestCertificate = certificate; newestNotAfter = certificate.NotAfter; } if (IsSelfSignedCertificate(certificate)) { message = HowToUpdateSelfSignedCertSfLinkHtml; } } DateTime?expiry = newestCertificate?.NotAfter; // Expiration time in local time (not UTC) TimeSpan?timeUntilExpiry = expiry?.Subtract(DateTime.Now); if (timeUntilExpiry?.TotalMilliseconds < 0) { ExpiredWarnings.Add( $"Certificate expired on {expiry?.ToShortDateString()}: " + $"[Thumbprint: {newestCertificate?.Thumbprint} " + $"" + $"Issuer {newestCertificate.Issuer}, " + $"Subject: {newestCertificate.Subject}]{Environment.NewLine}{message}"); } else if (timeUntilExpiry?.TotalDays < warningThreshold) { ExpiringWarnings.Add( $"Certificate expiring in {timeUntilExpiry?.TotalDays} days, on {expiry?.ToShortDateString()}: " + $"[Thumbprint: {newestCertificate.Thumbprint} " + $"Issuer {newestCertificate.Issuer}, " + $"Subject: {newestCertificate.Subject}]{Environment.NewLine}{message}"); } }
public override Task ReportAsync(CancellationToken token) { token.ThrowIfCancellationRequested(); // Someone calling without observing first, must be run after a new run of ObserveAsync if (ExpiringWarnings == null || ExpiredWarnings == null || NotFoundWarnings == null) { return(Task.CompletedTask); } HealthReport healthReport; if (ExpiringWarnings.Count == 0 && ExpiredWarnings.Count == 0 && NotFoundWarnings.Count == 0) { healthReport = new HealthReport { Observer = ObserverName, ReportType = HealthReportType.Node, EmitLogEvent = true, NodeName = NodeName, HealthMessage = $"All cluster and monitored app certificates are healthy.", State = HealthState.Ok, HealthReportTimeToLive = RunInterval > TimeSpan.MinValue ? RunInterval : HealthReportTimeToLive, }; HasActiveFabricErrorOrWarning = false; } else { string healthMessage = (ExpiredWarnings.Count == 0 ? string.Empty : (ExpiredWarnings.Aggregate(string.Empty, (i, j) => i + "\n" + j) + "\n")) + (NotFoundWarnings.Count == 0 ? string.Empty : (NotFoundWarnings.Aggregate(string.Empty, (i, j) => i + "\n" + j) + "\n")) + (ExpiringWarnings.Count == 0 ? string.Empty : ExpiringWarnings.Aggregate(string.Empty, (i, j) => i + "\n" + j)); healthReport = new HealthReport { Code = FOErrorWarningCodes.WarningCertificateExpiration, Observer = ObserverName, ReportType = HealthReportType.Node, EmitLogEvent = true, NodeName = NodeName, HealthMessage = healthMessage, State = HealthState.Warning, HealthReportTimeToLive = RunInterval > TimeSpan.MinValue ? RunInterval : HealthReportTimeToLive, }; HasActiveFabricErrorOrWarning = true; if (IsTelemetryProviderEnabled && IsObserverTelemetryEnabled) { TelemetryData telemetryData = new TelemetryData(FabricClientInstance, token) { Code = FOErrorWarningCodes.WarningCertificateExpiration, HealthState = "Warning", NodeName = NodeName, Metric = ErrorWarningProperty.CertificateExpiration, HealthEventDescription = healthMessage, ObserverName = ObserverName, OS = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "Windows" : "Linux", Source = ObserverConstants.FabricObserverName, Value = FOErrorWarningCodes.GetErrorWarningNameFromFOCode(FOErrorWarningCodes.WarningCertificateExpiration), }; _ = TelemetryClient?.ReportMetricAsync( telemetryData, Token); } if (IsEtwEnabled) { Logger.EtwLogger?.Write( ObserverConstants.FabricObserverETWEventName, new { Code = FOErrorWarningCodes.WarningCertificateExpiration, HealthState = "Warning", NodeName, Metric = ErrorWarningProperty.CertificateExpiration, HealthEventDescription = healthMessage, ObserverName, OS = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "Windows" : "Linux", Source = ObserverConstants.FabricObserverName, Value = FOErrorWarningCodes.GetErrorWarningNameFromFOCode(FOErrorWarningCodes.WarningCertificateExpiration), }); } } HealthReporter.ReportHealthToServiceFabric(healthReport); return(Task.CompletedTask); }