Azure Service Fabric 中的中央秘密服務

中央秘密服務 (CSS) 也稱為「中央密碼存放區」,是一種 Service Fabric 系統服務,其目的是要保護叢集內的秘密。 CSS 可簡化 SF 應用程式的秘密管理,而不需要依賴加密的參數。

中央秘密服務是持久、複寫的叢集中秘密快取;儲存在 CSS 中的秘密會待用加密至客戶提供的加密憑證。 CSS 提供用戶端 API 用於秘密管理,可供實體驗證為叢集或叢集系統管理員使用者存取。 Service Fabric 執行階段應用程式模型會與 CSS 整合,讓應用程式參數的宣告成為 CSS 秘密參考。

CSS 也有助於佈建宣告為 KeyVault 秘密 URI 的應用程式秘密,結合 Azure 部署的 Service Fabric 應用程式的受控識別

中央秘密服務並非要用來取代專用的外部秘密管理服務,例如 Azure Key Vault。

注意

在執行早於 7.1.CU3 版本的 SF 叢集上啟用 CSS 時,如果叢集設定為使用 Windows 驗證或 EncryptionCertificateThumbprint 宣告不正確,或未安裝對應的憑證,則啟動可能會失敗,並讓 CSS 處於永久狀況不良的狀態。 無論是哪一種情況,建議將叢集升級為比 7.1. CU3 更新的 SF 執行階段版本再繼續。

啟用中央秘密服務

若要啟用中央秘密服務,請更新叢集設定,如下所述。 建議您使用與您的叢集憑證不同的加密憑證。 此憑證必須安裝在所有節點上。

{ 
    "fabricSettings": [
        {
            "name":  "CentralSecretService",
            "parameters":  [
                {
                    "name":  "DeployedState",
                    "value":  "enabled"
                },
                {
                    "name" : "EncryptionCertificateThumbprint",
                    "value": "<thumbprint>"
                },
                {
                    "name":  "MinReplicaSetSize",
                    "value":  "1"
                },
                {
                    "name":  "TargetReplicaSetSize",
                    "value":  "3"
                }
            ]
        }
    ]
}

注意

在 Service Fabric 版本 8.0 中引進的組態設定 "DeployedState" 是啟用或停用 CSS 的慣用機制;此函式過去是由舊版的組態設定 "IsEnabled" 提供,現在已被視為過時。

中央秘密服務秘密模型

中央秘密服務 API 會公開兩個類型:秘密資源和秘密版本。 秘密資源類型概念上代表用於特定用途的單一秘密版本系列;範例包括:連接字串、密碼、端點憑證。 秘密資源類型的物件包含與該秘密相關聯的中繼資料,尤其是類型、內容類型和描述。 秘密版本類型代表其相關聯秘密的特定執行個體,並將秘密儲存為純文字 (加密);繼續進行上述範例,秘密版本包含目前的密碼值,憑證物件在當月底之前都是有效。更新這些秘密時,應該產生新的秘密版本 (並新增至 CSS)。

將模型具體化時,下列是在 CSS 實作中實作和強制執行的規則:

  • 秘密資源可能有零或多個版本
  • 每個秘密版本都是特定秘密資源的子系;版本只能有一個父資源
  • 可能會刪除個別的秘密版本,而不會影響相同秘密的其他版本
  • 刪除秘密資源會導致刪除其所有版本
  • 秘密版本的值不可變

宣告秘密資源

您可以使用 REST API 來建立秘密資源。

注意

如果叢集使用 Windows 驗證但沒有 HttpGateway 憑證,則會透過不安全的 HTTP 通道傳送 REST 要求。 若要啟用此通道的 TLS,應更新叢集定義以指定 HTTP 閘道伺服器憑證。

若要使用 REST API 建立 supersecret 秘密資源,請對 https://<clusterfqdn>:19080/Resources/Secrets/supersecret?api-version=6.4-preview 進行 PUT 要求。 您必須使用叢集憑證或系統管理用戶端憑證來進行驗證,以建立秘密資源。

$json = '{"properties": {"kind": "inlinedValue", "contentType": "text/plain", "description": "supersecret"}}'
Invoke-WebRequest  -Uri https://<clusterfqdn>:19080/Resources/Secrets/supersecret?api-version=6.4-preview -Method PUT -CertificateThumbprint <CertThumbprint> -Body $json

設定秘密值

使用下列指令碼來使用 REST API 以設定秘密值。

$Params = '{"properties": {"value": "mysecretpassword"}}'
Invoke-WebRequest -Uri https://<clusterfqdn>:19080/Resources/Secrets/supersecret/values/ver1?api-version=6.4-preview -Method PUT -Body $Params -CertificateThumbprint <ClusterCertThumbprint>

檢查秘密值

Invoke-WebRequest -CertificateThumbprint <ClusterCertThumbprint> -Method POST -Uri "https:<clusterfqdn>/Resources/Secrets/supersecret/values/ver1/list_value?api-version=6.4-preview"

在您的應用程式中使用秘密

應用程式可以從 CSS 取用秘密,方法是將它宣告為環境變數,或指定應將秘密純文字序列化的路徑。 遵循下列步驟來參考 CSS 秘密:

  1. 使用下列程式碼片段,在 settings.xml 檔案中新增區段。 請注意,該值的格式為 {secretname:version}。
     <Section Name="testsecrets">
      <Parameter Name="TopSecret" Type="SecretsStoreRef" Value="supersecret:ver1"/
     </Section>
  1. 匯入 ApplicationManifest.xml 中的區段。
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="testservicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
<Policies>
 <ConfigPackagePolicies CodePackageRef="Code">
   <ConfigPackage Name="Config" SectionName="testsecrets" EnvironmentVariableName="SecretPath" />
   </ConfigPackagePolicies>
</Policies>
</ServiceManifestImport>

範例 1:將秘密掛接至容器。 在容器內提供秘密所需的唯一變更,就是在 <ConfigPackage>specify 掛接點。 下列程式碼片段是修改過的 ApplicationManifest.xml

   <ServiceManifestImport>
       <ServiceManifestRef ServiceManifestName="testservicePkg" ServiceManifestVersion="1.0.0" />
       <ConfigOverrides />
       <Policies>
         <ConfigPackagePolicies CodePackageRef="Code">
           <ConfigPackage Name="Config" SectionName="testsecrets" MountPoint="C:\secrets" EnvironmentVariableName="SecretPath" />
           <!-- Linux Container
            <ConfigPackage Name="Config" SectionName="testsecrets" MountPoint="/mnt/secrets" EnvironmentVariableName="SecretPath" />
           -->
         </ConfigPackagePolicies>
       </Policies>
     </ServiceManifestImport>

秘密可在容器內的掛接點底下取得。

範例 2:指定 Type='SecretsStoreRef 以將秘密繫結至程序環境變數。 下列程式碼片段是如何在 ServiceManifest.xml 中將 supersecret 版本 ver1 繫結至環境變數 MySuperSecret 的範例。

   <EnvironmentVariables>
     <EnvironmentVariable Name="MySuperSecret" Type="SecretsStoreRef" Value="supersecret:ver1"/>
   </EnvironmentVariables>

環境變數 SecretPath 將指向儲存所有秘密的目錄。 testsecrets 區段底下所列的每個參數都會儲存在不同的檔案中。 應用程式現在可以使用秘密,如下所示:

secretValue = IO.ReadFile(Path.Join(Environment.GetEnvironmentVariable("SecretPath"),  "TopSecret"))

輪替中央秘密服務加密憑證

請務必注意,憑證在超出過期日後仍有效可供解密。 目前,建議您在輪替之後繼續佈建過去的加密憑證,以降低鎖定的機會。 輪替 CSS 加密憑證需要下列步驟:

  1. 將新憑證佈建至叢集的每個節點。 這次,請勿移除/繼續佈建先前的加密憑證。
  2. 開始叢集設定升級,將 EncryptionCertificateThumbprint 的值變更為新憑證的 SHA-1 指紋。 升級完成時,CSS 會開始將其現有的內容重新加密為新的加密憑證。 在此時間點之後新增至 CSS 的所有秘密都會直接對新加密憑證加密。 由於將所有受到新憑證保護之秘密的收斂都是非同步,因此,必須在所有節點上保持安裝舊的加密憑證,並且可供 CSS 使用。

從您的叢集移除中央秘密服務

從叢集移除安全中央秘密服務需要兩個升級。 第一個升級功能會停用 CSS,而第二個升級則會從叢集定義中移除服務,其包括永久刪除其內容。 這個兩階段的程序可避免意外刪除服務,並可協助確保在移除程序期間不會有任何遺留的 CSS 相依性。 此功能可從 SF 版本 8.0 以上取得。

步驟 1:將 CSS DeployedState 更新為 removing

"IsEnabled" = "true" 或從 "DeployedState" = "enabled" 將叢集定義升級至

{
    "name":  "DeployedState",
    "value":  "removing"
}

一旦中央秘密服務進入已部署狀態 Removing,它就會拒絕所有連入的秘密 API 呼叫,不論是直接 REST 呼叫,還是透過包含 SecretStoreRefs 或 KeyVaultReferences 的服務啟用。 叢集中仍相依於 CSS 的任何應用程式或元件會進入警告狀態。 如果發生此情況,就應該將升級至已部署狀態 Removing 復原;如果該升級已成功,則應該起始新的升級,將 CSS 變更回 DeployedState = Enabled。 如果中央秘密服務在部署狀態 Removing 下收到要求,則會傳回 HTTP 代碼 401 (未授權),並使其處於警告的健全狀態。

步驟 2:將 CSS DeployedState 更新為 disabled

將叢集定義從 "DeployedState" = "removing" 升級至

{
    "name":  "DeployedState",
    "value":  "disabled"
}

中央秘密服務應該不再會於叢集中執行,且將不會出現在系統服務清單中。 CSS 的內容無可補救地遺失。

下一步