針對使用一組驗證認證的資源,將祕密的輪替自動化

驗證Azure服務的最佳方式是使用 managed identity,但有些情況下這不是選項。 在這些情況下,會使用存取密鑰或秘密。 您應該定期輪替存取金鑰或秘密。

本教學課程示範如何針對使用一組驗證認證的資料庫和服務,自動定期輪替秘密。 欲完整了解 Azure Key Vault 中各種資產類型的自動旋轉概念與優點,請參閱深入理解 Azure Key Vault 的自動旋轉功能

具體來說,這個教學會透過由 Azure 事件方格 通知觸發的函式,輪換儲存在 Azure Key Vault 中的 SQL Server 密碼:

旋轉解決方案圖表

  1. 在秘密到期前三十天,金鑰保存庫 會將「接近到期」事件發布到 Event Grid。
  2. 事件網格會檢查事件訂閱,並使用 HTTP POST 呼叫已訂閱事件的函數應用程式端點。
  3. 功能應用程式會接收秘密資訊,產生新的隨機密碼,並在 金鑰保存庫 中建立新版本的秘密密碼。
  4. 函式應用程式會更新 SQL Server 並輸入新密碼。

備註

步驟 3 到 4 之間可能會有延遲。 在這段期間,金鑰保存庫 裡的秘密無法認證到 SQL Server。 如果有任何步驟失敗,事件方格會重試兩個小時。

先決條件

如果你沒有現有的 金鑰保存庫 和 SQL Server,可以使用這個部署連結:

圖片顯示一個標示為「部署到Azure」的按鈕。

  1. 在 [資源群組] 下,選取 [新建]。 提供群組名稱,在本教學課程中使用 akvrotation
  2. [SQL 管理員登入] 底下,輸入 SQL 系統管理員登入名稱。
  3. 選擇 檢閱 + 創建
  4. 選擇 建立

建立資源群組

你現在會有一個 金鑰保存庫 和一個 SQL Server 實例。 你可以在 Azure CLI 中執行以下指令來驗證此設定:

az resource list -o table -g akvrotation

結果看起來會像下列輸出:

Name                     ResourceGroup         Location    Type                               Status
-----------------------  --------------------  ----------  ---------------------------------  --------
akvrotation-kv           akvrotation      eastus      Microsoft.KeyVault/vaults
akvrotation-sql          akvrotation      eastus      Microsoft.Sql/servers
akvrotation-sql/master   akvrotation      eastus      Microsoft.Sql/servers/databases
akvrotation-sql2         akvrotation      eastus      Microsoft.Sql/servers
akvrotation-sql2/master  akvrotation      eastus      Microsoft.Sql/servers/databases

建立及部署 SQL Server 密碼輪替函式

這很重要

此範本要求金鑰庫、SQL Server 與 Azure 函式必須在同一資源群組中。

接下來,除了其他必要元件之外,使用系統管理的身分識別建立函式應用程式,並部署 SQL Server 密碼輪替函式

函式應用程式需要下列元件:

  • 一個 Azure App 服務 計劃
  • 具有 SQL 密碼輪替函式與事件觸發程式和 HTTP 觸發程式的函式應用程式
  • 函數應用程式觸發程序管理所需的儲存體帳戶
  • 為函式應用程式身分識別指派 Azure RBAC 角色,以存取金鑰保存庫中的密碼
  • SecretNearExpiry 事件的事件方格事件訂用帳戶
  1. 選擇 Azure 範本部署連結:

    圖片顯示一個標示為「部署到Azure」的按鈕。

  2. 在 [ 資源群組] 列表中,選取 akvrotation

  3. SQL Server Name 輸入SQL Server名稱並輸入密碼即可輪換

  4. 金鑰庫名稱 輸入金鑰庫名稱

  5. 函式應用程式名稱中,輸入名稱

  6. 在 [ 秘密名稱] 中,輸入將儲存密碼的秘密名稱

  7. Repo 網址中,輸入功能代碼的 GitHub 位置(https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp.git

  8. 選擇 檢閱 + 創建

  9. 選取 ,創建

選取 [檢閱 + 建立]

完成上述步驟之後,您將會有記憶體帳戶、伺服器陣列和函式應用程式。 你可以在 Azure CLI 中執行以下指令來驗證此設定:

az resource list -o table -g akvrotation

結果看起來會像下列輸出:

Name                     ResourceGroup         Location    Type                               Status
-----------------------  --------------------  ----------  ---------------------------------  --------
akvrotation-kv           akvrotation       eastus      Microsoft.KeyVault/vaults
akvrotation-sql          akvrotation       eastus      Microsoft.Sql/servers
akvrotation-sql/master   akvrotation       eastus      Microsoft.Sql/servers/databases
cfogyydrufs5wazfunctions akvrotation       eastus      Microsoft.Storage/storageAccounts
akvrotation-fnapp        akvrotation       eastus      Microsoft.Web/serverFarms
akvrotation-fnapp        akvrotation       eastus      Microsoft.Web/sites
akvrotation-fnapp        akvrotation       eastus      Microsoft.insights/components

關於如何建立函式應用程式並使用管理身份存取金鑰保存庫,請參見 從Azure入口網站建立函式應用程式如何使用管理身份支援應用程式服務與Azure Functions,以及 提供Azure RBAC 提供金鑰保存庫存取權限。

輪替函式

在前一步部署的函式會使用事件來觸發密碼的輪替,並更新 金鑰保存庫 和 SQL 資料庫。

函式觸發事件

此函式會讀取事件資料並執行旋轉邏輯:

public static class SimpleRotationEventHandler
{
   [FunctionName("AKVSQLRotation")]
   public static void Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
   {
      log.LogInformation("C# Event trigger function processed a request.");
      var secretName = eventGridEvent.Subject;
      var secretVersion = Regex.Match(eventGridEvent.Data.ToString(), "Version\":\"([a-z0-9]*)").Groups[1].ToString();
      var keyVaultName = Regex.Match(eventGridEvent.Topic, ".vaults.(.*)").Groups[1].ToString();
      log.LogInformation($"Key Vault Name: {keyVaultName}");
      log.LogInformation($"Secret Name: {secretName}");
      log.LogInformation($"Secret Version: {secretVersion}");

      SecretRotator.RotateSecret(log, secretName, keyVaultName);
   }
}

秘密輪替邏輯

此輪替方法會從祕密讀取資料庫資訊,建立新的祕密版本,並以新的祕密更新資料庫:

    public class SecretRotator
    {
		private const string CredentialIdTag = "CredentialId";
		private const string ProviderAddressTag = "ProviderAddress";
		private const string ValidityPeriodDaysTag = "ValidityPeriodDays";

		public static void RotateSecret(ILogger log, string secretName, string keyVaultName)
        {
            //Retrieve Current Secret
            var kvUri = "https://" + keyVaultName + ".vault.azure.net";
            var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
            KeyVaultSecret secret = client.GetSecret(secretName);
            log.LogInformation("Secret Info Retrieved");

            //Retrieve Secret Info
            var credentialId = secret.Properties.Tags.ContainsKey(CredentialIdTag) ? secret.Properties.Tags[CredentialIdTag] : "";
            var providerAddress = secret.Properties.Tags.ContainsKey(ProviderAddressTag) ? secret.Properties.Tags[ProviderAddressTag] : "";
            var validityPeriodDays = secret.Properties.Tags.ContainsKey(ValidityPeriodDaysTag) ? secret.Properties.Tags[ValidityPeriodDaysTag] : "";
            log.LogInformation($"Provider Address: {providerAddress}");
            log.LogInformation($"Credential Id: {credentialId}");

            //Check Service Provider connection
            CheckServiceConnection(secret);
            log.LogInformation("Service Connection Validated");
            
            //Create new password
            var randomPassword = CreateRandomPassword();
            log.LogInformation("New Password Generated");

            //Add secret version with new password to Key Vault
            CreateNewSecretVersion(client, secret, randomPassword);
            log.LogInformation("New Secret Version Generated");

            //Update Service Provider with new password
            UpdateServicePassword(secret, randomPassword);
            log.LogInformation("Password Changed");
            log.LogInformation($"Secret Rotated Successfully");
        }
}

你可以在GitHub找到完整的程式碼。

將機密加入 金鑰保存庫

設定存取原則,將 管理秘密 許可權授與使用者:

az role assignment create --role "Key Vault Secrets Officer" --assignee <email-address-of-user> --scope /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.KeyVault/vaults/akvrotation-kv

建立一個新的秘密,標籤包含 SQL Server 資源 ID、SQL Server 登入名稱,以及該秘密的有效期(天數)。 提供 SQL 資料庫的密碼名稱、初始密碼(在我們的範例中為 “Simple123”),並包含明天設定的到期日。

$tomorrowDate = (get-date).AddDays(+1).ToString("yyyy-MM-ddThh:mm:ssZ")
az keyvault secret set --name sqlPassword --vault-name akvrotation-kv --value "Simple123" --tags "CredentialId=sqlAdmin" "ProviderAddress=<sql-database-resource-id>" "ValidityPeriodDays=90" --expires $tomorrowDate

建立具有簡短到期日的祕密,系統會在 15 分鐘內發佈 SecretNearExpiry 事件,進而觸發函式進行祕密輪替。

測試和驗證

要確認密鑰是否已更新,請前往 金鑰保存庫>Secrets

截圖,顯示如何存取 金鑰保存庫 > Secrets.

開啟 sqlPassword 祕密,並檢視原始和已輪替的版本:

移至 [祕密]

建立 Web 應用程式

若要驗證 SQL 認證,請建立 Web 應用程式。 這個網頁應用程式會從 金鑰保存庫 取得秘密,從秘密中提取 SQL 資料庫資訊和憑證,並測試與 SQL Server 的連線。

Web 應用程式需要下列元件:

  • 具有系統受控識別的 Web 應用程式
  • 透過 Web 應用程式受控識別存取金鑰保存庫中密碼的存取原則
  1. 選擇 Azure 範本部署連結:

    圖片顯示一個標示為「部署到Azure」的按鈕。

  2. 選取 akvrotation 資源群組。

  3. SQL Server Name 輸入SQL Server名稱並輸入密碼即可輪換

  4. 金鑰保存庫 Name 欄位中輸入金鑰保存庫的名稱

  5. 在 [ 秘密名稱] 中,輸入密碼儲存所在的秘密名稱

  6. 存放庫 Url 中,輸入Web 應用程式程式碼 GitHub 位置 (https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp-WebApp.git)

  7. 選擇 檢閱 + 創建

  8. 選取 ,創建

開啟 Web 應用程式

移至已部署的應用程式網址:

https://akvrotation-app.azurewebsites.net/

當應用程式在瀏覽器中開啟時,您會看到 [產生的秘密值 ] 和 [ 資料庫連線 ] 值為 true

用 AI 自訂資料庫的旋轉功能

這個教學示範了 SQL Server 的秘密旋轉,但你也可以將旋轉函式調整到其他資料庫類型。 GitHub Copilot 在 VS Code 中可以幫助你修改旋轉函式程式碼,使其符合你特定的資料庫或憑證類型。

I'm using the Azure Key Vault secret rotation tutorial for SQL Server. Help me modify the rotation function to work with PostgreSQL instead. The function should:
1. Generate a new secure password
2. Update the PostgreSQL database user password
3. Store the new password in Key Vault
Show me the changes needed to the C# function code, including the correct PostgreSQL connection library and password update command.

Copilot 也能協助你將此模式調整至其他憑證類型,如 API 金鑰、連線字串或服務帳號密碼。

GitHub Copilot 由 AI 驅動,因此意外與錯誤是有可能發生的。 欲了解更多資訊,請參閱 Copilot常見問題

瞭解更多資訊