【Azure Key Vault】「シークレット」な情報がApp Serviceのアプリ設定から漏れないようにする(PowerShell編)Tech TIPS

Azure App Serviceのアプリ設定にパスワードなどを格納していると、Azureポータルあるいはデプロイのコードなどから、それが漏れてしまう危険がある。これを「Key Vault」の「シークレット」で解決することが可能だ。その方法のうち、PowerShellでの手順を説明する。

» 2024年08月21日 05時00分 公開
[島田広道デジタルアドバンテージ]
「Tech TIPS」のインデックス

連載目次

Azure Key VaultでApp Serviceの「シークレット」な情報の漏えいを防ぐ(PowerShell編)

対象:Azure App Service、Key Vault(キーコンテナー)、PowerShell


 「Azure App Service」上のアプリケーションから認証が必要な別のサービスを利用するために、IDやパスワード、APIキーなどの秘密情報を「アプリ設定」に保存しておき、アプリケーションのコードから参照する。これはよくある実装だろう。

 ただ、このように保存している秘密情報は、そのApp Serviceの設定を閲覧できるスタッフならば容易に知ることができる。また、リソースをデプロイしているコードのアプリ設定部分には、秘密情報が暗号化されずに露出していることも多いのではないだろうか。

 そこでTech TIPS「【Azure Key Vault】App Serviceのアプリケーション設定から『シークレット』な情報が漏れないようにする(Azureポータル編)」では、「Azure Key Vault」(キーコンテナー)とApp Serviceを連携させることで、秘密情報の漏えいを抑える方法を紹介した。

 本Tech TIPSでは、Azure PowerShellで同じことを実現する手順を紹介したい。基本的な事柄については前出のTech TIPSで説明しているので、そちらに目を通してから本Tech TIPSを読み進めていただきたい。

 App ServiceとKey Vaultは、同じサブスクリプションであらかじめデプロイ済みとする。また、以下に記載しているコマンドレットの実行前には、「Connect-AzAccount」コマンドレットでAzureへログイン(接続)し、「Set-AzContext」コマンドレットでデフォルトのサブスクリプションを選択しておく必要がある。

■執筆時の各種ツール/APIのバージョン


【準備】App Serviceの「マネージドID」を有効化する

 Key Vaultからシークレットを読み出すには、まず参照元のApp Serviceで「マネージドID」を有効化する必要がある。本Tech TIPSでは、「システム割り当て」「ユーザー割り当て」という2種類のマネージドIDのうち、より簡単に利用できる前者で説明する。

 システム割り当てのマネージドIDを有効化するには、以下のように「Set-AzWebApp」コマンドレットを実行する。

Set-AzWebApp -Name <App Service名> `
  -ResourceGroupName <App Serviceリソースグループ名> `
  -AssignIdentity $true # システム割り当てのマネージドIDを有効化

【PowerShell】App Serviceの「マネージドID」を有効化する
※Microsoftのレファレンス: Set-AzWebApp

 「-AssignIdentity」オプションに「$true」を指定すると、システム割り当てのマネージドIDが有効になる。

 この作業はApp Serviceごとに1回行えばよい。

【準備】App ServiceマネージドIDの「プリンシパルID」を取得する

 App ServiceでマネージドIDを有効化すると、「プリンシパルID」(オブジェクトID)という固有のGUIDが割り当てられる。Key Vaultシークレットを参照するには、このプリンシパルIDが必要なので、以下のように「Get-AzWebApp」コマンドレットで取得しておく。

$site = Get-AzWebApp -Name <App Service名> ` # App Serviceを取得
  -ResourceGroupName <>App Serviceリソースグループ名>
$principalId = $site.Identity.PrincipalId # プリンシパルIDを変数に格納
$principalId # 表示

【PowerShell】App ServiceマネージドID(システム割り当て)の「プリンシパルID」を表示する
※Microsoftのレファレンス: Get-AzWebApp

 何も表示されない場合は、システム割り当てのマネージドIDがまだ無効のままと考えられる。前述の手順で有効化してみよう。

 プリンシパルIDは「Get-AzADServicePrincipal」コマンドレットでも取得できる。

$principalId = (Get-AzADServicePrincipal -DisplayName <App Service名>).Id
$principalId # 表示

【PowerShell】Entra IDからApp ServiceマネージドID(システム割り当て)の「プリンシパルID」を取得して表示する
※Microsoftのレファレンス: Get-AzADServicePrincipal

 この作業もApp Serviceごとに1回行えばよい。

【準備】App ServiceにKey Vaultシークレットの取得(参照)を許可する

 次に、App ServiceがKey Vaultシークレットを取得できるように、有効化したマネージドIDを使ってアクセス許可を設定する。

 本Tech TIPSでは、「コンテナーアクセスポリシー」「Azureロールベースのアクセス制御(Azure RBAC)」という2種類のKey Vaultアクセス制御方式のうち、よりシンプルな前者を選んでいるものとして説明する(Microsoftは後者を推奨している)。

 コンテナーアクセスポリシーでApp ServiceにKey Vaultシークレットの取得を許可するには、以下のように「Set-AzKeyVaultAccessPolicy」コマンドレットを実行する。

Set-AzKeyVaultAccessPolicy -VaultName <Key Vault名> `
  -ObjectId $principalId ` # 取得したプリンシパルID(を格納しておいた変数)
  -PermissionsToSecrets Get # 「取得」のみ許可

【PowerShell】App ServiceにKey Vaultシークレットの取得(参照)を許可する
※Microsoftのレファレンス: Set-AzKeyVaultAccessPolicy

 「-ObjectId」オプションの後には、取得しておいたApp ServiceマネージドIDのプリンシパルIDを指定する。

 「-PermissionsToSecrets」オプションの後には、Key Vaultシークレットに対して許可する操作として、唯一必要な「get(取得)」のみ指定している。複数の場合は、操作内容を表す単語「all」「backup」「delete」「get」「list」「purge」「recover」「restore」「set」を選んで、半角コンマで区切りつつ列挙すればよい。

 この作業はマネージドID(プリンシパルID)ごとに1回ずつ行う必要がある。

Vaultシークレットにパスワードなどの秘密情報を保存する

 Key Vaultシークレットに秘密情報を保存するには、以下のように「Set-AzKeyVaultSecret」コマンドレットを実行する。

# 秘密情報を対話的に入力する場合
$securedSecret = Read-Host "秘密情報を入力してください"
  -AsSecureString

# 秘密情報を平文で記載する場合(非推奨)
$securedSecret = ConvertTo-SecureString `
  -String '<パスワードなどの秘密情報>' `
  -AsPlainText

# Key Vaultにシークレットを登録する
Set-AzKeyVaultSecret -VaultName <Key Vault名> `
  -Name <シークレット名> ` # 半角英数字とハイフンで127文字以内
  -SecretValue $securedSecret

【PowerShell】Key Vaultシークレットにパスワードなどの秘密情報を保存する
※Microsoftのレファレンス: Read-HostConvertTo-SecureStringSet-AzKeyVaultSecret

 <シークレット名>は、半角の英数字およびハイフン、かつ127文字以内で指定する必要がある。

 この作業はKey Vaultシークレットごとに1回ずつ行う必要がある。

App ServiceからKey Vaultシークレットを参照(取得)する

 App Service からKey Vaultシークレットを参照して、そこに保存してある秘密情報をアプリ設定に格納するには、以下のようにアプリ設定を変更する。

$site = Get-AzWebApp -Name <App Service名> ` # App Serviceを取得
  -ResourceGroupName <App Serviceのリソースグループ名>
$appSettings = $site.SiteConfig.AppSettings # 既存のアプリ設定を抽出

# 既存のアプリ設定の一覧をハッシュテーブルに変換
$newAppSetHash = @{}
$appSettings | ForEach-Object {
  $newAppSetHash[$_.Name] = $_.value
}

# シークレットを参照するアプリ設定をハッシュテーブルに追加
$appSetName = "<アプリ設定の名称>" # 半角の英数字とピリオド、アンダースコア
$appSetValue = "@Microsoft.KeyVault(VaultName=<Key Vault名>;SecretName=<シークレット名>)"
$newAppSetHash[$appSetName] = $appSetValue

# ハッシュテーブルからアプリ設定を変更
Set-AzWebApp -Name $site.Name `
  -ResourceGroupName $site.ResourceGroup `
  -AppSettings $newAppSetHash

【PowerShell】App ServiceからKey Vaultシークレットを参照(取得)する
※Microsoftのレファレンス: Get-AzWebAppForEach-ObjectハッシュテーブルSet-AzWebApp

 PowerShellの場合、アプリ設定の一部のみ変更することはできず、全てのアプリ設定を指定して更新する必要がある。今回のような新規追加の場合、まず既存のアプリ設定を全て読み出し、それに新たなアプリ設定を追加して反映するという手順を踏む必要がある点に注意してほしい。

 追加したいアプリ設定が複数の場合は、その名称と値の組み合わせを上記リストのハッシュテーブル「$newAppSetHash」に追加すればよい。

 <アプリ設定の名称>は、半角の英数字とピリオド、アンダースコアで指定する必要がある。

 上記リストを実行すると、自動的にアプリケーションのリサイクルがかかり、一時的にWebサイト/アプリの応答が途絶することがあるので注意が必要だ。

 上記で追加したアプリ設定に対して「デプロイスロットの設定」を「オン」にする、すなわち、スロット固有にするには、以下も実行する必要がある。

# 「デプロイスロットの設定」が「オン」である既存のアプリ設定名一覧を取得
$slotConfigNames = Get-AzWebAppSlotConfigName $site
$appSetNames = $slotConfigNames.AppSettingNames # アプリ設定のみ抽出

# 取得した一覧に、さきほど追加したアプリ設定名を追加
$newAppSetNames = $appSetNames + $appSetName 

# App Serviceに反映
Set-AzWebAppSlotConfigName $site -AppSettingNames $newAppSetNames

【PowerShell】追加したアプリ設定の「デプロイスロットの設定」を「オン」にする
※Microsoftのレファレンス: Get-AzWebAppSlotConfigNameSet-AzWebAppSlotConfigName

 「デプロイスロットの設定」を「オン」にするには、「Get-AzWebAppSlotConfigName」コマンドレットで既存のアプリ設定名の一覧を取得し、それに新たなアプリ設定名を追加して、「Set-AzWebAppSlotConfigName」コマンドレットで反映すればよい。

Vaultシークレットが正しく参照できているかどうか確認する

 設定が完了したら、App ServiceからKey Vaultシークレットが正しく参照(取得)できているかどうか確認しよう。それには、前述のリスト内の<アプリ設定の名称>($appSetName変数)と同じ名前の環境変数の内容がKey Vaultシークレットの内容と同じであるかどうかチェックすればよい。

 以下ではLinuxベースのApp ServiceにSSHで接続し、「printenv <アプリ設定の名称>」と実行して環境変数の内容を表示させている。

App Serviceに接続したSSHでKey Vaultシークレットの参照に成功しているかどうかを確認する App Serviceに接続したSSHでKey Vaultシークレットの参照に成功しているかどうかを確認する

 参照に失敗していると、前述の「@Microsoft〜」から始まる参照文字列が(展開されることなく)そのまま環境変数の内容として格納されているはずだ。その場合はアプリ設定などを再確認すること。

 上記の例から分かるように、Key Vaultシークレットへの参照を設定していても、アプリケーションのインスタンス内部で環境変数など参照可能なユーザーには、秘密情報が閲覧されてしまう。本Tech TIPSで紹介している方法では漏えいの危険性を下げることはできても、完全に防ぐことはできない。引き続きアクセス権の制限などに注意を払う必要がある。

Key Vaultシークレットを更新する

 認証情報の更新に伴い、Key Vaultシークレットの内容も更新しなければならない場合は、追加時のコマンドラインのうち「-SecretValue」オプションの値のみ<更新された秘密情報>(SecureString型)に差し替えて実行する。

Set-AzKeyVaultSecret -VaultName <Key Vault名> `
  -Name <シークレット名> `
  -SecretValue <更新された秘密情報> ` # SecureString型


 App Serviceを放置した場合、上記コマンドレットを実行してから24時間以内に自動で最新の内容(更新した内容)が反映される。

 すぐに反映したいなら、アプリ設定を読み出して、変更することなく、そのまま反映する。

$site = Get-AzWebApp -Name <App Service名> ` # サイトを取得
  -ResourceGroupName <App Serviceのリソースグループ名>
$appSettings = $site.SiteConfig.AppSettings # 既存のアプリ設定を抽出

# 既存のアプリ設定の一覧をハッシュテーブルに変換
$newAppSetHash = @{}
$appSettings | ForEach-Object {
  $newAppSetHash[$_.Name] = $_.value
}

# ハッシュテーブルからアプリ設定の更新を実行
Set-AzWebApp -Name $site.Name `
  -ResourceGroupName $site.ResourceGroup `
  -AppSettings $newAppSetHash


 するとアプリケーションのリサイクルとKey Vaultシークレットの再読み出しが実行され、最新のKey Vaultシークレットの内容が反映される。

「Tech TIPS」のインデックス

Tech TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。