Service Fabric 应用 Kestrel 证书轮换新证书
Service Fabric app Kestrel cert rotation on new cert
我有一个 Service Fabric 无状态应用程序。
为 ServiceInstanceListener 使用以下代码:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel(opt =>
{
int port = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
{
X509Certificate2 cert = GetCertificateFromStore();
listenOptions.UseHttps(cert);
listenOptions.NoDelay = true;
});
函数 GetCertificateFromStore:
private static X509Certificate2 GetCertificateFromStore()
{
string subjectCommonName = Environment.GetEnvironmentVariable("certsubject");
X509Certificate2 certForApp = null;
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var certCollection = store.Certificates;
// https://docs.microsoft.com/en-us/azure/service-fabric/cluster-security-certificate-management
foreach (var enumeratedCert in certCollection)
{
if (StringComparer.OrdinalIgnoreCase.Equals(subjectCommonName, enumeratedCert.GetNameInfo(X509NameType.SimpleName, forIssuer: false))
&& DateTime.Now < enumeratedCert.NotAfter
&& DateTime.Now >= enumeratedCert.NotBefore)
{
if (certForApp == null)
{
certForApp = enumeratedCert;
}
else
{
// the Service Fabric runtime will find and select the most recently issued matching certificate (largest value of the 'NotBefore' property). Note this is a change from previous versions of the Service Fabric runtime.
if (enumeratedCert.NotBefore > certForApp.NotBefore)
{
certForApp = enumeratedCert;
}
}
}
}
if (certForApp == null)
{
throw new Exception($"Could not find a match for a certificate with subject 'CN={subjectCommonName}'.");
}
return certForApp;
}
如果在 VMSS 上安装了新版本的证书(在证书轮换后说),无状态应用程序应该如何获取新证书而不服务重启.
如果服务重新启动,将获取最新的证书。
您可以这样修改您的代码:
new WebHostBuilder()
.UseKestrel(options =>
{
options.Listen(IPAddress.Any, 80);
options.Listen(IPAddress.Any, 443, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
httpsOptions.ServerCertificateSelector = (context, dnsName) =>
{
//return cached certificate, invalidate if needed (e.g. check periodically)
if(_cachedCertificate is null)
{
_cachedCertificate = GetCertificateFromStore();
return _cachedCertificate;
}
}
}
}
更多信息here
我有一个 Service Fabric 无状态应用程序。
为 ServiceInstanceListener 使用以下代码:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel(opt =>
{
int port = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
{
X509Certificate2 cert = GetCertificateFromStore();
listenOptions.UseHttps(cert);
listenOptions.NoDelay = true;
});
函数 GetCertificateFromStore:
private static X509Certificate2 GetCertificateFromStore()
{
string subjectCommonName = Environment.GetEnvironmentVariable("certsubject");
X509Certificate2 certForApp = null;
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var certCollection = store.Certificates;
// https://docs.microsoft.com/en-us/azure/service-fabric/cluster-security-certificate-management
foreach (var enumeratedCert in certCollection)
{
if (StringComparer.OrdinalIgnoreCase.Equals(subjectCommonName, enumeratedCert.GetNameInfo(X509NameType.SimpleName, forIssuer: false))
&& DateTime.Now < enumeratedCert.NotAfter
&& DateTime.Now >= enumeratedCert.NotBefore)
{
if (certForApp == null)
{
certForApp = enumeratedCert;
}
else
{
// the Service Fabric runtime will find and select the most recently issued matching certificate (largest value of the 'NotBefore' property). Note this is a change from previous versions of the Service Fabric runtime.
if (enumeratedCert.NotBefore > certForApp.NotBefore)
{
certForApp = enumeratedCert;
}
}
}
}
if (certForApp == null)
{
throw new Exception($"Could not find a match for a certificate with subject 'CN={subjectCommonName}'.");
}
return certForApp;
}
如果在 VMSS 上安装了新版本的证书(在证书轮换后说),无状态应用程序应该如何获取新证书而不服务重启.
如果服务重新启动,将获取最新的证书。
您可以这样修改您的代码:
new WebHostBuilder()
.UseKestrel(options =>
{
options.Listen(IPAddress.Any, 80);
options.Listen(IPAddress.Any, 443, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
httpsOptions.ServerCertificateSelector = (context, dnsName) =>
{
//return cached certificate, invalidate if needed (e.g. check periodically)
if(_cachedCertificate is null)
{
_cachedCertificate = GetCertificateFromStore();
return _cachedCertificate;
}
}
}
}
更多信息here