Spring Bootでは、application.yml、application-prod.yml、プロファイル別のファイル、外部設定ファイルがよく使われます。この方式自体に問題はありませんが、本番用のシークレットをリポジトリにコミットした場合は、露出したものとして扱う必要があります。
このガイドを使う場面
application.ymlやapplication-prod.ymlにDBパスワード、トークン、署名鍵が直接記載されている場合- Spring Bootがプロファイル別の設定を使用している場合
${ENV_VAR}参照とマウントした設定ファイルのどちらを使うか決める場合- Kubernetes、VM、安全なファイル配布でSpringの設定を外部から供給する場合
例
Pattern A: ${ENV_VAR}による注入
環境変数を注入できる環境では、単純な構成で利用できます。
このパターンを選ぶ場面
- シークレットの数が比較的少なく、環境変数で渡せる場合
- デプロイシステムが環境変数の注入を標準で提供する場合
- プロファイルを維持し、実際のシークレットだけを外部から供給する場合
変更前
yaml
spring:
datasource:
url: jdbc:postgresql://prod-db.internal:5432/app
username: app_user
password: super-secret-password
jwt:
secret: hardcoded-jwt-secret
変更後
yaml
spring:
datasource:
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
jwt:
secret: ${JWT_SECRET}
Springのコード例
java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotBlank;
@Validated
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
@NotBlank
private String secret;
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
}
Jakarta Validationを使うSpring Boot環境の抜粋です。検証用の依存関係を追加し、@ConfigurationPropertiesScanまたは@EnableConfigurationPropertiesでクラスを登録してください。必須の値が欠けている場合や空の場合は、起動を中止してください。
Pattern B: マウントしたapplication.ymlの注入
運用上application.ymlやapplication-prod.ymlが必要な場合は、実際の本番ファイルを/config/application.ymlや/etc/app/application.ymlなどのパスに実行時に供給してください。
このパターンを選ぶ場面
- プロファイル別のファイル構成を維持する必要がある場合
- 外部設定ファイルのパスを運用標準としている場合
- Kubernetes Secretボリューム、Vault Agent、安全なファイル配布を利用できる場合
リポジトリに置くファイルの例
yaml
spring:
datasource:
url: jdbc:postgresql://prod-db.internal:5432/app
username: app_user
password: "<runtime-provided>"
jwt:
secret: "<runtime-provided>"
実行時のファイルパス例
text
/config/application.yml
/etc/app/application.yml
Springの設定例
spring.config.importまたはSpring Bootの標準的な外部設定パスを使用できます。実値はリポジトリに保存せず、実行時に供給してください。
yaml
spring:
config:
import: file:/etc/app/application.yml
このファイルは必須なので、optional:を付けません。本番用のapplication.ymlやapplication-prod.ymlはGitにコミットしないでください。
開発者の作業
application.ymlとapplication-prod.ymlから実際のシークレットを削除してください。- サービスに合った環境変数参照または外部ファイル読み込みを選んでください。
- 必須の値がなければ、
@ConfigurationPropertiesや既存のローダーで処理を中止するようにしてください。 - ログ、例外、デバッグ出力、Actuatorエンドポイントにシークレットが出ないことを確認してください。
インフラ・プラットフォーム担当者の作業
- 環境変数を使う場合は、デプロイ時の注入を構成してください。
- ファイルを使う場合は、Secretボリューム、安全なファイル配布、外部ファイルパスを標準化してください。
- Helm values、Dockerイメージ、ConfigMapへの実値の保存を防いでください。
- シークレットのローテーション時に必要な再起動や再読み込みを運用手順に記載してください。
検証方法
application-prod.ymlなどの本番ファイルがリポジトリにないことを確認してください。- デプロイ先で
${ENV_VAR}やマウントしたファイルが実際に供給されることを確認してください。 /actuator/env、デバッグログ、例外応答にシークレットが出ないことを確認してください。- 必須のシークレットがなければ起動に失敗することを確認してください。
よくある誤り
application-prod.ymlをコミットする- Helm valuesにシークレットを直接保存する
- 本番設定をDockerイメージに組み込む
/actuator/env、デバッグログ、例外スタックに設定値を出力する- 空の既定値を使い、必須のシークレットがなくても起動できるようにする
担当者への案内例
- 「Spring Bootの設定から実際のシークレットを削除し、
${ENV_VAR}参照か実行時に供給する外部ファイルに置き換えてください。」 - 「
application-prod.ymlが必要でもコミットせず、/config/application.ymlや/etc/app/application.ymlなどのパスで実行時に供給してください。」 - 「必須のシークレットがなければ、
@ConfigurationPropertiesや既存のローダーですぐに起動を中止し、/actuator/envやデバッグログにも値が出ないことを確認してください。」