AWS Secrets Manager入門 パスワード・APIキーを安全に管理する実践ガイド

Cloud Security

「アプリケーションのDB接続パスワード、どこに保存していますか?」

オンプレミス時代は設定ファイルにパスワードを直書きしたり、Excelの管理台帳で共有したりするのが当たり前でした。しかしクラウド環境では、EC2やLambdaが動的にスケールし、コンテナが使い捨てで起動する世界です。設定ファイルにパスワードを埋め込む方式は、セキュリティリスクが格段に上がります。

この記事では、AWS Secrets Managerを使ったシークレット管理の基本から、オンプレ環境との違い、実際の運用フローまでを解説します。「パスワードをどこに置くか」という現場の悩みを、クラウドネイティブなやり方で解決する方法がわかります。

AWS Secrets Manager入門 パスワード・APIキーを安全に管理する実践ガイド

なぜシークレット管理が必要なのか?オンプレとの違い

オンプレ環境でのパスワード管理を振り返ってみましょう。多くの現場では、こんな運用が一般的でした。

設定ファイルに直書き: /etc/myapp/config.ini にDB接続パスワードを平文で記載
環境変数にセット: .bashrcやsystemdのUnitファイルにパスワードを記載
Excel管理台帳: 共有フォルダにあるパスワード一覧ファイルで管理
手動ローテーション: 年に1回、運用担当者がパスワードを変更して回る

この方式がクラウドで破綻する理由は明確です。

1. コードリポジトリへの混入リスク

設定ファイルにパスワードを書く文化のまま開発を進めると、GitHubやCodeCommitにパスワードがプッシュされる事故が起きます。GitGuardianの調査によると、パブリックリポジトリで検出されるシークレットの漏洩は年間1,000万件を超えています。

2. オートスケーリング環境での配布問題

EC2 Auto Scalingで新しいインスタンスが自動起動するとき、そのインスタンスにパスワードをどう渡すかという問題が発生します。AMIにパスワードを焼き込むのは論外ですし、UserDataに書くのもCloudTrailに記録されるため危険です。

3. ローテーションの自動化

オンプレでは「年1回のパスワード変更」で済んでいたかもしれません。しかしクラウドのセキュリティベストプラクティスでは、30日〜90日ごとのローテーションが推奨されています。手動では現実的に回りません。

AWS Secrets Managerの基本的な仕組み

AWS Secrets Managerは、パスワード、APIキー、データベース認証情報などのシークレットを暗号化して一元管理するマネージドサービスです。

機能 AWS Secrets Manager オンプレ相当
シークレット保管 暗号化されたKVストア 設定ファイル / 管理台帳
アクセス制御 IAMポリシー + リソースポリシー ファイルパーミッション / AD権限
暗号化 AWS KMSによる自動暗号化 手動でのファイル暗号化
ローテーション Lambda連携で自動ローテーション 手動で定期変更
監査ログ CloudTrailに自動記録 独自のアクセスログ

ポイントは、アプリケーションが直接パスワードを持たないという設計思想です。アプリはSecrets ManagerのAPIを呼び出してパスワードを取得し、メモリ上でのみ使用します。設定ファイルやコードにパスワードは一切残りません。

料金体系(2026年4月時点)

シークレット保管: 1シークレットあたり月額$0.40(USD)
API呼び出し: 10,000回あたり$0.05(USD)

たとえばRDSのパスワード1つを管理し、1日1,000回のAPI呼び出しがある場合、月額コストは$0.40 + $0.15 = 約$0.55です。オンプレでの管理工数を考えれば、十分にコスト効率が良い水準です。

AWS Secrets Manager入門 パスワード・APIキーを安全に管理する実践ガイド - 解説

シークレットの作成と取得(コンソール操作 + CLI)

1. マネジメントコンソールでシークレットを作成する

AWSマネジメントコンソールからSecrets Managerを開き、「新しいシークレットを保存する」をクリックします。

シークレットのタイプを選択します。RDS、Redshift、DocumentDBの認証情報であれば専用のテンプレートが用意されています。それ以外のパスワードやAPIキーは「その他のシークレットのタイプ」を選びます。

キーと値のペアでシークレットを入力します。たとえばDB接続情報なら、以下のように設定します。

username: myapp_user
password: (自動生成または手動入力)
host: mydb.cluster-xxxx.ap-northeast-1.rds.amazonaws.com
port: 3306

暗号化キーはデフォルトの aws/secretsmanager(AWS管理キー)で問題ありません。独自のKMSキーを使う場合は、ここで選択します。

シークレット名を入力します。命名規則は「環境/サービス/用途」のスラッシュ区切りがおすすめです。例: prod/myapp/db-credentials

2. AWS CLIでシークレットを作成する

# AWS CLIでシークレットを作成 aws secretsmanager create-secret \ --name prod/myapp/db-credentials \ --description "本番環境のDB接続情報" \ --secret-string '{"username":"myapp_user","password":"MyStr0ngP@ss!","host":"mydb.cluster-xxxx.ap-northeast-1.rds.amazonaws.com","port":"3306"}' \ --region ap-northeast-1

3. アプリケーションからシークレットを取得する

Python(boto3)での取得例です。

# Python boto3でシークレットを取得 import boto3 import json def get_db_credentials(): client = boto3.client('secretsmanager', region_name='ap-northeast-1') response = client.get_secret_value(SecretId='prod/myapp/db-credentials') secret = json.loads(response['SecretString']) return secret # 使用例 creds = get_db_credentials() print(f"Host: {creds['host']}, User: {creds['username']}")

AWS CLIでの取得はこちらです。

# AWS CLIでシークレットを取得 aws secretsmanager get-secret-value \ --secret-id prod/myapp/db-credentials \ --region ap-northeast-1 \ --query SecretString \ --output text | jq .

自動ローテーションの設定

Secrets Managerの最大の強みは、パスワードの自動ローテーションです。RDS、Redshift、DocumentDBについてはAWSが用意したLambda関数を使って、ほぼ設定するだけでローテーションが動きます。

RDSパスワードの自動ローテーション設定

コンソールでシークレットの詳細画面を開き、「ローテーション」セクションの「編集」をクリックします。

ローテーションスケジュールを設定します。一般的な運用では30日ごとが推奨です。コンプライアンス要件に応じて7日〜365日の範囲で設定できます。

ローテーションの仕組みは、裏側でLambda関数が以下のステップを実行しています。

createSecret: 新しいパスワードを生成し、Secrets Managerに「AWSPENDING」ステージとして保存
setSecret: RDSのマスターユーザーを使って、DBのパスワードを新しいものに変更
testSecret: 新しいパスワードでDBに接続できるかテスト
finishSecret: テスト成功後、「AWSPENDING」を「AWSCURRENT」に昇格

ローテーション時のダウンタイムを防ぐ設計

自動ローテーションで一番心配なのが「パスワード変更の瞬間にアプリが接続エラーを起こさないか」です。

これを防ぐには、シングルユーザーローテーションではなく、マルチユーザーローテーション戦略を使います。

シングルユーザー: 1つのDBユーザーのパスワードを直接更新する。ローテーション中の数秒間、旧パスワードでの接続が失敗する可能性がある
マルチユーザー: 2つのDBユーザーを交互に使う。一方のパスワードを更新中も、もう一方で接続できるため、ダウンタイムが発生しない

本番環境では、マルチユーザー戦略の採用を強く推奨します。

実務で使えるSecrets Managerの設計パターン

パターン1: マルチ環境でのシークレット管理

開発・ステージング・本番の各環境でシークレットを分離するには、命名規則とIAMポリシーを組み合わせます。

# 命名規則の例 dev/myapp/db-credentials stg/myapp/db-credentials prod/myapp/db-credentials # IAMポリシーで環境ごとにアクセスを制限 # 開発チームには dev/* のみ、本番運用チームには prod/* のみを許可

IAMポリシーの設定例です。

# 本番環境のシークレットのみ取得可能なIAMポリシー { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/*" } ] }

パターン2: LambdaからSecrets Managerを使う

Lambda関数でDB接続する際は、コールドスタートのたびにSecrets ManagerのAPIを呼ぶとレイテンシが増えます。AWS提供のLambda Extensionを使えば、シークレットをローカルキャッシュして呼び出し回数を削減できます。

# Lambda ExtensionのARN(東京リージョン(ap-northeast-1)、2026年4月時点) # AWS公式ドキュメントで最新のARNを確認してください arn:aws:lambda:ap-northeast-1:133490413xxx:layer:AWS-Parameters-and-Secrets-Lambda-Extension:XX

この拡張機能を使うと、シークレットはLambda実行環境のメモリにキャッシュされ、TTL(デフォルト300秒)の間はAPIを呼ばずにキャッシュから返されます。

パターン3: ECS/Fargateコンテナへの注入

ECSタスク定義でSecrets Managerのシークレットを環境変数として注入できます。コンテナイメージにパスワードを含める必要がなくなります。

# ECSタスク定義(JSON抜粋) { "containerDefinitions": [ { "name": "myapp", "secrets": [ { "name": "DB_PASSWORD", "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/myapp/db-credentials:password::" } ] } ] }

valueFromのARNの末尾に「:password::」とキー名を指定すると、JSON形式のシークレットから特定のキーだけを取り出して環境変数にセットできます。

よくあるトラブルと対処法

トラブル1: AccessDeniedExceptionが出る

シークレットの取得時にAccessDeniedExceptionが発生する場合、以下を確認します。

IAMポリシー: secretsmanager:GetSecretValue のアクションが許可されているか
KMSキー: シークレットの暗号化にカスタムKMSキーを使っている場合、kms:Decrypt の権限も必要
リソースARN: ポリシーのResourceに指定したARNが正しいか。Secrets ManagerのARNにはランダムな6文字のサフィックスが付く

トラブル2: ローテーション後にアプリが接続エラーになる

ローテーション直後に接続エラーが発生する場合、アプリ側でシークレットをキャッシュしていることが原因です。

対処法は2つあります。

キャッシュTTLを短くする: Secrets Manager SDKのキャッシュTTLを300秒以下に設定
接続エラー時にリトライ: 接続失敗時にシークレットを再取得してリトライするロジックを実装

# リトライ付きDB接続(Python例) import time def connect_with_retry(max_retries=3): for attempt in range(max_retries): try: creds = get_db_credentials() # 毎回最新を取得 connection = mysql.connector.connect( host=creds['host'], user=creds['username'], password=creds['password'] ) return connection except mysql.connector.Error: if attempt < max_retries - 1: time.sleep(2) raise Exception("DB接続に失敗しました")

トラブル3: シークレットを誤って削除してしまった

Secrets Managerでシークレットを削除すると、デフォルトで7日間の猶予期間が設定されます。この期間中は復元が可能です。

# 削除予定のシークレットを復元 aws secretsmanager restore-secret \ --secret-id prod/myapp/db-credentials \ --region ap-northeast-1

本番環境のシークレットには、IAMポリシーで secretsmanager:DeleteSecret を制限しておくのが安全です。

Secrets Manager vs Systems Manager Parameter Store

AWSにはシークレット管理できるサービスがもう1つあります。Systems Manager Parameter Store(SSM Parameter Store)です。どちらを使うか迷う場面は多いので、違いを整理しておきます。

比較項目 Secrets Manager SSM Parameter Store
料金 $0.40/シークレット/月 Standard無料 / Advanced $0.05/月
自動ローテーション 組み込みサポートあり 自分でLambdaを実装する必要あり
暗号化 デフォルトで暗号化 SecureString型で暗号化
クロスアカウント共有 リソースポリシーで対応 非対応
最大サイズ 64KB Standard 4KB / Advanced 8KB
向いている用途 DB認証・APIキーなどの機密情報 設定値・フラグなど非機密情報も含む

判断基準はシンプルです。自動ローテーションが必要なDB認証情報やAPIキーはSecrets Manager、アプリケーションの設定値や機密性の低いパラメータはSSM Parameter Storeを使います。コスト重視でローテーションが不要なら、SSM Parameter StoreのSecureStringでも十分です。

AWS Secrets Manager入門 パスワード・APIキーを安全に管理する実践ガイド - まとめ

本記事のまとめ

AWS Secrets Managerを使ったシークレット管理の基本を解説しました。

やりたいこと Secrets Managerの機能 オンプレ相当
パスワードを安全に保管 KMSで暗号化して一元管理 設定ファイル / Excel管理台帳
アプリからパスワードを取得 API呼び出し(SDK/CLI) 設定ファイル読み込み
パスワードを定期変更 Lambda連携の自動ローテーション 手動で年1回変更
誰がいつ触ったか記録 CloudTrailに自動記録 独自のアクセスログ
環境ごとにアクセス制限 IAMポリシー + 命名規則 ファイルパーミッション

オンプレ時代の「設定ファイルにパスワードを書く」運用から脱却し、クラウドネイティブなシークレット管理に移行することで、セキュリティレベルが大幅に向上します。まずは新規プロジェクトから導入して、既存システムの移行は段階的に進めるのが現実的です。

Linuxサーバー上でのAWS CLI設定やIAMの基礎については、姉妹サイトLinuxMaster.JPで詳しく解説しています。セキュリティの基本的な考え方を体系的に学びたい方は、セキュリティマスターズ.TOKYOもあわせてご覧ください。

パスワード管理、まだ設定ファイルに直書きしていませんか?

クラウド移行で見落とされがちなシークレット管理。Secrets Managerの導入は、セキュリティ強化の第一歩です。
オンプレの経験を活かしながら、現場で使えるクラウドスキルを体系的に身につけたい方へ、メルマガで実践的なクラウド活用ノウハウをお届けしています。

コメント

タイトルとURLをコピーしました