在Azure Service Fabric中加载SSL证书以获取自定义TCP服务

时间:2016-08-28 05:31:55

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

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

4 个答案:

答案 0 :(得分:1)

我们遇到了类似的问题(我们希望使用带有HTTPS的Kestrel),并找到了实现此目的的两种方法。

  1. 使用ARM脚本&amp ;;将证书转储到VM的密钥库中。 Keyvault然后使用X509Store读出它。
  2. 这种方法存在问题,因为AFAIK服务结构在NETWORK_SERVICE下运行,并且没有读取私钥的权限。

    1. 我们的后备是阅读证书&密码作为密钥库的秘密,然后创建一个新的X509Certificate2。我们通过提供天蓝色AD服务主体访问来读取秘密,然后使用KeyVaultClient来获取它们。
    2. 这里有更好的解释 - https://azure.microsoft.com/en-gb/documentation/articles/key-vault-use-from-web-application

      我很乐意,如果有人可以建议在这种情况下最佳做法 - 我认为第二个选项有问题,创建一个新的X509Certificate2也在磁盘上的临时位置创建证书,但没有清理,但我和#39;我相信还有更多。

答案 1 :(得分:1)

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

    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/

答案 2 :(得分:1)

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

下面的完整示例,注意我在所有LocalMachine / My证书上设置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

<强>配置-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>
...

答案 3 :(得分:1)

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

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

基本上,您只需将Application Manifest更新为

即可
  1. <Principals>
  2. 中定义网络帐户(用于访问证书)
  3. 添加将网络帐户与证书相关联的<SecurityAccessPolicy>
  4. <Certificates>
  5. 中识别证书

    示例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>