C# 为本地群集安装证书

C# 为本地群集安装证书,c#,azure-service-fabric,C#,Azure Service Fabric,我有一些代码要通过Azure密钥库进行身份验证,以便检索一些机密。我正在使用客户端id和证书进行身份验证,而不是使用客户端id和密码。此代码在普通控制台应用程序中非常有效: var store = new X509Store(StoreName.My, StoreLocation.CurrentUser); try { store.Open(OpenFlags.ReadOnly); var matchingCertificates = store.Certificates.Fi

我有一些代码要通过Azure密钥库进行身份验证,以便检索一些机密。我正在使用客户端id和证书进行身份验证,而不是使用客户端id和密码。此代码在普通控制台应用程序中非常有效:

var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
    store.Open(OpenFlags.ReadOnly);

    var matchingCertificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
    if (matchingCertificates.Count != 1)
    {
        return null;
    }

    return matchingCertificates[0];
}
finally
{
    if (store != null) store.Close();
}
一旦我尝试在有状态服务应用程序中使用此代码,它就无法再找到证书


如何安装证书以使其可供本地群集使用?

服务结构应用程序在网络服务帐户下运行,因此您需要确保该帐户具有证书的访问/权限

编辑:

对于在本地机箱上运行的群集,您可以使用certmgr.msc或相关mmc管理单元查找证书,然后右键单击>所有任务>管理私钥,然后授予网络服务读取权限

对于Azure中的远程群集,您可以在规模集的虚拟机上使用一个可运行PowerShell脚本(该脚本设置您想要的权限)来执行此操作。例如,它可以执行以下操作:

$certificate = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq $certificateThumbprint}

# Get file path
$certificateFilePath = "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\" + $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName

# Take ownership of the file so that permissions can be set
takeown /F $certificateFilePath

# Give the NETWORK SERVICE read permissions
$acl = (Get-Item $certificateFilePath).GetAccessControl('Access')
$rule = new-object System.Security.AccessControl.FileSystemAccessRule "NETWORK SERVICE","Read","Allow"
$acl.SetAccessRule($rule)
Set-Acl -Path $certificateFilePath -AclObject $acl

这不能按原样工作的原因是服务结构在网络服务帐户下运行,没有配置,网络服务帐户无权访问证书

至少对我们来说,当使用Microsoft.Azure.KeyVault提供的
KeyVault客户端
使用证书连接到密钥库时,此场景导致“密钥集不存在”异常

解决方案是将证书包含在
ApplicationManifest.xml
中,它指示服务结构向网络服务帐户授予对证书的访问权

<ApplicationManifest>
   <!-- snip -->
   <Principals>
      <Users>
         <User Name="NetworkServiceAccount" AccountType="NetworkService" />
      </Users>
   </Principals>
   <Policies>
      <SecurityAccessPolicies>
         <SecurityAccessPolicy ResourceRef="KeyVaultCert" PrincipalRef="NetworkServiceAccount" GrantRights="Full" ResourceType="Certificate" />
      </SecurityAccessPolicies>
   </Policies>
   <Certificates>
      <SecretsCertificate X509FindValue="1ABCD86B815F37123459A34C1BA9EDEBABCEDF1" Name="KeyVaultCert" />
   </Certificates>
</ApplicationManifest>

所以只要本地计算机有权访问,它仍然可以看到安装在本地计算机上的所有证书?是的,没错。通过在ApplicationManifest.xml中定义用户、组和访问策略,您可以让Service Fabric自动授予对特定证书的访问权,而不是手动授予访问权。有关设置的更多信息,请参阅此文档:能否提供有关如何在Service Fabric中授予证书访问权限的更多详细信息?该文档讨论了SSL端点证书,但这不是我的用例。我正在使用证书私钥对KeyVault资源进行身份验证。我已经在缩放集的VM定义上使用自定义脚本扩展完成了此操作,该扩展将运行脚本来设置这些权限。然而,@VaclavTurecek可能能够使用RunAs提供更优雅的解决方案。请注意,在德国,“网络服务”是“Netzwerkdienst”-即使您将Windows语言切换为英语。这就是为什么最好使用
新对象System.Security.Principal.SecurityIdentifier(“S-1-5-20”)
等。这是更好的答案,更简洁、更容易。完美无瑕!此解决方案似乎不支持证书滚动。Azure Service Fabric不会使用类似“netsh http ssl remove..”的内容注销端口,并且使用新指纹升级应用程序失败…一个让我感到困惑的澄清:确保将证书安装到LOCALMACHINE(而不是CurrentUser)位置。如果您只是dbl单击了*.pfx/cer文件,那么它将转到CurrentUser。这将在codepackage部署步骤中为您提供结构\u E\u证书\u NOTFOUND错误。@Satthru如果您通过VM Scale Set资源添加证书(请参阅以获取信息),则该证书将自动安装在本地计算机存储中。