2019年3月28日木曜日

【技術メモ】SpringBoot の起動シーケンスに割り込んで Custom な PropertySource を実行させる方法

AWS SSM ParameterStore に設定されたシークレットな情報を Spring 起動時に Property として勝手に読み込む機能を実装しました。

SSM ParameterStore はもう皆さんおなじみですね。利用できないだけで禁断症状が出るほどに便利なアレです。

ECS では TaskDefinition から SSM ParameterStore を参照できるようになりました。
通常ですと ECS が担当することなので SpringApplication は通常どおり起動するだけで問題はありません。

ではなぜこの記事で紹介するような遠回りな方法が必要なのでしょう。



なぜこんなことをしたのか

この手段は CloudFormation TaskDefinition Resource が対応するまでの Workaround だと考えています。
SpringBoot 側の仕様変更等で使えなくなることは容易に考えられます。安易に組み込んだり、商用サービスに利用するのは注意してください。

問題1: CloudFormation が作る TaskDefinition リソースが SSM ParameterStore に対応出来ていない

CloudFormation で作った TaskDefinition にはこれを設定する Parameter がありません。
でも CloudFormation Template にシークレットな情報をベタに書きたくないし、入力値としても渡したくないです。

Spring が起動する時に Custom な PropertySource を読み出す方法はいくつかあります。

例) 76.3 Customize the Environment or ApplicationContext Before It Starts

が、この方法を SpringBoot で利用する方法を探せませんでした。


この手の要望はあるようで、探してみると情報はそれなりにありました。

Spring Boot and AWS Parameter Store

方法としては、起動前に Initializer として Custom な PropertySource を Spring にしれっと登録してしまう、という流れです。

問題2: SpringCloud for AWS が AWS SDK for Jara V1 しか対応していない

担当の開発が V2 で進んでいること、混在にはしたくないためこの方法を選びました。
SpringCloud for AWS を利用出来るならその方が圧倒的に楽ですし安全です。

解決方法

前項の通り、この方法が必要な条件はかなり限定的です。


  1. CloudFormation で TaskDefinition を作っている
  2. SpringCloud for AWS が使えない
  3. AWS SDK for Java V2 以外使いたくない
  4. EC2 で直接起動していてそのあたりの制御がグロい


このうち、私と同じように1が原因の場合はそのうち不要になる方法だと思います。不要になると信じたいです。

注意事項

ここに書かれているソースコードは参考例のため切り出してきたものです。
このままでは動作しないので雰囲気だけ拾ってください。
Kotlinで書かれています。Javaで組む場合は適宜変換してください。

SpringBootApplication に Custom な Initializer を追加する

ApplicationContextInitialzer から派生した CustomInitializer を起動前に追加しておきます。

Application.kt を参照


ApplicationContextInitializer から派生した Custom な ContextInitializer を作る

SsmClient をここで作っていますがこれはお好みで良いと思います。
もっと奥の層で作ってもいいです。

CustomContextInitializer.kt を参照


CustomPropertySource を作る

PropertySource を継承して CustomProertySource を作ります。
getPropertyは単に name が対象の property かどうかを判定して source の実装を呼ぶだけの単純な作りです。

application.properties に
param.hoge=${/ssm/path/hoge}
のように記述して使います。

CustomPropertySource.kt を参照

CustomSource を実装する

SSM から実際に値を取得する機能を実装します。
SSM だけじゃなく、あらゆるソースから取得する実装に変更することもできます。

CustomSource.kt を参照

0 件のコメント :

コメントを投稿