【问题标题】:Load SSL Certificate in Azure Service Fabric for Custom TCP service在 Azure Service Fabric 中为自定义 TCP 服务加载 SSL 证书
【发布时间】:2017-01-04 10:12:18
【问题描述】:

我创建了一个 TCP 服务,它创建了一个安全的 SSL 连接,我试图在 Azure Service Fabric 群集中托管该连接。虽然有关于如何为网站和 API 加载和使用 SSL 证书的文档,但我似乎找不到任何关于如何为我的服务加载证书的文档。我已将证书加载到密钥保管库,但现在需要创建 X509Certificate2 的实例以保护我的 tcp 连接。

【问题讨论】:

    标签: azure azure-cloud-services azure-service-fabric


    【解决方案1】:

    一种选择是以SYSTEM 身份运行Service Fabric 设置任务(只有SYSTEM 有权更改证书上的ACL)并授予NETWORK SERVICE 读取证书的权限

    下面的完整示例,注意我在所有 LocalMachine / 我的证书上设置了 ACL,修改 PS 脚本以仅获取您需要的证书

    ServiceManifest.xml

      <CodePackage Name="Code" Version="1.0.0">
        <SetupEntryPoint>
          <ExeHost>
            <Program>setup.cmd</Program>
            <WorkingFolder>CodePackage</WorkingFolder>
          </ExeHost>
        </SetupEntryPoint>
        <EntryPoint>
          <ExeHost>
            <Program>XXX.exe</Program>
            <WorkingFolder>CodePackage</WorkingFolder>
          </ExeHost>
        </EntryPoint>
      </CodePackage>
    

    setup.cmd

    powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File configure-certs.ps1
    

    configure-certs.ps1

    $store = New-Object System.Security.Cryptography.X509Certificates.X509Store @(
        [System.Security.Cryptography.X509Certificates.StoreName]::My,
        [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)
    
    try
    {
        $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
        $certs = $store.Certificates
    
        $rule = New-Object System.Security.AccessControl.FileSystemAccessRule @(
            "NETWORK SERVICE",
            [System.Security.AccessControl.FileSystemRights]::Read,
            [System.Security.AccessControl.AccessControlType]::Allow)
    
        foreach ($cert in $certs)
        {
            $privateKeyPath = "$($ENV:ProgramData)\Microsoft\Crypto\RSA\MachineKeys\$($cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName)"
            $privateKeyInfo = New-Object System.IO.FileInfo @($privateKeyPath)
    
            $privateKeyAccessControl = $privateKeyInfo.GetAccessControl()
            $privateKeyAccessControl.AddAccessRule($rule)
    
            $privateKeyInfo.SetAccessControl($privateKeyAccessControl)
        }
    }
    finally
    {
        $store.Close()
    }
    

    ApplicationManifest.xml

    ConfigOverrides 作为您要添加设置的包的 ServiceManifestImport 的子项之后

    ...
        <Policies>
          <RunAsPolicy CodePackageRef="Code" UserRef="LocalSystem" EntryPointType="Setup" />
        </Policies>
    ...
    

    DefaultServices 之后作为 ApplicationManifest

    的子项
    ...
          <Principals>
            <Users>
              <User Name="LocalSystem" AccountType="LocalSystem" />
            </Users>
          </Principals>
    ...
    

    【讨论】:

      【解决方案2】:

      我们遇到了类似的问题(我们想将 Kestrel 与 HTTPS 一起使用)并找到了两种方法来实现这一点。

      1. 使用 ARM 脚本和 Keyvault 将证书转储到 VM 的密钥库中,然后使用 X509Store 将其读出。

      这种方法存在问题,因为 AFAIK 服务结构在 NETWORK_SERVICE 下运行并且没有读取私钥的权限。

      1. 我们的后备方案是从密钥库中读取证书和密码作为机密,然后创建一个新的 X509Certificate2。我们通过授予 azure AD 服务主体访问权限来读取机密然后使用 KeyVaultClient 获取它们来做到这一点。

      这里有更好的解释 - https://azure.microsoft.com/en-gb/documentation/articles/key-vault-use-from-web-application

      如果有人能建议在这种情况下什么是最佳实践,我会很高兴 - 我认为第二个选项存在问题,即创建新的 X509Certificate2 还会在磁盘上未清理的临时位置创建证书,但我'肯定还有更多。

      【讨论】:

      • 我知道已经晚了,但是你可以五个网络服务权限来读取证书,看我的回答
      【解决方案3】:

      当我最初创建集群时,它是一个不安全的集群。只需将其重新创建为安全集群,我现在就可以使用我创建的以下帮助方法访问保险库中用于保护集群的证书。

          private static X509Certificate GetServerCertificate(string thumbprint)
          {
              string thumbprint = CertificateThumbprint;
              X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
              store.Open(OpenFlags.ReadOnly);
              var certificateCollection = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
      
              if (certificateCollection.Count == 0)
              {
                  store.Close();
                  string errorMessage = string.Format("Unable to load certificate with thumbprint {0}", thumbprint);
                  throw new ApplicationException(errorMessage);
              }
              else
              {
                  var certificate = new X509Certificate2(certificateCollection[0]);
                  store.Close();
                  return certificate;
              }
          }
      

      可以在此处找到有关创建安全集群的说明:https://azure.microsoft.com/en-us/documentation/articles/service-fabric-cluster-creation-via-arm/

      【讨论】:

        【解决方案4】:

        实际上有一种更简单的方法可以确保 Service Fabric(例如默认 Network_Service)有权访问您的证书。

        我运行一个内部部署的 Service Fabric 集群,过去我不得不做类似的事情,因为我使用证书来加密应用程序机密。

        基本上,您所要做的就是将您的应用程序清单更新为

        1. &lt;Principals&gt; 中定义网络帐户(用于访问证书)
        2. 添加&lt;SecurityAccessPolicy&gt;,将网络帐户与证书相关联
        3. &lt;Certificates&gt; 中标识证书

        示例ApplicationManifest.xml 提取:

        <Principals>
          <Users>
            <User Name="DefaultServiceAccount" AccountType="NetworkService" />
          </Users>
        </Principals>
        <Policies>
          <SecurityAccessPolicies>
            <SecurityAccessPolicy ResourceRef="AppSecretsCert" PrincipalRef="DefaultServiceAccount" ResourceType="Certificate" />
          </SecurityAccessPolicies>
        </Policies>
        <Certificates>
          <SecretsCertificate X509FindValue="YOUR CERT THUMPRINT" Name="AppSecretsCert" />
        </Certificates>
        

        【讨论】:

        • 上面的一个小修正 - &lt;SecretsCertificate /&gt; 用于加密应用程序配置。为了您的 SSL 目的,您应该改用 &lt;EndpointCertificate /&gt;
        猜你喜欢
        • 2018-01-06
        • 1970-01-01
        • 2019-03-26
        • 2016-12-14
        • 2016-12-03
        • 2017-01-08
        • 2021-12-20
        • 1970-01-01
        • 2016-12-08
        相关资源
        最近更新 更多