概要
データベースのユーザー名とパスワードを、アプリケーションのソースコードや設定ファイルに直接書いてしまうことがあります。動きはしますが、リポジトリを見られる人には誰にでもパスワードが見え、パスワードを変えるたびにコードを書き換えてデプロイし直す必要があります。
AWS Secrets Manager に認証情報を保存しておけば、アプリケーションは実行時に API(GetSecretValue)で値を取りに行くだけで済みます。コードに残るのはシークレットの名前だけです。さらに Secrets Manager には、保存した認証情報を定期的に変えるローテーションの仕組みがあります。
この記事では、認証情報の置き場所の選択肢(ソースコード、環境変数、Parameter Store、Secrets Manager)を比べたうえで、Lambda から Secrets Manager のシークレットを取得するコードと、そのために必要な実行ロールの権限を整理します。実践では、権限が無いと取得に失敗することを確かめてから、実行ロールに権限を足して取得できるようにします。

クラウドおさる倉庫の合言葉を巻物に書いて持ち歩くと、落としたときに猿山じゅうに知れ渡るでござる。合言葉は長老の金庫に預けて、必要なときだけ聞きに行く。今日はその「聞きに行く」部分を作るでござるよ。
この記事のメリット
- 認証情報をソースコード・環境変数・Parameter Store・Secrets Manager に置いた場合の違いを説明できるようになる
- Lambda から
GetSecretValueでシークレットを取得するコードを書けるようになる - シークレットの取得に必要な実行ロールの権限(
secretsmanager:GetSecretValue)を設定できるようになる - 「自動ローテーションが必要なら Secrets Manager」という使い分けを判断できるようになる
執筆者とキャラクター紹介
執筆者:土肥(とひ)
株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。


クラウドおさる



はじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。



基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。



猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。
技術解説
認証情報の置き場所の比較
| 置き場所 | 中身を見られる人 | 変えるときの作業 | 自動ローテーション |
|---|---|---|---|
| ソースコード | リポジトリを読める全員 | コードを書き換えて再デプロイ | できない |
| 環境変数(Lambda・EC2・AMI など) | 関数やインスタンスの設定を見られる人 | 設定を書き換えて再デプロイ・再起動 | できない |
| Systems Manager Parameter Store(SecureString) | パラメータの読み取り権限を持つ人 | パラメータを更新 | 組み込みの仕組みは無い |
| AWS Secrets Manager | シークレットの読み取り権限を持つ人 | シークレットを更新 | できる(RDS などとの統合、または Lambda によるローテーション) |
「安全に保管する」だけなら Parameter Store の SecureString でも KMS で暗号化して保管できます。「自動でローテーションする」まで求められる場合は Secrets Manager を選びます。Secrets Manager は、Amazon RDS・Amazon Redshift・Amazon DocumentDB などの認証情報について、ローテーションの仕組みをあらかじめ用意しています。



「環境変数に入れたから安全」と思いがちでござるが、関数の設定を見られる人には丸見えで、変えるには関数を更新するしかないのでござる。ローテーションまで求められたら Secrets Manager、と覚えておくでござるぞ。
アプリケーションからの取得
アプリケーションは、SDK の GetSecretValue でシークレットを取得します。Python(boto3)なら次のようになります。
import json
import boto3
client = boto3.client("secretsmanager")
resp = client.get_secret_value(SecretId="dva-lab/db-credentials")
secret = json.loads(resp["SecretString"]) # {"username": "...", "password": "...", ...}コードに書くのはシークレットの名前(または ARN)だけです。名前も環境変数で渡せば、環境ごとに別のシークレットを指せます。ローテーションでパスワードが変わっても、アプリケーションは次に取得したときに新しい値を受け取るので、コードの変更は要りません。


取得に必要な権限
Lambda 関数が AWS のサービスを呼ぶときの権限は、実行ロールで決まります。シークレットを取得するには、実行ロールに次の権限が必要です。
| 権限 | 必要になる場面 |
|---|---|
secretsmanager:GetSecretValue | シークレットの値を取得する |
kms:Decrypt | シークレットをカスタマー管理キーで暗号化している場合(AWS マネージドキー aws/secretsmanager なら不要) |
権限が無いと、GetSecretValue は AccessDeniedException を返します。リソースは * ではなく、取得するシークレットの ARN に絞ります。
呼び出すたびに取りに行かない工夫
GetSecretValue は API 呼び出しごとに料金がかかり、呼び出しの分だけ処理も遅くなります。Lambda では、関数の外側(初期化時)で取得して実行環境の中で使い回したり、AWS Parameters and Secrets Lambda Extension を使って取得した値をキャッシュしたりする方法があります。



合言葉は金庫から聞いてきて、しばらくは覚えておくのでござる。毎回長老を起こしに行っていたら、長老も弊猿もくたびれるでござるな。
実践
Lambda 関数 dva-secret-lab-fn は、環境変数 SECRET_ID に入っている名前のシークレットを取得して、ユーザー名・ホスト名・パスワードの文字数を返します(パスワードそのものは返しません)。まずシークレットを作り、権限が無い状態で呼び出して失敗することを確かめてから、実行ロールに権限を足します。
前提条件
- リージョン:
ap-northeast-1(東京) - 以下のリソースが作成済みであること
まだ用意していない場合は、「作り方の参考」の記事の手順で作れます。リソース名は、この記事の名前に読み替えてください。
| リソース種別 | リソース名 | 内容 | 作り方の参考 |
|---|---|---|---|
| Lambda 関数 | dva-secret-lab-fn | Python 3.13。環境変数 SECRET_ID = dva-lab/db-credentials。上の「アプリケーションからの取得」と同じ処理で、取得したシークレットからユーザー名・ホスト名・パスワードの文字数を返す | AWS Lambda で関数を作成しイベント駆動で実行する |
| IAM ロール | dva-secret-lab-role | 上の関数の実行ロール。CloudWatch Logs への出力(AWSLambdaBasicExecutionRole)だけを許可 | ― |
作成するリソース一覧
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| シークレット | dva-lab/db-credentials | データベースの認証情報(ハンズオン用のダミー) |
| インラインポリシー | dva-secret-lab-get-secret | 実行ロールにシークレットの取得を許可する |
手順 1: シークレットを作る
AWS マネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。上部の検索バーに Secrets Manager と入力し、「Secrets Manager」を選択します。
「新しいシークレットを保存する」をクリックし、以下を設定します。
- シークレットのタイプ: 「その他のシークレットのタイプ」
- キー/値のペア: 「行を追加」で次の 4 行を入力
username:app_userpassword:Handson-Passw0rd-2026(ハンズオン用のダミー)host:db.example.internalport:3306- 暗号化キー:
aws/secretsmanager(デフォルト)


「次」をクリックし、シークレットの名前に dva-lab/db-credentials と入力して「次」をクリックします。ローテーションの設定はデフォルト(無効)のまま「次」をクリックし、レビュー画面で「保存」をクリックします。
手順 2: 権限が無い状態で関数を呼び出す
上部の検索バーに Lambda と入力し、「Lambda」を選択します。関数の一覧から dva-secret-lab-fn を開き、「テスト」タブを選択します。イベント名に empty と入力し、イベント JSON は {} のまま「テスト」をクリックします。
実行結果は「実行中の関数: 失敗」になります。その下の「詳細」を開くと、Response の errorMessage に AccessDeniedException と、実行ロール dva-secret-lab-role が secretsmanager:GetSecretValue を実行する権限を持っていない旨が表示されます。





シークレットはちゃんとあるのに、関数の背負っている役目(実行ロール)に「金庫を開けてよい」と書いていないので断られたのでござるな。
手順 3: 実行ロールに取得の権限を足す
関数の画面の「設定」タブ →「アクセス権限」を選択し、「実行ロール」のロール名 dva-secret-lab-role をクリックします。IAM コンソールでロールが開きます。
「許可を追加」→「インラインポリシーを作成」を選択します。ポリシーエディタで「JSON」を選び、次のポリシーを入力します。Resource は、手順 1 で作ったシークレットの ARN(Secrets Manager のシークレットの詳細画面で確認できます)に置き換えます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:ap-northeast-1:<アカウントID>:secret:dva-lab/db-credentials-XXXXXX"
}
]
}

「次へ」をクリックし、ポリシー名に dva-secret-lab-get-secret と入力して「ポリシーの作成」をクリックします。ロールの「許可ポリシー」に dva-secret-lab-get-secret が追加されたことを確認します。
手順 4: もう一度呼び出す
Lambda コンソールに戻り、dva-secret-lab-fn の「テスト」タブで、もう一度「テスト」をクリックします。今度は成功し、username に app_user、host に db.example.internal、password_length にパスワードの文字数、version_id に取得したシークレットのバージョン ID が返ります(結果は「詳細」を開くと見られます)。


関数のコードと環境変数には、パスワードはどこにも書かれていません。関数は実行のたびに、Secrets Manager から値を取りに行っています。
手順 5: ローテーションの設定画面を確かめる
Secrets Manager のコンソールで dva-lab/db-credentials を開き、「ローテーション」タブを選択して「ローテーションを編集」をクリックします。「ローテーション設定を編集する」ダイアログが開き、「自動ローテーション」をオンにすると、ローテーションのスケジュールと、ローテーションを行う Lambda 関数を指定する欄が表示されます。今回のシークレットは「その他のシークレットのタイプ」なので、パスワードを変える処理(Lambda 関数)を自分で用意する必要があります。RDS などのデータベースのタイプを選んだシークレットでは、AWS が用意したローテーションの仕組みを使えます。


ここでは設定を保存せずに「Cancel」をクリックします。RDS の認証情報を実際にローテーションする流れは、Secrets ManagerによるECSコンテナの認証情報管理と自動ローテーション で扱っています。



アプリは名前だけ知っていて、中身は金庫番(Secrets Manager)が管理する。だから合言葉を変えても、アプリは書き換えずに済むのでござる。
まとめ
| 要件 | 選ぶもの |
|---|---|
| 認証情報をコードに書かずに安全に保管する | Parameter Store の SecureString、または Secrets Manager |
| さらに自動でローテーションする | Secrets Manager |
| Lambda から取得できるようにする | 実行ロールに secretsmanager:GetSecretValue(カスタマー管理キーなら kms:Decrypt も) |
- ソースコードや環境変数に入れた認証情報は、見られる範囲が広く、変えるたびに再デプロイが要る
- Secrets Manager に保存すれば、アプリケーションは
GetSecretValueで実行時に取得し、コードにはシークレットの名前だけが残る - 取得の権限は Lambda の実行ロールで与える。権限が無いと
AccessDeniedExceptionになる - 自動ローテーションは Secrets Manager の機能。RDS などには組み込みの仕組みがあり、その他のシークレットはローテーション用の Lambda 関数を用意する
- 呼び出しのたびに取得しないよう、初期化時に取得して使い回すか、Parameters and Secrets Lambda Extension でキャッシュする
参照先
- AWS Secrets Manager とは – AWS Secrets Manager
- AWS Secrets Manager からシークレットを取得する – AWS Secrets Manager
- AWS Lambda 関数で AWS Secrets Manager シークレットを使用する – AWS Secrets Manager
- AWS Secrets Manager シークレットのローテーション – AWS Secrets Manager
- 実行ロールを使用した Lambda 関数のアクセス許可の定義 – AWS Lambda
- AWS Systems Manager Parameter Store – AWS Systems Manager














