Spring Cloud Azure Key Vault指南

2025/04/24

1. 概述

在本教程中,我们将探讨云原生开发的基本原理以及使用Spring Cloud Azure Key Vault的好处。

2. 什么是Spring Cloud Azure?

Spring Cloud Azure是一套全面的库和工具,专门设计用于促进Spring应用程序和Microsoft Azure服务之间的集成

虽然已经可以将Java应用程序Azure SDK集成,但Spring Cloud Azure的引入将这种集成提升到了一个全新的水平。

通过利用Spring Cloud Azure提供的强大的API集,我们可以方便地与各种Azure服务(例如Azure存储Cosmos DB等)进行交互。

它简化了开发过程并增强了应用程序的整体安全性和性能

Spring Cloud Azure提供了多个模块,用于将我们的应用程序与最相关的Azure服务集成,让我们看几个例子:

我们可以在这里找到可用模块的完整列表。

3. 项目设置

要开始使用Azure云服务,第一步是注册Azure订阅

订阅完成后,让我们安装Azure CLI,此命令行界面工具允许我们从本地计算机与Azure服务进行交互。

接下来,让我们打开命令提示符并运行命令:

> az login

登录后,我们将为订阅创建一个新的资源组:

>az group create --name spring_cloud_azure --location eastus

除了通过命令行创建资源组之外,我们还可以使用Web浏览器中的Azure门户创建新订阅,这为管理我们的Azure资源和订阅提供了直观的界面。

接下来,我们将配置IDE。在本教程中,我们将使用IntelliJ作为IDE。

Azure Toolkit是进行Azure相关开发时非常有用的工具包,它提供专门设计的工具和资源,帮助开发人员在Azure平台上构建和管理应用程序。

因此,让我们在IDE上安装此插件,然后转到Tools > Azure > Login,这将提示我们输入Azure凭据以验证我们对平台的访问。

4. 集成

我们已经完成将Spring应用程序与Azure服务集成的必要准备。

在本教程中,我们将利用官方Azure SDK for Java和专用的Spring Cloud模块将Azure Key Vault服务集成到我们的应用程序中。

4.1 Azure Key Vault

Azure Key Vault是一种基于云的强大服务,可提供安全可靠的方式来存储和管理敏感数据,包括加密密钥、机密和证书

它可以充当应用程序的外部配置源,我们不必将敏感信息定义为配置文件中的值,而是可以将它们定义为Azure Key Vault中的机密,然后在运行时将它们安全地注入到应用程序中。

首先,我们需要在之前创建的资源组上创建一个新的Key Vault。我们可以使用Azure CLI来执行此操作,但如果愿意,我们也可以使用Azure门户

> az keyvault create --name new_keyvault --resource-group spring_cloud_azure --location eastus

创建Key Vault存储后,让我们在Key Vault存储new_keyvault中创建两个机密:

> az keyvault secret set --name my-database-secret --value my-database-secret-value --vault-name new_keyvault
> az keyvault secret set --name my-secret --value my-secret-value --vault-name new_keyvault

第一个机密具有密钥my-database-secret和值my-database-secret-value,而第二个机密具有密钥my-secret和值my-secret-value。

我们还可以在Azure门户上检查并确认这些机密的创建:

4.2 机密客户端

一旦我们定义了这些机密,我们就可以在我们的应用程序上定义SecretClient

SecretClient类提供了一个客户端接口,用于从Azure Key Vault检索和管理机密。

因此让我们定义一个接口:

public interface KeyVaultClient {

    SecretClient getSecretClient();

    default KeyVaultSecret getSecret(String key) {
        KeyVaultSecret secret;
        try {
            secret = getSecretClient().getSecret(key);
        } catch (Exception ex) {
            throw new NoSuchElementException(String.format("Unable to retrieve %s secret", key), ex);
        }
        return secret;
    }
}

KeyVaultClient接口声明了两种方法:

  • 第一个方法getSecretClient()返回SecretClient类的实例。
  • 第二个方法getSecret()提供了一个默认实现,用于从机密客户端检索嵌套在对象KeyVaultSecret中的特定机密。

现在让我们看看定义SecretClient的两种方法,一种是使用标准Azure SDK,另一种是使用Spring Cloud模块。

4.3 不使用Spring Cloud Azure进行集成

在这种方法中,我们将仅使用Microsoft的Azure SDK公开的API来配置SecretClient。

因此,让我们将azure-keyvault-extensions依赖添加到pom.xml文件中:

<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-keyvault-extensions</artifactId>
    <version>1.2.6</version>
</dependency>

现在让我们在application.yaml文件中定义配置SecretClient所需的参数:

azure:
    keyvault:
        vaultUrl: {$myVaultUrl}
        tenantId: {$myTenantId}
        clientId: {$myClientId}
        clientSecret: {$myClientSecret}

我们应该用适当的值替换所有占位符。

一种选择是将值直接硬编码到application.yaml中,但是,这种方法需要存储多个敏感数据,包括clientId或clientSecret,这可能会带来安全风险。

我们不需要对这些值进行硬编码,而是可以为每个敏感数据创建一个机密,然后使用Azure管道将其注入到我们的配置文件中

接下来,我们创建一个KeyVaultProperties类来处理此配置:

@ConfigurationProperties("azure.keyvault")
@ConstructorBinding
public class KeyVaultProperties {
    private String vaultUrl;
    private String tenantId;
    private String clientId;
    private String clientSecret;
    //Standard constructors, getters and setters
}

现在让我们创建客户端类:

@EnableConfigurationProperties(KeyVaultProperties.class)
@Component("KeyVaultManuallyConfiguredClient")
public class KeyVaultManuallyConfiguredClient implements KeyVaultClient {

    private KeyVaultProperties keyVaultProperties;

    private SecretClient secretClient;

    @Override
    public SecretClient getSecretClient() {
        if (secretClient == null) {
            secretClient = new SecretClientBuilder()
                    .vaultUrl(keyVaultProperties.getVaultUrl())
                    .credential(new ClientSecretCredentialBuilder()
                            .tenantId(keyVaultProperties.getTenantId())
                            .clientId(keyVaultProperties.getClientId())
                            .clientSecret(keyVaultProperties.getClientSecret())
                            .build())
                    .buildClient();
        }
        return secretClient;
    }
}

一旦我们注入KeyVaultClient的这个实现,getSecret()默认方法就会返回手动配置的SecretClient对象。

4.4 与Spring Cloud Azure集成

作为此方法的一部分,我们将使用Spring Cloud Azure Key Vault设置SecretClient,并利用该框架的另一个有用功能:将机密注入属性文件。

因此,让我们将spring-cloud-azure-starter-keyvault-secrets依赖添加到pom.xml文件中:

<dependency>
   <groupId>com.azure.spring</groupId>
   <artifactId>spring-cloud-azure-starter-keyvault-secrets</artifactId>
   <version>5.12.0-beta.1</version>
</dependency>

接下来,让我们向application.yaml添加以下属性:

spring:
    cloud:
        azure:
            keyvault:
                secret:
                    endpoint: {$key-vault-endpoint}

我们应该将key-vault-endpoint占位符替换为我们存储的URI,该URI在Azure门户的Resources > {our keyvault} > Vault URI下定义。

现在让我们创建客户端类:

@Component("KeyVaultAutoconfiguredClient")
public class KeyVaultAutoconfiguredClient implements KeyVaultClient {
    private final SecretClient secretClient;

    public KeyVaultAutoconfiguredClient(SecretClient secretClient) {
        this.secretClient = secretClient;
    }

    @Override
    public SecretClient getSecretClient() {
        return secretClient;
    }
}

一旦我们注入KeyVaultClient的这个实现,getSecret()默认方法将返回自动配置的SecretClient对象。除了端点机密之外,我们不需要在application.yaml中指定任何配置值。

Spring Cloud将自动填充所有SecretClient的凭证参数。

我们也可以在属性文件中使用Spring Cloud Azure模块注入机密,让我们在application.yaml中添加属性:

spring:
    cloud:
        azure:
            compatibility-verifier:
                enabled: false
            keyvault:
                secret:
                    property-sources[0]:
                        name: key-vault-property-source-1
                        endpoint: https://spring-cloud-azure.vault.azure.net/
                    property-source-enabled: true

通过设置标志property-source-enabled,Spring Cloud Azure从keyvault-secret-property-sources[0]中指定的Key Vault存储中注入机密。

接下来,我们可以在application.yaml中创建一个动态属性:

database:
    secret:
        value: ${my-database-secret}

当应用程序启动时,Spring Cloud Azure会将${my-database-secret}占位符替换为Azure Key Vault中定义的机密my-database-secret的实际值。

4.5 在属性文件中注入机密

我们已经看到了两种将机密注入属性文件的方法:使用Spring Cloud Azure Key Vault或配置Azure管道。

如果我们只使用Spring Cloud Azure Key Vault,我们应该在application.yaml中对Key Vault端点进行硬编码,以在我们的属性文件上启用注入,这可能会带来安全风险。

另一方面,使用Azure管道,无需对任何值进行硬编码,管道将替换我们application.yaml中的机密。

因此,我们应该仅使用Spring Cloud Azure Key Vault模块来获得自动配置的SecretClient和其他功能的好处,同时将机密注入我们的属性文件的任务委托给Azure管道

4.6 运行应用程序

现在让我们运行Spring Boot应用程序:

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Value("${database.secret.value}")
    private String mySecret;

    private final KeyVaultClient keyVaultClient;

    public Application(@Qualifier(value = "KeyVaultAutoconfiguredClient") KeyVaultAutoconfiguredClient keyVaultAutoconfiguredClient) {
        this.keyVaultClient = keyVaultAutoconfiguredClient;
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class);

    }

    @Override
    public void run(String... args) throws Exception {
        KeyVaultSecret keyVaultSecret = keyVaultClient.getSecret("my-secret");
        System.out.println("Hey, our secret is here ->" + keyVaultSecret.getValue());
        System.out.println("Hey, our secret is here from application properties file ->" + mySecret);
    }
}

我们的应用程序将从自动配置的客户端和启动时注入到application.yaml中的密钥检索机密,然后在控制台上显示两者。

5. 总结

在本文中,我们讨论了Spring Cloud与Azure的集成。

我们了解到,使用Spring Cloud Azure Key Vault而不是Microsoft提供的Azure SDK来集成Azure Key Vault和Spring应用程序会更加简单、简洁。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章