ConfigData API

推荐使用 ConfigData API 替代以前的 Bootstrap 上下文,因为它提供了更灵活的配置来源顺序,允许指定要导入的配置系统和导入顺序。此外,文章介绍了 Vault 配置选项,例如配置位置、禁用 Vault 配置和定制基础设施类。

Spring Boot 从 2.4 版本开始提供 ConfigData API,允许声明配置源并将其导入为属性源。

Spring Boot provides since version 2.4 a ConfigData API that allows the declaration of configuration sources and importing these as property sources.

从 3.0 版本开始,Spring Cloud Vault 使用 ConfigData API 将 Vault 的密钥后端装入为属性源。在之前的版本中,使用了 Bootstrap 上下文。ConfigData API 更加灵活,因为它允许指定要导入哪些配置系统以及按什么顺序导入。

Spring Cloud Vault uses as of version 3.0 the ConfigData API to mount Vault’s secret backends as property sources. In previous versions, the Bootstrap context was used. The ConfigData API is much more flexible as it allows specifying which configuration systems to import and in which order.

你可以通过设置配置属性 spring.cloud.bootstrap.enabled=true 或包含依赖项 org.springframework.cloud:spring-cloud-starter-bootstrap 来启用引导上下文。使用引导上下文应该是非常罕见的,因此我们建议使用配置数据 API,以便在属性源排序方面有更大的灵活性。

You can enable the bootstrap context either by setting the configuration property spring.cloud.bootstrap.enabled=true or by including the dependency org.springframework.cloud:spring-cloud-starter-bootstrap. Using the boostrap context should be only rarely required hence we recommend using the Config Data API for more flexibility regarding property source ordering.

ConfigData Locations

您可以通过一个或多个从 Vault 实质化的 PropertySource 装入 Vault 配置。Spring Cloud Vault 支持两个配置位置:

You can mount Vault configuration through one or more PropertySource that are materialized from Vault. Spring Cloud Vault supports two config locations:

  • vault:// (default location)

  • vault:///<context-path> (contextual location)

使用默认位置挂载所有启用 Secret Backends 的属性源。如果没有进行进一步配置,Spring Cloud Vault 会在 /secret/${spring.application.name} 挂载键值后端。每个激活的配置文件都通过遵循 /secret/$\{spring.application.name}/${profile} 的格式添加另一个上下文路径。像 spring-cloud-config-databases 这样的其他模块添加到类路径后,会提供其他秘密后端配置选项,如果这些选项启用,会作为属性源进行挂载。

Using the default location mounts property sources for all enabled Secret Backends. Without further configuration, Spring Cloud Vault mounts the key-value backend at /secret/${spring.application.name}. Each activated profile adds another context path following the form /secret/$\{spring.application.name}/${profile}. Adding further modules to the classpath, such as spring-cloud-config-databases, provides additional secret backend configuration options which get mounted as property sources if enabled.

如果您希望控制从 Vault 作为`PropertySource`挂载的上下文路径,您可以使用上下文位置 (vault:///my/context/path) 或配置xref:secret-backends.adoc#vault.config.backends.configurer[VaultConfigurer)。

If you want to control which context paths are mounted from Vault as PropertySource, you can either use a contextual location (vault:///my/context/path) or configure a VaultConfigurer.

上下文位置单独指定并装入。Spring Cloud Vault 将每个位置装入为唯一的 PropertySource。您可以将默认位置与上下文位置(或其他配置系统)混合使用,以控制属性源的顺序。此方法在您想要禁用默认键值路径计算并自行装入每个键值后端时特别有用。

Contextual locations are specified and mounted individually. Spring Cloud Vault mounts each location as a unique PropertySource. You can mix the default locations with contextual locations (or other config systems) to control the order of property sources. This approach is useful in particular if you want to disable the default key-value path computation and mount each key-value backend yourself instead.

application.yml
spring.config.import: vault://first/context/path, vault://other/path, vault://

为避免阴影效应,Spring Environment 中的属性名称必须是唯一的。如果您在不同的上下文路径中使用相同的密钥名称,而且想要将它们公开为单独的属性,可以通过向位置添加 prefix 查询参数进行区分。

Property names within a Spring Environment must be unique to avoid shadowing. If you use the same secret names in different context paths and you want to expose these as individual properties you can distinguish them by adding a prefix query parameter to the location.

Example 1. application.yml
spring.config.import: vault://my/path?prefix=foo., vault://my/other/path?prefix=bar.
secret: ${foo.secret}
other.secret: ${bar.secret}

前缀按原样添加到 Vault 返回的所有属性名称。如果你希望键名在键名和前缀之间用点号分隔,请确保向前缀添加一个尾随点号。

Prefixes are added as-is to all property names returned by Vault. If you want key names to be separated with a dot between the prefix and key name, make sure to add a trailing dot to the prefix.

Conditionally enable/disable Vault Configuration

在某些情况下,可能需要在没有 Vault 的情况下启动应用程序。您可以通过位置字符串表示 Vault 配置位置应该是可选的还是强制的(默认):

In some cases, it can be required to launch an application without Vault. You can express whether a Vault config location should be optional or mandatory (default) through the location string:

  • optional:vault:// (default location)

  • optional:vault:///<context-path> (contextual location)

如果通过 spring.cloud.vault.enabled=false 禁用 Vault 支持,则在应用程序启动过程中会跳过可选位置。

Optional locations are skipped during application startup if Vault support was disabled through spring.cloud.vault.enabled=false.

将跳过无法找到的 Vault 上下文路径(HTTP 状态 404),无论配置位置是否标记为可选项。如果由于 HTTP 状态 404 而无法找到 Vault 上下文路径,Vault Client Fail Fast 允许在启动时失败。

Vault context paths that cannot be found (HTTP Status 404) are skipped regardless of whether the config location is marked optional. Vault Client Fail Fast allows failing on start if a Vault context path cannot be found because of HTTP Status 404.

Infrastructure Customization

Spring Cloud Vault 需要基础设施类与 Vault 交互。在不使用 ConfigData API(这意味着您没有指定 spring.config.import=vault:// 或上下文 Vault 路径)时,Spring Cloud Vault 会通过 VaultAutoConfigurationVaultReactiveAutoConfiguration 定义其 Bean。Spring Boot 在可用 Spring 上下文之前启动应用程序。因此,VaultConfigDataLoader 会自行注册 Bean,以便稍后将它们传播到应用程序上下文中。

Spring Cloud Vault requires infrastructure classes to interact with Vault. When not using the ConfigData API (meaning that you haven’t specified spring.config.import=vault:// or a contextual Vault path), Spring Cloud Vault defines its beans through VaultAutoConfiguration and VaultReactiveAutoConfiguration. Spring Boot bootstraps the application before a Spring Context is available. Therefore VaultConfigDataLoader registers beans itself to propagate these later on into the application context.

您可以使用 Bootstrapper API 注册自定义实例来定制 Spring Cloud Vault 使用的基础设施:

You can customize the infrastructure used by Spring Cloud Vault by registering custom instances using the Bootstrapper API:

Customizing ClientHttpRequestFactory
ClientOptions options = new ClientOptions();
SslConfiguration sslConfiguration = SslConfiguration.unconfigured();
HttpClientBuilder builder = HttpComponents.getHttpClientBuilder(options, sslConfiguration);

InstanceSupplier<ClientFactoryWrapper> supplier = context ->
new ClientFactoryWrapper(new HttpComponentsClientHttpRequestFactory(builder.build()));

SpringApplication application = new SpringApplication(MyApplication.class);
application.addBootstrapRegistryInitializer(registry -> registry.register(ClientFactoryWrapper.class, supplier));
Customizing RestTemplateBuilder
InstanceSupplier<RestTemplateBuilder> supplier = context -> {

	return RestTemplateBuilder
			.builder()
			.requestFactory(context.get(ClientFactoryWrapper.class).getClientHttpRequestFactory())
			.defaultHeader("X-Vault-Namespace", "my-namespace");
};

SpringApplication application = new SpringApplication(MyApplication.class);
application.addBootstrapRegistryInitializer(registry -> registry.register(RestTemplateBuilder.class, supplier));

有关自定义挂钩,另请参见 Customize which secret backends to expose as PropertySourceVaultConfigDataLoader 的来源。

See also Customize which secret backends to expose as PropertySource and the source of VaultConfigDataLoader for customization hooks.