共用方式為


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

向 Azure 服務進行驗證的最佳方式是使用 受控識別,但有些案例則不是選項。 在這些情況下,會使用存取密鑰或秘密。 您應該定期輪替存取金鑰或秘密。

本教學課程示範如何針對使用一組驗證認證的資料庫和服務,自動定期輪替秘密。 如需跨不同資產類型自動調整概念和優點的完整概觀,請參閱 瞭解 Azure Key Vault 中的自動調整

具體而言,本教學課程會使用 Azure 事件方格通知所觸發的函式,輪替儲存在 Azure Key Vault 中的 SQL Server 密碼:

旋轉解決方案圖表

  1. 在密鑰過期日期前 30 天,Key Vault 會將「即將過期」事件發佈到事件網格。
  2. 事件網格會檢查事件訂閱,並使用 HTTP POST 呼叫已訂閱事件的函數應用程式端點。
  3. 函數應用程式接收祕密資訊,產生新的隨機密碼,並使用 Key Vault 中的新密碼為祕密建立新版本。
  4. 功能應用程式使用新密碼更新 SQL Server。

備註

步驟 3 到 4 之間可能會有延遲。 在此期間,Key Vault 中的秘密將無法向 SQL Server 進行驗證。 如果有任何步驟失敗,事件方格會重試兩個小時。

先決條件

如果您沒有現有的 Key Vault 和 SQL Server,您可以使用此部署連結:

顯示標示為「部署至 Azure」的按鈕影像。

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

建立資源群組

您現在會有 Key Vault 和 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 Service 方案
  • 具有 SQL 密碼輪替函式與事件觸發程式和 HTTP 觸發程式的函式應用程式
  • 函數應用程式觸發程序管理所需的儲存體帳戶
  • 供函數應用程式身分識別存取 Key Vault 中祕密的存取原則
  • SecretNearExpiry 事件的事件方格事件訂用帳戶
  1. 選取 Azure 樣本部署連結:

    顯示標示為「部署至 Azure」的按鈕影像。

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

  3. [SQL Server 名稱] 中,輸入包含密碼的 SQL Server 名稱以進行旋轉

  4. Key Vault 名稱中,輸入金鑰保存庫名稱

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

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

  7. 在 [存放庫 URL] 中,輸入函式程式碼 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

如需如何建立函式應用程式及使用受控識別來存取 Key Vault 的詳細資訊,請參閱 從 Azure 入口網站建立函式應用程式如何使用 App Service 和 Azure Functions 的受控識別,以及 使用 Azure 入口網站指派 Key Vault 存取原則

輪替函式

前一個步驟中部署的函式會透過更新 Key Vault 和 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 上找到完整的程式碼。

將秘密新增至 Key Vault

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

az keyvault set-policy --upn <email-address-of-user> --name akvrotation-kv --secret-permissions set delete get list

建立新祕密,其中標籤包含 SQL Server 資源識別碼、SQL Server 登入名稱,以及祕密的有效期間 (以天為單位)。 提供 SQL 資料庫的密碼名稱、初始密碼(在我們的範例中為 “Simple123”),並包含明天設定的到期日。

$tomorrowDate = (get-date).AddDays(+1).ToString("yyy-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 事件,進而觸發函式進行祕密輪替。

測試和驗證

若要確認秘密已輪替,請移至 Key Vault>秘密

顯示如何存取 Key Vault > 祕密的螢幕擷取畫面。

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

移至 [祕密]

建立 Web 應用程式

若要驗證 SQL 認證,請建立 Web 應用程式。 此 Web 應用程式會從 Key Vault 取得秘密、從秘密擷取 SQL 資料庫資訊和認證,以及測試與 SQL Server 的連線。

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

  • 具有系統受控識別的 Web 應用程式
  • 透過 Web 應用程式受控識別存取 Key Vault 中祕密的存取原則
  1. 選取 Azure 樣本部署連結:

    顯示標示為「部署至 Azure」的按鈕影像。

  2. 選取 akvrotation 資源群組。

  3. [SQL Server 名稱] 中,輸入包含密碼的 SQL Server 名稱以進行旋轉

  4. Key Vault 名稱中,輸入金鑰保存庫名稱

  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

瞭解更多資訊