はじめに
踏み台運用からSession Managerを利用した踏み台レス運用に切り替えた場合、
認証情報はどこに保管することを考えていますか?
従来の踏み台運用では、SSH秘密鍵やデータベースのパスワード、
APIキーなどを踏み台サーバーに集約して管理することもあったかと思います。
しかし、踏み台レスに移行すると、この「認証情報の保管場所」がなくなってしまいます。その後は各エンジニアのローカルPCに分散したり、EC2インスタンス内のファイルにハードコードされたりと、管理が煩雑になるかもしれません。
本記事では、そのような課題を解決するAWS Systems Manager Parameter Storeについてご紹介します。
実際に使ってみながら認証情報の一元管理が実現するまでのフローを確認しますので、是非最後までご覧ください。
目次
検証構成
今回はSession Managerを利用した完全閉域環境内で定期的にバッチ処理を行うEC2の認証情報を管理することを想定します。
より高度な認証情報管理ということでSecrets Managerも使います。

以下のリソースは事前に作成済みです。
【作成済みリソース】
・VPC:1つ
・VPCエンドポイント:4つ
⇒com.amazonaws.ap-northeast-1.ssm
com.amazonaws.ap-northeast-1.ssmmessages
com.amazonaws.ap-northeast-1.ec2messages
com.amazonaws.ap-northeast-1.secretsmanager
・プライベートサブネット:1つ
・EC2:2台
⇒EC2-1:データ取得・加工バッチサーバ
EC2-2:データ投入・集計バッチサーバ
・EC2用ポリシー:SessionManager、Parameter Store、Secrets Managerの操作許可権限
※ AWS Systems Managerで踏み台運用をやめる - クロスパワークラウドブログの記事を参考に閉域環境の作成していますので、よければ見てみてください。
※ポリシーは本検証で不自由のないレベルで許可権限を付けています。詳細は割愛します。
また、Parameter StoreおよびSecrets Managerは設定データ管理と機密管理のための安全な階層型ストレージを提供しています。
今回作成するパラメータの階層は下記のようにします。
/batch/common/* → 両サーバ共通
/batch/ec2-1/* → EC2-1固有(EC2-2から参照不可)
/batch/ec2-2/* → EC2-2固有(EC2-1から参照不可)
確認手順
以下の流れで確認を進めます。
今回はコンソールとAWS CLIを利用して実施していきます。
1. パラメータの作成と取得
2. 認証情報の一括取得
3. 高度な認証情報管理
4. バージョン管理
1. パラメータの作成と取得
まずはコンソール画面からパラメータを作成します。
AWS Systems Managerからパラメータストアを選択して、パラメータの作成まで進みます。
2つのサーバで共有するS3バケット名を平文パラメータで作成してみましょう。
名前:/batch/common/s3-bucket-name
説明:任意の内容
タイプ:文字列
データ型:text
値:h*****-test-blog ※S3バケット名

必要項目を記入できたら[パラメータの作成]を押下します。
パラメータストアの[マイパラメータ]一覧に作成したパラメータが表示されていれば、とりあえず問題なしです。
続けてAWS CLIでパラメータを作成してみます。
ダミーですがAPIキーを作成するので、タイプはSecureString(安全な文字列)を指定した以下のコマンドを実行します。
aws ssm put-parameter --name "/batch/common/api-key" --value "dummy-*****" --type "SecureString"

"Version"と"Tier"が出力されました。特に問題なく作成できていそうですね。
このままAWS CLIで作成したパラメータを取得してみます。
以下のコマンドを実行して作成した2つのパラメータを確認します。
aws ssm get-parameter --name "/batch/common/s3-bucket-name"
aws ssm get-parameter --name "/batch/common/api-key"

コマンドの結果から正常に作成、取得できていることを確認できました。
※api-keyに関しては暗号化されていますが、復号化するオプションは後述します。
上記は/batch/common/配下に作成したので、EC2-1、EC2-2どちらからも参照することができます。
ただ、ポリシーで固有の階層のアクセス制限をしている場合などは、そうとはいきません。
例えば、今回はEC2-1から/batch/ec2-2/配下のパラメータを参照しようとすると以下のようなエラー文が出力されます。

2. 認証情報の一括取得
EC2-1上で以下のコマンドを実行し、作成した認証情報を一括で取得してみます。
aws ssm get-parameters-by-path --path "/batch/ec2-1/" --with-decryption --recursive
# --with-decryptionは暗号化パラメータを復号化します。
# --recursiveは全ての階層を再帰的に取得します。
これまで作成したパラメータがすべて確認できます。
また、SecureStringタイプのパラメータが暗号化されていないことも要注目です。
とはいえ、実際に見たい部分はValueの値だけの場合などは上記のようにjson形式で全情報出されても見づらいですね。以下のようにオプションを書き換えてみましょう。
aws ssm get-parameters-by-path --path "/batch/ec2-1/" --with-decryption --query "Parameters[*].Value" --output table
# --queryは欲しい部分だけをフィルタリングできます。
# --outputは出力フォーマットを指定します。デフォルトはjsonです。

table形式で出力させてみました。テーブル内にValueの値だけがまとまります。
こちらは複数個のパラメータ名を指定した場合になります。
コマンドがとても長いですね。
実用性を求めるなら以下のようなパラメータを環境変数化するシェルスクリプトを作ってみてください。
バッチ処理の実行スクリプトなど作成する際に応用できます。
#!/bin/bash
# EC2-1固有のパラメータを一括取得してJSON保存
aws ssm get-parameters-by-path \
--path "/batch/ec2-1/" \
--with-decryption \
--recursive \
--query "Parameters" \
--output json > /tmp/params.json
# jqで各パラメータを環境変数に設定
export SOURCE_S3_PREFIX=$(cat /tmp/params.json | jq -r '.[] | select(.Name=="/batch/ec2-1/source-s3-prefix") | .Value')
export PROCESSING_DAYS=$(cat /tmp/params.json | jq -r '.[] | select(.Name=="/batch/ec2-1/processing-days") | .Value')
export OUTPUT_S3_PREFIX=$(cat /tmp/params.json | jq -r '.[] | select(.Name=="/batch/ec2-1/output-s3-prefix") | .Value')
export EXTERNAL_API_KEY=$(cat /tmp/params.json | jq -r '.[] | select(.Name=="/batch/ec2-1/external-api-key") | .Value')
export ENCRYPTION_KEY=$(cat /tmp/params.json | jq -r '.[] | select(.Name=="/batch/ec2-1/encryption-key") | .Value')
# 一時ファイル削除
rm /tmp/params.json

3.高度な認証情報管理
ここまでParameter Storeに全ての認証情報を詰め込んでいきましたが、セキュリティの観点から、より高度な管理が必要なパラメータもあります。
これまで作成した中でいうとAPIキー(external-api-key)や秘密鍵(encryption-key)が該当します。
そういったパラメータはSecrets Managerへの移行を検討してみてください。
Secrets ManagerはParameter Storeと統合している為、Parameter Storeパラメータへの参照がサポートされています。
※本記事ではSecrets Managerの説明は割愛します。公式のドキュメントをご参照ください。
では、実際に移行してみましょう。AWS CLIから実施します。
aws secretsmanager create-secret \
--name "batch/ec2-1/api-key" \
--description "外部API認証キー(Parameter Storeから移行)" \
--secret-string "$(aws ssm get-parameter --name "/batch/ec2-1/external-api-key"\
--with-decryption --query "Parameter.Value" --output text)"
長いコマンドになるので分かりやすさ重視で複数行に分けて実行してみます。

"ARN","Name","VersionID"が出力されました。問題なさそうですね。
実際にコンソール上とAWS CLI上で移行後のパラメータを確認します。
aws secretsmanager get-secret-value --secret-id "batch/ec2-1/api-key"


パラメータが正常に移行されていることが確認できました。
今回はダミーデータなので機能確認は行いませんが、Secrets Managertは定期的なローテーション・厳格な監査が必要な際に役に立ちますので、是非利用してみてください。
※移行後、Parameter Storeから自動で削除されるといった機能はないので、不要になったパラメータは手動で削除する必要があります。
4. バージョン管理
Parameter Storeはバージョン管理機能も充実しています。
値を更新するたびに自動的に新しいバージョンが作られるようになっています。
以下のコマンドでパラメータ「/batch/ec2-1/source-s3-prefix」のバージョン履歴を確認してみます。
aws ssm get-parameter-history --name "/batch/ec2-1/source-s3-prefix"

これまでの更新履歴が全て出力されました。
「"Version":」が更新した回数だけカウントされていることに要注目です。
パラメータ取得コマンドにバージョンを指定することで過去のパラメータを取得できます。
aws ssm get-parameter --name "/batch/ec2-1/source-s3-prefix:1" --query "Parameter.Value" --output text
![]()
なお、これらバージョンの保持数上限は決まっていて、標準パラメータだと最大100バージョンまで保持できます。
そこまで注意する必要はないと思いますが、上限に達すると最も古いバージョンから順に自動削除される仕組みなのは認識しておきましょう。
おわりに
本記事では、AWS Systems Manager Parameter Storeを使った認証情報の一元管理について、プライベートサブネット内のバッチ処理サーバを例に確認してきました。
階層構造を活用することで、共通設定と個別設定を分けて管理でき、IAMポリシーによる権限分離も実現できました。また、バージョン管理機能により、設定変更の履歴も自動的に記録され、必要に応じて過去の値を参照することも可能です。
Secrets Managerへの移行方法についても触れましたが、まずはParameter Storeで認証情報管理の基本を押さえることを重視しました。改めてとなりますが、将来的に自動ローテーションや厳格な監査が必要になった場合に、Secrets Managerへの移行を検討するとよいと思います。
Parameter Storeを活用することで、スクリプト内に認証情報をハードコードすることなく、安全かつ柔軟な設定管理が実現できます。ぜひ、皆さんの運用にも取り入れてみてください。