使用托管标识将 Azure Spring Apps 连接到 Key Vault

注意

基本、标准和企业计划将从 2025 年 3 月中旬开始弃用,停用期为 3 年。 建议转换到 Azure 容器应用。 有关详细信息,请参阅 Azure Spring Apps 停用公告

标准消耗和专用计划将于 2024 年 9 月 30 日开始弃用,并在六个月后完全关闭。 建议转换到 Azure 容器应用。

本文介绍如何为部署到 Azure Spring Apps 的应用创建系统分配的或用户分配的托管标识,并使用该标识来访问 Azure Key Vault。

Azure Key Vault 可以用来安全地存储令牌、密码、证书、API 密钥和应用的其他机密,并对其访问进行严格控制。 可以在 Microsoft Entra ID 中创建托管标识,并向支持 Microsoft Entra 身份验证的任何服务(包括 Key Vault)进行身份验证,而无需在代码中显示任何凭据。

先决条件

  • Azure 订阅。 如果你没有订阅,请在开始之前创建一个试用版订阅。
  • Azure CLI,2.55.0 或更高版本。

提供每个资源的名称

使用以下命令创建变量以保存资源名称。 请务必将占位符替换为你自己的值。

export LOCATION=<location>
export RESOURCE_GROUP=myresourcegroup
export SPRING_APPS=myasa
export APP=springapp-system
export KEY_VAULT=<your-keyvault-name>

创建资源组

资源组是在其中部署和管理 Azure 资源的逻辑容器。 使用 az group create 命令创建一个资源组,以用于包含 Key Vault 和 Spring Cloud,如以下示例所示:

az group create --name ${RESOURCE_GROUP} --location ${LOCATION}

设置密钥保管库

若要创建密钥保管库,请使用 az keyvault create 命令,如以下示例所示:

重要

每个密钥保管库必须具有唯一的名称。

az keyvault create \
    --resource-group ${RESOURCE_GROUP} \
    --name ${KEY_VAULT}

使用以下命令显示应用 URL,然后记下返回的 URL,其格式为 https://${KEY_VAULT}.vault.azure.cn。 在下面的步骤中将使用此值。

az keyvault show \
    --resource-group ${RESOURCE_GROUP} \
    --name ${KEY_VAULT} \
    --query properties.vaultUri --output tsv

现在可以使用 az keyvault secret set 命令将机密放入你的密钥保管库中,如以下示例所示:

az keyvault secret set \
    --vault-name ${KEY_VAULT} \
    --name "connectionString" \
    --value "jdbc:sqlserver://SERVER.database.chinacloudapi.cn:1433;database=DATABASE;"

创建 Azure Spring Apps 服务和应用

安装所有相应的扩展后,使用以下命令创建 Azure Spring Apps 实例:

az extension add --upgrade --name spring
az spring create \
    --resource-group ${RESOURCE_GROUP} \
    --name ${SPRING_APPS}

以下示例按 --system-assigned 参数的请求,创建名为 springapp 且已启用系统分配托管标识的应用。

az spring app create \
    --resource-group ${RESOURCE_GROUP} \
    --service ${SPRING_APPS} \
    --name ${APP} \
    --assign-endpoint true \
    --runtime-version Java_17 \
    --system-assigned
export MANAGED_IDENTITY_PRINCIPAL_ID=$(az spring app show \
    --resource-group ${RESOURCE_GROUP} \
    --service ${SPRING_APPS} \
    --name ${APP} \
    --query identity.principalId --output tsv)

请授予应用对密钥保管库的访问权限

使用以下命令在密钥保管库中为应用授予适当的访问权限:

az keyvault set-policy \
    --name ${KEY_VAULT} \
    --object-id ${MANAGED_IDENTITY_PRINCIPAL_ID} \
    --secret-permissions set get list

注意

对于系统分配的托管标识,请在禁用系统分配的托管标识后使用 az keyvault delete-policy --name ${KEY_VAULT} --object-id ${MANAGED_IDENTITY_PRINCIPAL_ID} 移除你的应用的访问权限。

使用 Spring Boot 简易版构建示例 Spring Boot 应用

此应用有权从 Azure Key Vault 获取机密。 使用 Azure 密钥保管库机密 Spring Boot Starter。 Azure Key Vault 添加为 Spring PropertySource 的实例。 可以像任何外部化配置属性(如文件中的属性)一样方便地访问和使用存储在 Azure Key Vault 中的机密。

  1. 使用以下命令通过 Azure 密钥保管库 Spring Starter 从 start.spring.io 生成示例项目。

    curl https://start.spring.io/starter.tgz -d dependencies=web,azure-keyvault -d baseDir=springapp -d bootVersion=3.2.1 -d javaVersion=17 -d type=maven-project | tar -xzvf -
    
  2. 在应用中指定密钥保管库。

    cd springapp
    vim src/main/resources/application.properties
    
  3. 若要对 Azure Spring Apps 上部署的应用使用托管标识,请将包含以下内容的属性添加到 src/main/resources/application.properties 文件。

    spring.cloud.azure.keyvault.secret.property-sources[0].endpoint=<your-keyvault-url>
    spring.cloud.azure.keyvault.secret.property-sources[0].credential.managed-identity-enabled=true
    

    注意

    必须在 application.properties 文件中添加密钥保管库 URL,如上所示。 否则,在运行时可能不会捕获密钥保管库 URL。

  4. 使用以下示例代码更新 src/main/java/com/example/demo/DemoApplication.java。 此代码从密钥保管库检索连接字符串。

    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    public class DemoApplication implements CommandLineRunner {
    
        @Value("${connectionString}")
        private String connectionString;
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        @GetMapping("get")
        public String get() {
            return connectionString;
        }
    
        public void run(String... args) throws Exception {
            System.out.println(String.format("\nConnection String stored in Azure Key Vault:\n%s\n",connectionString));
        }
    }
    

    如果打开 pom.xml 文件,则可以看到 spring-cloud-azure-starter-keyvault 依赖项,如以下示例所示:

    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-keyvault</artifactId>
    </dependency>
    
  5. 使用以下命令将你的应用部署到 Azure Spring Apps:

    az spring app deploy \
        --resource-group ${RESOURCE_GROUP} \
        --service ${SPRING_APPS} \
        --name ${APP} \
        --source-path
    
  6. 若要测试应用,请使用以下命令访问公共终结点或测试终结点:

    curl https://${SPRING_APPS}-${APP}.microservices.azure.cn/get
    

    响应正文中将返回以下消息:jdbc:sqlserver://SERVER.database.chinacloudapi.cn:1433;database=DATABASE;

清理资源

使用以下命令删除整个资源组(包括新创建的服务实例):

az group delete --name ${RESOURCE_GROUP} --yes

后续步骤