次の方法で共有


Azure Key Vault を使用した MicroProfile の構成

このチュートリアルでは、MicroProfile 構成 API を使って Azure Key Vault からシークレットを取得するよう MicroProfile アプリケーションを構成する方法について説明します。 開発者、構成データを取得し、これを自分のマイクロサービスに挿入する際に、オープン標準 MicroProfile 構成 API のメリットを活かすことができます。

前提条件

  • Azure サブスクリプション。Azure サブスクリプションをまだお持ちでない場合は、MSDN サブスクライバーの特典を有効にするか、または無料のアカウントにサインアップできます。
  • Unix に似た環境用の Azure CLI。 この記事では、Azure CLI の Bash バリアントのみが必要です。
    • Azure CLI をインストールし、 az login コマンドを使って対話形式でサインインし、コードで DefaultAzureCredential を使用する前に Azure にログインします。
      az login
      
    • この記事では、バージョン 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));
    }
}

このサンプルでは、MicroProfileOpen 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

次のステップ

次のリファレンスで詳細を確認できます。