ConfigData API

Spring Boot は、バージョン 2.4 以降、構成ソースの宣言とプロパティソースとしてのインポートを可能にする ConfigData API を提供します。

Spring Cloud Vault は、バージョン 3.0 以降、ConfigData API を使用して、Vault のシークレットバックエンドをプロパティソースとしてマウントします。以前のバージョンでは、ブートストラップコンテキストが使用されていました。ConfigData API は、どの構成システムをどの順序でインポートするかを指定できるため、はるかに柔軟です。

ブートストラップコンテキストを有効にするには、構成プロパティ spring.cloud.bootstrap.enabled=true を設定するか、依存関係 org.springframework.cloud:spring-cloud-starter-bootstrap を含めます。ブースストラップコンテキストの使用が必要になることはほとんどないため、プロパティソースの順序付けをより柔軟に行うために Config Data API を使用することをお勧めします。

ConfigData の場所

Vault から実現される 1 つ以上の PropertySource を介して Vault 構成をマウントできます。Spring Cloud Vault は、次の 2 つの構成場所をサポートします。

  • vault:// (デフォルトロケーション)

  • vault:///<context-path> (コンテキスト上の位置)

デフォルトの場所を使用すると、すべての有効なシークレットのバックエンドのプロパティソースがマウントされます。さらに構成を行わなくても、Spring Cloud Vault はキーと値のバックエンドを /secret/${spring.application.name} にマウントします。アクティブ化されたプロファイルごとに、/secret/$\{spring.application.name}/${profile} の形式に従って別のコンテキストパスが追加されます。spring-cloud-config-databases などのモジュールをクラスパスに追加すると、追加のシークレットバックエンド構成オプションが提供され、有効になっている場合はプロパティソースとしてマウントされます。

Vault から PropertySource としてマウントされるコンテキストパスを制御する場合は、コンテキストロケーション (vault:///my/context/path) を使用するか、VaultConfigurer を設定することができます。

コンテキスト上の場所が指定され、個別にマウントされます。Spring Cloud Vault は、各場所を一意の PropertySource としてマウントします。デフォルトの場所とコンテキスト上の場所 (または他の構成システム) を組み合わせて、プロパティソースの順序を制御できます。このアプローチは、デフォルトのキーと値のパス計算を無効にして、代わりに各キーと値のバックエンドを自分でマウントする場合に特に便利です。

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

Spring Environment 内のプロパティ名は、シャドウイングを避けるために一意である必要があります。異なるコンテキストパスで同じシークレット名を使用し、これらを個別のプロパティとして公開したい場合は、場所に prefix クエリパラメーターを追加することで区別できます。

例 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 によって返されるすべてのプロパティ名にそのまま追加されます。キー名をプレフィックスとキー名の間にドットで区切る場合は、必ずプレフィックスの末尾にドットを追加してください。

条件付きで Vault 構成を有効 / 無効にする

場合によっては、Vault なしでアプリケーションを起動する必要がある場合があります。Vault 構成の場所をオプションにするか必須 (デフォルト) にするかを、場所文字列を使用して表現できます。

  • optional:vault:// (デフォルトロケーション)

  • optional:vault:///<context-path> (コンテキスト上の位置)

Vault サポートが spring.cloud.vault.enabled=false によって無効になっている場合、オプションの場所はアプリケーションの起動中にスキップされます。

見つからない Vault コンテキストパス (HTTP ステータス 404) は、構成の場所がオプションとしてマークされているかどうかに関係なくスキップされます。Vault クライアントのフェイルファストでは、HTTP ステータス 404 が原因で Vault コンテキストパスが見つからない場合、起動に失敗することが許可されます。

インフラストラクチャのカスタマイズ

Spring Cloud Vault には、Vault と対話するためのインフラストラクチャクラスが必要です。ConfigData API を使用しない場合 (つまり、spring.config.import=vault:// またはコンテキスト Vault パスを指定していない場合)、Spring Cloud Vault は VaultAutoConfiguration および VaultReactiveAutoConfiguration を通じて Bean を定義します。Spring Boot は、Spring コンテキストが使用可能になる前にアプリケーションをブートストラップします。VaultConfigDataLoader は Bean 自体を登録して、後でアプリケーションコンテキストに伝播します。

Bootstrapper API を使用してカスタムインスタンスを登録することで、Spring Cloud Vault で使用されるインフラストラクチャをカスタマイズできます。

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));
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));

カスタマイズフックについては、PropertySource として公開するシークレットバックエンドをカスタマイズするおよび VaultConfigDataLoader のソースも参照してください。