Azure サービスに対して認証を行う最善の方法は マネージド ID を使用することですが、オプションではないシナリオがいくつかあります。 このような場合は、アクセス キーまたはシークレットが使用されます。 アクセス キーまたはシークレットを定期的にローテーションする必要があります。
このチュートリアルでは、1 セットの認証資格情報を使用するデータベースとサービスのシークレットの定期的なローテーションを自動化する方法について説明します。 さまざまな資産の種類にわたる自動ローテーションの概念と利点の包括的な概要については、「 Azure Key Vault の自動ローテーションについて」を参照してください。
具体的には、このチュートリアルでは、Azure Event Grid 通知によってトリガーされる関数を使用して、Azure Key Vault に格納されている SQL Server パスワードをローテーションします。
- シークレットの有効期限が切れる 30 日前に、Key Vault から "有効期限が近づいている" ことを示すイベントが Event Grid に発行されます。
- Event Grid がイベント サブスクリプションを確認し、HTTP POST を使用して、このイベントをサブスクライブしている関数アプリ エンドポイントを呼び出します。
- 関数アプリがシークレットの情報を受け取り、新たにランダムなパスワードを生成してから、新しいパスワードを使用して Key Vault にシークレットの新しいバージョンを作成します。
- 関数アプリが新しいパスワードを使用して SQL Server を更新します。
注
手順 3 から 4 の間に遅延が発生する可能性があります。 その間、Key Vault のシークレットは SQL Server に対して認証できません。 いずれかの手順でエラーが発生した場合、Event Grid は 2 時間再試行します。
[前提条件]
- Azure サブスクリプション - 無料アカウントを作成します。
- Azure Key Vault
- SQL Server
既存の Key Vault と SQL Server がない場合は、次のデプロイ リンクを使用できます。
- [リソース グループ] で、 [新規作成] を選択します。 グループに名前を付けます。このチュートリアルでは akvrotation を使用します。
- [ SQL 管理者ログイン] に「SQL 管理者ログイン名」と入力します。
- [Review + create](レビュー + 作成) を選択します。
- を選択し を作成する
これで、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 パスワード ローテーション関数を作成してデプロイする
Von Bedeutung
このテンプレートでは、キー コンテナー、SQL Server、Azure 関数が同じリソース グループ内に存在する必要があります。
次に、他の必要なコンポーネントに加えて、システムマネージド ID を持つ関数アプリを作成し、SQL Server パスワード ローテーション関数をデプロイします
関数アプリには、次のコンポーネントが必要です。
- Azure App Service プラン
- イベント トリガーと http トリガーを使用した SQL パスワード ローテーション関数を含む関数アプリ
- 関数アプリのトリガー管理に必要なストレージ アカウント
- Key Vault 内のシークレットにアクセスするための Function App ID のアクセス ポリシー
- SecretNearExpiry イベントの Event Grid イベント サブスクリプション
Azure テンプレートのデプロイ リンクを選択します。
リソース グループの一覧で、akvrotation を選択します。
[SQL Server 名] に、ローテーションするパスワードを含む SQL Server 名を入力します
キー ボールト名に、キー ボールト名を入力します。
関数アプリ名に、関数アプリ名を入力します。
[ シークレット名] に、パスワードが格納されるシークレット名を入力します
リポジトリ URL に、関数コード GitHub の場所を入力します (https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp.git)
[Review + create](レビュー + 作成) を選択します。
を選択してを作成します。
上記の手順を完了すると、ストレージ アカウント、サーバー ファーム、関数アプリが作成されます。 このセットアップは、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
関数アプリを作成し、マネージド ID を使用して Key Vault にアクセスする方法については、「 Azure portal から関数アプリを作成する」、 App Service と Azure Functions のマネージド ID を使用する方法、および Azure portal を使用して 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 リソース ID、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>Secrets に移動します。
sqlPassword シークレットを開き、元のバージョンとローテーションされたバージョンを表示します。
Web アプリを作成する
SQL 資格情報を確認するには、Web アプリを作成します。 この Web アプリは、Key Vault からシークレットを取得し、シークレットから SQL データベース情報と資格情報を抽出し、SQL Server への接続をテストします。
Web アプリには、次のコンポーネントが必要です。
- システムマネージド ID を持つ Web アプリ
- Web アプリのマネージド ID を介して Key Vault 内のシークレットにアクセスするためのアクセス ポリシー
Azure テンプレートのデプロイ リンクを選択します。
akvrotation リソース グループを選択します。
[SQL Server 名] に、ローテーションするパスワードを含む SQL Server 名を入力します
キー ボールト名に、キー ボールト名を入力します。
[ シークレット名] に、パスワードが格納されているシークレット名を入力します
リポジトリ URL に、Web アプリ コードの GitHub の場所を入力します (https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp-WebApp.git)
[Review + create](レビュー + 作成) を選択します。
を選択してを作成します。
Web アプリを開く
デプロイされたアプリケーション URL に移動します。
https://akvrotation-app.azurewebsites.net/
ブラウザーでアプリケーションが開くと、[ 生成されたシークレット値 ] と [ データベース接続 済み] の値が true と表示されます。