共用方式為


使用 Azure 金鑰保存庫 設定 MicroProfile

本教學課程示範如何使用 MicroProfile 設定 APIAzure 金鑰保存庫 擷取秘密的 MicroProfile 應用程式。 開發人員受益於開放式標準 MicroProfile 設定 API,以擷取和插入組態數據至其微服務。

必要條件

  • Azure 訂用帳戶;如果您還沒有 Azure 訂用帳戶,您可以啟用 MSDN 訂閱者權益 或註冊 免費帳戶
  • 適用於 Unix 的 Azure CLI 環境。 本文只需要 Azure CLI 的 Bash 變體。
    • 安裝 Azure CLI,並使用 az login 命令以互動方式登入 Azure,再使用 DefaultAzureCredential 程式代碼。
      az login
      
    • 本文需要使用至少 Azure CLI 2.61.0 版。 若您使用的是 Azure Cloud Shell,即已安裝最新版本。
  • Azure Cloud Shell 已預先安裝上述全部必要條件。 如需詳細資訊,請參閱 Azure Cloud Shell 快速入門
  • 如果您在本地執行本指南中的命令 (而不是使用 Azure Cloud Shell),請完成下列步驟:
    • 使用已安裝類似 Unix 的作業系統 (例如 Ubuntu、macOS 或 Windows 子系統 Linux 版) 準備本機電腦。
    • 安裝 Java SE 實作版本 17 或更新版本(例如, Microsoft OpenJDK 的組建)。
    • 安裝 Maven 3.9.8 或更高版本。
    • 安裝 cURL

使用 Azure 金鑰保存庫 連線 MicroProfile 組態

讓我們快速了解結合 Azure 金鑰保存庫 和 MicroProfile 組態 API 的強大功能。 以下是以和@ConfigProperty標註@Inject之類別中欄位的代碼段。 name註出指定的 是 Azure 金鑰保存庫 中要查閱的秘密名稱,如果defaultValue找不到秘密,則會使用 。 儲存在 Azure 金鑰保存庫 中的秘密值,或不存在這類秘密的預設值,會在運行時間自動插入欄位中。 以這種方式插入屬性值可提供許多優點。 例如,您不再需要在建構函式和 setter 方法中傳遞值,而且組態會從程式碼外部化。 其中一個最強大的優點是針對開發、測試和生產環境使用不同的值集合。

@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 的低摩擦 Azure 擴充功能,金鑰保存庫 自定義 ConfigSource 連結庫。 如需此連結庫的詳細資訊,請參閱 連結庫自述檔

以下是在本機計算機上執行此程式碼所需的步驟,從建立 Azure 金鑰保存庫 資源開始。

建立 Azure Key Vault 資源

您可以使用 Azure CLI 來建立 Azure 金鑰保存庫 資源,並填入兩個秘密。

首先,登入 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

現在建立具有唯一名稱的 Azure 金鑰保存庫 資源(例如 kvejb010424)、新增兩個秘密,並將 金鑰保存庫 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 ,才能將連結庫設定為稍後使用範例。 讓終端機保持開啟,並在稍後在本機執行應用程式。

介紹完畢 您現在已使用兩個秘密在 Azure 中執行 金鑰保存庫。 您現在可以複製範例存放庫,並將其設定為在應用程式中使用此資源。

在本機啟動並執行

此範例是以 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訊息,此訊息是安全的忽略。

注意

連結庫會使用 預設 Azure 認證 在 Azure 中驗證。

由於您已透過 Azure CLI az login 命令在本機驗證帳戶,因此會DefaultAzureCredential使用該帳戶進行驗證,以存取 Azure 金鑰保存庫。

等到您看到類似的 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 Config 的運作方式,以及 MicroProfile 金鑰保存庫 自定義 ConfigSource 連結庫的運作方式。

連結庫相依性

在應用程式中包含 MicroProfile 金鑰保存庫 自定義 ConfigSource,並具有下列 Maven 相依性:

<dependency>
  <groupId>com.azure.microprofile</groupId>
  <artifactId>azure-microprofile-config-keyvault</artifactId>
</dependency>

連線到 Azure 金鑰保存庫

連結庫會將azure-microprofile-config-keyvault您的應用程式連線至 Azure 金鑰保存庫,而不需要在 Azure API 上引進任何直接相依性。 連結庫提供 MicroProfile Config 規格 ConfigSource 介面的實作,以瞭解如何從 Azure 金鑰保存庫 讀取。 MicroProfile Config 的其餘實作是由 Open Liberty 運行時間提供。 如需規格的連結,請參閱 後續步驟

連結庫會定義組態屬性, azure.keyvault.url 以將您的應用程式系結至特定的密鑰保存庫。 MicroProfile 組態規格會定義「環境變數對應規則」,以瞭解如何在運行時間探索組態屬性的值,例如 azure.keyvault.url。 其中一個規則指出屬性會轉換成環境變數。 屬性 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 實作來查閱應用程式組態來源的值。 透過 MicroProfile Config 規格所定義的搜尋演算法,找到實作上 Config 的任何值查閱。 連結庫會將 azure-microprofile-config-keyvault Azure 金鑰保存庫 新增為組態來源。

方法 getConfigSource() 會避免搜尋演算法,並直接前往 AzureKeyVaultConfigSource 來解析屬性。 和 getConfigProperties() 方法會使用getConfigPropertyNames()這個方法。

在 Azure Container Apps 上執行

在本節中,您會容器化應用程式、設定使用者指派的受控識別來存取 Azure 金鑰保存庫,並在 Azure Container Apps 上部署容器化應用程式。

切換回您在本機執行應用程式的終端機,並在本節中使用它。

設定 Azure Container Registry

您可以使用 Azure Container Registry 來容器化應用程式並儲存應用程式映像。

首先,建立具有唯一名稱的 Azure Container Registry,例如 acrejb010424

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)

設定使用者指派的受控識別

如先前所述,連結庫會使用 預設 Azure 認證 在 Azure 中驗證。 當您將應用程式部署至 Azure Container Apps 時,您會將環境變數AZURE_CLIENT_ID設定為設定 DefaultAzureCredential,以使用者定義受控識別進行驗證,其具有存取 Azure 金鑰保存庫 的許可權,稍後會指派給 Azure Container Apps。

首先,使用下列命令來建立具有唯一名稱的使用者指派受控識別,例如 uamiejb010424。 如需詳細資訊,請參閱建立使用者指派的受控識別

export USER_ASSIGNED_IDENTITY_NAME=uamiejb010424
az identity create \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${USER_ASSIGNED_IDENTITY_NAME}

接下來,使用下列命令授與它從 Azure 金鑰保存庫 取得和列出秘密的許可權。 如需詳細資訊,請參閱 指派存取原則

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,請先進行疑難解答並解決問題,再繼續進行。

然後,使用下列命令來擷取使用者指派受控識別的標識碼和用戶端標識碼,以便稍後將它指派給 Azure Container Apps,以存取 Azure 金鑰保存庫:

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 金鑰保存庫。 現在您可以在 Azure Container Apps 上部署容器化應用程式。

首先,建立 Azure Container Apps 的環境。 Azure 容器應用程式中的環境會在容器應用程式群組周圍建立安全界限。 部署至相同環境的容器應用程式會部署在相同的虛擬網路中,並將記錄寫入相同的 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 命令建立具有唯一名稱的 Container Apps 實例(例如 acaappejb010424),以在從 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'

注意

您可以使用 參數 --user-assigned ${USER_ASSIGNED_IDENTITY_ID},將使用者指派的受控識別指派給 Container Apps 實例。

Container Apps 實例可以使用參數 --env-vars AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL}中提供的兩個環境變數來存取 Azure 金鑰保存庫。 請記住, AZURE_KEYVAULT_URL 由於 MicroProfile Config 規格所定義的環境變數對應規則,因此會參考環境變數。

然後,使用下列命令擷取完整 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

下一步

您可以從下列參考進行深入了解: