Azure Key Vault を使用した MicroProfile の構成
このチュートリアルでは、MicroProfile 構成 API を使って Azure Key Vault からシークレットを取得するよう MicroProfile アプリケーションを構成する方法について説明します。 開発者、構成データを取得し、これを自分のマイクロサービスに挿入する際に、オープン標準 MicroProfile 構成 API のメリットを活かすことができます。
前提条件
- Azure サブスクリプション。Azure サブスクリプションをまだお持ちでない場合は、MSDN サブスクライバーの特典を有効にするか、または無料のアカウントにサインアップできます。
- Unix に似た環境用の Azure CLI。 この記事では、Azure CLI の Bash バリアントのみが必要です。
- この記事では、バージョン 2.61.0 以降の Azure CLI が必要です。 Azure Cloud Shell を使用している場合は、最新バージョンが既にインストールされています。
- Azure Cloud Shell には、これらの前提条件がすべてプレインストールされています。 詳細については、「Azure Cloud Shell のクイックスタート」を参照してください。
- (Azure Cloud Shell を使うのではなく) このガイドのコマンドをローカルで実行している場合は、次の手順を実行します。
- Unix のようなオペレーティング システム (Ubuntu、macOS、または Linux 用 Windows サブシステムなど) がインストールされているローカル マシンを準備します。
- Java SE 実装バージョン 17 以降 (OpenJDK の Microsoft ビルドなど) をインストールします。
- Maven 3.9.8 以上をインストールします。
- cURL をインストールします。
MicroProfile 構成と Azure Key Vault の接続
Azure Key Vault と MicroProfile 構成 API を組み合わせた場合のメリットを簡単に見てみましょう。 @Inject
および @ConfigProperty
の注釈が付いている、クラス内のフィールドのコード スニペットを次に示します。 注釈で指定されている name
は Azure Key Vault で検索するシークレットの名前で、シークレットが検出されない場合は、defaultValue
が使用されます。 実行時、Azure Key Vault に格納されているシークレット値、またはそのようなシークレットが存在しない場合は既定値が、フィールドに自動的に挿入されます。 この方法でプロパティ値を挿入することには、多くのメリットがあります。 たとえば、コンストラクターと setter メソッドで値を渡す必要がなくなり、構成はコードから外部化されます。 最も大きなメリットの 1 つは、開発環境、テスト環境、運用環境ごとに別個の値のセットを使用できることです。
@Inject
@ConfigProperty(name = "key-name", defaultValue = "Unknown")
String keyValue;
次の例に示すように、MicroProfile 構成には命令によってアクセスすることもできます。
public class DemoClass {
@Inject
Config config;
public void method() {
System.out.println("Hello: " + config.getValue("key-name", String.class));
}
}
このサンプルでは、MicroProfile の Open Liberty 実装を使用します。 互換性のある実装の詳細な一覧については、MicroProfile と互換性のある実装に関するページをご覧ください。 このサンプルでは、Azure でアプリケーションをコンテナー化し、実行する方法についても説明します。
このサンプルでは、MicroProfile Key Vault カスタム ConfigSource ライブラリ用の低摩擦な Azure 拡張機能を使用します。 このライブラリについて詳しくは、ライブラリの README をご覧ください。
ここでは、お使いのローカル コンピューターで、このコードを実行するのに必要な手順を示します。最初は、Azure Key Vault リソースを作成します。
Azure Key Vault リソースを作成する
Azure CLI を使用して Azure Key Vault リソースを作成し、2 つのシークレットを設定します。
まず、Azure にサインインし、サブスクリプションを現在アクティブなサブスクリプションに設定します。
az login
az account set --subscription <subscription-id>
次に、一意の名前 (mp-kv-rg-ejb010424 など) のリソース グループを作成します。
export RESOURCE_GROUP_NAME=mp-kv-rg-ejb010424
az group create \
--name ${RESOURCE_GROUP_NAME} \
--location eastus
次に、一意の名前 (kvejb010424 など) を持つ Azure Key Vault リソースを作成し、2 つのシークレットを追加して、Key Vault URI を環境変数としてエクスポートします。
export KEY_VAULT_NAME=kv-ejb010424
az keyvault create \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${KEY_VAULT_NAME}" \
--location eastus \
--enable-rbac-authorization false
az keyvault secret set \
--vault-name "${KEY_VAULT_NAME}" \
--name secret \
--value 1234
az keyvault secret set \
--vault-name "${KEY_VAULT_NAME}" \
--name anotherSecret \
--value 5678
export AZURE_KEYVAULT_URL=$(az keyvault show \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${KEY_VAULT_NAME}" \
--query properties.vaultUri \
--output tsv)
echo $AZURE_KEYVAULT_URL
後でサンプルを操作できるようライブラリを構成するには、環境変数 AZURE_KEYVAULT_URL
が必要です。 ターミナルを開いたままにします。後でアプリをローカルで実行する際に使用します。
これで完了です。 現在、2 つのシークレットを使用して Azure で Key Vault が実行されています。 これで、サンプル リポジトリを複製し、アプリでこのリソースを使用するように構成できます。
ローカルで起動して実行する
このコード例は、GitHub で入手できるサンプル アプリケーションに基づいています。 前の手順で開いたターミナルに切り替え、以下のコマンドを実行してリポジトリを複製し、アプリをローカルで実行します。
git clone https://github.com/Azure/azure-microprofile.git
cd azure-microprofile
git checkout 1.0.0-beta.3
cd integration-tests/open-liberty-sample
mvn clean package liberty:run
You are in 'detached HEAD' state
に関するメッセージが表示された場合、このメッセージは無視しても問題ありません。
Note
このライブラリは、既定の Azure 資格情報を使って Azure で認証を行います。
Azure CLI az login
コマンドを使ってアカウントをローカルで認証したため、DefaultAzureCredential
はそのアカウントで認証して Azure Key Vault にアクセスします。
The defaultServer server is ready to run a smarter planet
のような出力が表示されるまで待ちます。 新しいターミナルを開き、以下のコマンドを実行してサンプルをテストします。
# Get the value of secret "secret" stored in the Azure key vault. You should see 1234 in the response.
echo $(curl -s http://localhost:9080/config/value/secret -X GET)
# Get the value of secret "anotherSecret" stored in the Azure key vault. You should see 5678 in the response.
echo $(curl -s http://localhost:9080/config/value/anotherSecret -X GET)
# Get the names of secrets stored in the Azure key vault. You should see ["anotherSecret","secret"] in the response.
echo $(curl -s http://localhost:9080/config/propertyNames -X GET)
# Get the name-value paris of secrets stored in the Azure key vault. You should see {"anotherSecret":"5678","secret":"1234"} in the response.
echo $(curl -s http://localhost:9080/config/properties -X GET)
コメントに記載されている、予想される出力が表示されます。 アプリが実行されているターミナルに戻ります。 Ctrl + C キーを押して、アプリを停止します。
サンプル アプリを詳しく調べる
MicroProfile 構成の一般的な動作と、特に MicroProfile Key Vault カスタム ConfigSource ライブラリの動作について詳しく説明します。
ライブラリ依存関係
以下の Maven 依存関係を持つ MicroProfile Key Vault カスタム ConfigSource をアプリに追加します。
<dependency>
<groupId>com.azure.microprofile</groupId>
<artifactId>azure-microprofile-config-keyvault</artifactId>
</dependency>
Azure Key Vault への接続
azure-microprofile-config-keyvault
ライブラリは、Azure API への直接の依存関係を導入せずに、アプリを Azure Key Vault に接続します。 このライブラリには、Azure Key Vault から読み取る方法を認識する MicroProfile 構成仕様の ConfigSource インターフェイスの実装が用意されています。 MicroProfile 構成の実装における残りの部分は、Open Liberty ランタイムによって提供されます。 仕様へのリンクについては、「次の手順」をご覧ください。
ライブラリは、アプリを特定の Key Vault にバインドする azure.keyvault.url
構成プロパティを定義します。 MicroProfile 構成仕様では、実行時に config プロパティの値 (azure.keyvault.url
など) を検出する方法に関する "環境変数マッピング規則" が定義されます。 これらの規則の 1 つは、プロパティが環境変数に変換されることを示しています。 プロパティ azure.keyvault.url
の結果、環境変数 AZURE_KEYVAULT_URL
が参照されます。
サンプル アプリの主なクラス
前述の cURL コマンドにより呼び出されている REST リソースについて調べてみましょう。 この REST リソースは、integration-tests/open-liberty-sample
プロジェクト内のクラス ConfigResource.java
で定義されます。
@Path("/config")
public class ConfigResource {
@Inject
private Config config;
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/value/{name}")
public String getConfigValue(@PathParam("name") String name) {
return config.getConfigValue(name).getValue();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/propertyNames")
public Set<String> getConfigPropertyNames() {
ConfigSource configSource = getConfigSource(AzureKeyVaultConfigSource.class.getSimpleName());
return configSource.getPropertyNames();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/properties")
public Map<String, String> getConfigProperties() {
ConfigSource configSource = getConfigSource(AzureKeyVaultConfigSource.class.getSimpleName());
return configSource.getProperties();
}
private ConfigSource getConfigSource(String name) {
return StreamSupport.stream(config.getConfigSources().spliterator(), false)
.filter(source -> source.getName().equals(name))
.findFirst()
.orElseThrow(() -> new RuntimeException("ConfigSource not found: " + name));
}
}
getConfigValue()
メソッドは、挿入された Config
実装を使って、アプリケーション構成ソースから値を検索します。 Config
実装に対する値の検索は、MicroProfile 構成仕様によって定義された検索アルゴリズムを通じて検出されます。 azure-microprofile-config-keyvault
ライブラリは、Azure Key Vault を構成ソースとして追加します。
getConfigSource()
メソッドは検索アルゴリズムを回避し、プロパティを解決するために AzureKeyVaultConfigSource
に直接進みます。 このメソッドは、getConfigPropertyNames()
メソッドと getConfigProperties()
メソッドによって使用されます。
Azure Container Apps での実行
このセクションでは、アプリをコンテナー化して、ユーザーが割り当てたマネージド ID を Azure Key Vault にアクセスするよう構成し、コンテナー化されたアプリを Azure Container Apps にデプロイします。
アプリをローカルで実行したターミナルに戻ります。このターミナルは、このセクション全体で使用します。
Azure Container Registry のセットアップ
アプリをコンテナー化し、アプリ イメージを格納するには、Azure Container Registry を使用します。
まず、一意の名前 (acrejb010424 など) を使って Azure Container Registry を作成します。
export ACR_NAME=acrejb010424
az acr create \
--resource-group $RESOURCE_GROUP_NAME \
--name $ACR_NAME \
--sku Basic
このコマンドが値を返した後、数分待ってから続行してください。
アプリのコンテナー化
次に、アプリをコンテナー化し、アプリ イメージを Azure Container Registry にプッシュします。 サンプル アプリのパス (azure-microprofile/integration-tests/open-liberty-sample など) を開いていることを確認します。
az acr build \
--registry ${ACR_NAME} \
--image open-liberty-mp-azure-keyvault:latest \
.
Run ID: ca1 was successful after 1m28s
のようなメッセージで終了するビルド出力が表示されます。 同様のメッセージが表示されない場合は、続行する前にトラブルシューティングを行って問題を解決してください。
後でアプリを Azure Container Apps にデプロイするとき、イメージにアクセスするのに必要な接続情報を取得するには、以下のコマンドを使用します。
export ACR_LOGIN_SERVER=$(az acr show \
--name $ACR_NAME \
--query 'loginServer' \
--output tsv)
ユーザーが割り当たマネージド ID のセットアップ
前述のように、ライブラリは既定の Azure 資格情報を使って Azure で認証を行います。 アプリを Azure Container Apps にデプロイするときは、環境変数 AZURE_CLIENT_ID
を設定し、ユーザー定義のマネージド ID として認証するよう DefaultAzureCredential を構成します。このマネージド ID は、Azure Key Vault にアクセスするためのアクセス許可を持っており、後で Azure Container Apps に割り当てられます。
まず、以下のコマンドを使って、一意の名前 (uamiejb010424 など) を持つ、ユーザーが割り当てたマネージド ID を作成します。 詳細については、「ユーザー割り当てマネージド ID を作成する」を参照してください。
export USER_ASSIGNED_IDENTITY_NAME=uamiejb010424
az identity create \
--resource-group ${RESOURCE_GROUP_NAME} \
--name ${USER_ASSIGNED_IDENTITY_NAME}
次に、以下のコマンドを使って、Azure Key Vault からシークレットを取得および一覧表示するためのアクセス許可を付与します。 詳細については、アクセス ポリシーの割り当てに関するページを参照してください。
export USER_ASSIGNED_IDENTITY_OBJECT_ID="$(az identity show \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${USER_ASSIGNED_IDENTITY_NAME}" \
--query 'principalId' \
--output tsv)"
az keyvault set-policy --name "${KEY_VAULT_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--secret-permissions get list \
--object-id "${USER_ASSIGNED_IDENTITY_OBJECT_ID}"
成功したと見なされるには、次の JSON が出力に含まれている必要があります。
"permissions": {
"certificates": null,
"keys": null,
"secrets": [
"list",
"get"
],
"storage": null
}
出力にこの JSON が含まれていない場合、続行する前にトラブルシューティングを行って問題を解決してください。
次のコマンドを使って、ユーザーが割り当てたマネージド ID の ID およびクライアント ID を取得し、後で Azure Key Vault にアクセスできるよう Azure Container Apps に割り当てることができます。
export USER_ASSIGNED_IDENTITY_ID="$(az identity show \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${USER_ASSIGNED_IDENTITY_NAME}" \
--query 'id' \
--output tsv)"
export USER_ASSIGNED_IDENTITY_CLIENT_ID="$(az identity show \
--name "${USER_ASSIGNED_IDENTITY_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--query 'clientId' \
--output tsv)"
echo $USER_ASSIGNED_IDENTITY_ID
echo $USER_ASSIGNED_IDENTITY_CLIENT_ID
Azure Container Apps へのアプリのデプロイ
アプリをコンテナー化し、Azure Key Vault にアクセスできるよう、ユーザーが割り当てたマネージド ID を構成しました。 ここでは、コンテナー化されたアプリを Azure Container Apps にデプロイできます。
まず、Azure Container Apps の環境を作成します。 Azure Container Apps 環境では、コンテナー アプリのグループを囲むセキュリティ保護された境界が作成されます。 同じ環境にデプロイされた Container Apps は、同じ仮想ネットワークにデプロイされ、同じ Log Analytics ワークスペースにログを書き込みます。 次の例に示すように、az containerapp env create コマンドを使って、一意の名前 (acaenvejb010424 など) を持つ環境を作成します。
export ACA_ENV=acaenvejb010424
az containerapp env create \
--resource-group $RESOURCE_GROUP_NAME \
--location eastus \
--name $ACA_ENV
次に、以下の例に示すように、az containerapp create コマンドを使って、一意の名前 (acaappejb010424 など) を持つ Container Apps インスタンスを作成し、Container Registry からイメージをプルした後にアプリを実行します。
export ACA_NAME=acaappejb010424
az containerapp create \
--resource-group ${RESOURCE_GROUP_NAME} \
--name ${ACA_NAME} \
--environment ${ACA_ENV} \
--image ${ACR_LOGIN_SERVER}/open-liberty-mp-azure-keyvault:latest \
--registry-server $ACR_LOGIN_SERVER \
--registry-identity system \
--user-assigned ${USER_ASSIGNED_IDENTITY_ID} \
--env-vars \
AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} \
AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL} \
--target-port 9080 \
--ingress 'external'
Note
パラメーター --user-assigned ${USER_ASSIGNED_IDENTITY_ID}
を使って、ユーザーが割り当てたマネージド ID を Container Apps インスタンスに割り当てます。
Container Apps インスタンスは、パラメーター --env-vars AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL}
で指定された 2 つの環境変数を使って Azure Key Vault にアクセスできます。 AZURE_KEYVAULT_URL
環境変数は、MicroProfile 構成仕様で定義されている環境変数マッピング規則によって参照されている点に留意してください。
次に、以下のコマンドを使って、アプリにアクセスするための完全修飾 URL を取得します。
export APP_URL=https://$(az containerapp show \
--resource-group ${RESOURCE_GROUP_NAME} \
--name ${ACA_NAME} \
--query properties.configuration.ingress.fqdn \
--output tsv)
最後に、以下のコマンドをもう一度実行し、Container Apps インスタンスで実行されているサンプルをテストします。
# Get the value of secret "secret" stored in the Azure key vault. You should see 1234 in the response.
echo $(curl -s ${APP_URL}/config/value/secret -X GET)
# Get the value of secret "anotherSecret" stored in the Azure key vault. You should see 5678 in the response.
echo $(curl -s ${APP_URL}/config/value/anotherSecret -X GET)
# Get the names of secrets stored in the Azure key vault. You should see ["anotherSecret","secret"] in the response.
echo $(curl -s ${APP_URL}/config/propertyNames -X GET)
# Get the name-value paris of secrets stored in the Azure key vault. You should see {"anotherSecret":"5678","secret":"1234"} in the response.
echo $(curl -s ${APP_URL}/config/properties -X GET)
コメントに記載されている、予想される出力が表示されます。 表示されない場合でもアプリが起動している可能性があります。 しばらく待ってから、もう一度やり直してください。
リソースをクリーンアップする
Azure の課金を回避するには、不要なリソースをクリーンアップする必要があります。 リソースが不要になったら、以下のコマンドを実行してリソースをクリーンアップします。
az keyvault delete \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${KEY_VAULT_NAME}"
az keyvault purge \
--name "${KEY_VAULT_NAME}" \
--no-wait
az group delete \
--name ${RESOURCE_GROUP_NAME} \
--yes \
--no-wait
次のステップ
次のリファレンスで詳細を確認できます。