🙌

AWS学びなおし(+TF)_Secrets Manager

2025/03/01に公開

AWS Secrets Managerは、データベースの認証情報、APIキー、OAuthトークンなどの機密情報 (シークレット) を安全に管理、ローテーション、および取得できるサービスです。

従来の課題とSecrets Managerのメリット

従来、機密情報はアプリケーションコードや設定ファイルに直接埋め込まれたり、バージョン管理システムに平文で保存されたりすることがありました。これらの方法はセキュリティリスクが高く、情報漏洩のリスクや、認証情報の変更時の手間といった課題がありました。

Secrets Managerはこれらの課題を解決し、以下のメリットを提供します。

  • セキュリティの向上:
    • 機密情報を集中管理し、暗号化して安全に保管します。
    • 不要な場所への機密情報の露出を減らし、セキュリティリスクを低減します。
    • AWS KMS (Key Management Service) と統合されており、暗号化キーの管理も容易です。
  • 機密情報のローテーション自動化:
    • データベースパスワードなどを定期的に自動で変更 (ローテーション) できます。
    • 手動でのローテーション作業を削減し、セキュリティポリシー遵守を支援します。
    • ローテーション設定をカスタマイズ可能で、様々なシステムに対応できます。
  • アクセスの集中管理と制御:
    • IAM (Identity and Access Management) を使用して、誰がどのシークレットにアクセスできるかを細かく制御できます。
    • アクセスログを監査証跡として利用でき、セキュリティ監視に役立ちます。
  • アプリケーションからの簡単な利用:
    • AWS SDKやCLIを通じて、アプリケーションから簡単にシークレットを取得できます。
    • シークレットの値が変更されても、アプリケーションコードの変更を最小限に抑えられます。
  • 様々な種類のシークレットに対応:
    • データベース認証情報、APIキー、OAuthトークン、証明書、その他のテキスト情報など、様々な種類のシークレットを管理できます。
    • バイナリ形式のシークレットもサポートしています。
  • コスト効率:
    • 使用量に応じた従量課金制であり、初期費用は不要です。
    • 大規模なシステムから小規模なシステムまで、柔軟に利用できます。

Secrets Managerの主な機能

  • シークレットの作成と管理:
    • AWSコンソール、CLI、SDK、Terraformなどを使用してシークレットを作成、更新、削除できます。
    • シークレットには名前、説明、タグなどのメタデータを付与できます。
    • シークレットの値はテキスト形式またはバイナリ形式で保存できます。
  • シークレットのローテーション:
    • 定期的な自動ローテーションを設定できます (データベース、その他認証情報など)。
    • ローテーションロジックをカスタマイズするためのLambda関数を連携できます。
    • ローテーションのスケジュールや頻度を柔軟に設定できます。
  • シークレットの取得:
    • AWS SDK、CLI、またはHTTPSエンドポイントを通じて、アプリケーションからシークレットを取得できます。
    • シークレットのバージョン管理機能により、特定のバージョンのシークレットを取得できます。
    • キャッシュ機能を利用することで、頻繁なアクセスによるパフォーマンスへの影響を軽減できます。
  • アクセス制御:
    • IAMポリシーを使用して、シークレットへのアクセス許可をユーザー、グループ、ロールに対して付与できます。
    • シークレットレベルでのきめ細かいアクセス制御が可能です。
    • 最小権限の原則に基づいたアクセス制御を実装できます。
  • 監査ログ:
    • AWS CloudTrailと統合されており、シークレットへのアクセスや変更などの操作ログを記録できます。
    • セキュリティインシデント発生時の原因究明や、コンプライアンス監査に役立ちます。
  • 他のAWSサービスとの統合:
    • RDS、ECS、Lambda、CodeBuildなど、様々なAWSサービスとシームレスに統合できます。
    • シークレットを必要とするAWSサービスの設定で、Secrets Managerのシークレットを直接参照できます。

【実務レベルの内容と重要事項】

Secrets Managerを実務で利用する上で重要な点は、セキュリティ、運用性、コストのバランスを考慮した設計と運用を行うことです。

セキュリティに関する重要事項

  • 最小権限の原則: IAMポリシーは必要最小限の権限のみを付与するように設計します。不要なユーザーやサービスにシークレットへのアクセス権を与えないように徹底します。
  • シークレットのローテーション戦略: ローテーション頻度、ローテーション方法、失敗時の対応などを事前に計画し、文書化しておきます。ローテーションLambda関数のテストも重要です。
  • 暗号化キーの管理: Secrets ManagerはデフォルトでAWS管理のキーでシークレットを暗号化しますが、機密性の高い情報についてはカスタマー管理のキー (CMK) を使用することを検討します。CMKのローテーションやアクセス制御も適切に行う必要があります。
  • 監査ログの監視: CloudTrailのログを定期的に監視し、不正アクセスや異常な操作がないか確認します。アラート設定も有効活用します。
  • VPCエンドポイントの利用: Secrets ManagerへのアクセスをVPC内からのみに制限するために、VPCエンドポイント (Secrets Manager API) の利用を検討します。インターネット経由での不要なアクセスを遮断します。

運用性に関する重要事項

  • シークレット名の命名規則: シークレット名を体系的に管理するための命名規則を策定します。環境 (dev/stg/prod)、アプリケーション名、シークレットの種類などを考慮した命名規則が有効です。
  • シークレットのバージョン管理: ローテーション履歴や変更履歴を把握するために、シークレットのバージョン管理機能を活用します。必要に応じて特定のバージョンにロールバックできるように準備しておきます。
  • DR (災害復旧) 対策: リージョンを跨いだDR構成を検討します。シークレットのレプリケーションや、DR環境でのローテーション設定などを事前に検証しておきます。
  • モニタリングとアラート: Secrets Managerの利用状況 (APIリクエスト数、エラー率など) をCloudWatchでモニタリングし、異常があればアラートを通知するように設定します。
  • ローテーションLambda関数の安定性: ローテーションLambda関数は、シークレットのローテーション処理の中核となるため、安定稼働が非常に重要です。十分なテストとエラーハンドリングを実装し、監視体制を構築します。

コストに関する重要事項

  • シークレット数とAPIリクエスト数: Secrets Managerの料金は、保存するシークレット数とAPIリクエスト数に基づいて課金されます。不要なシークレットを削除したり、APIリクエスト数を最適化したりすることでコストを削減できます。
  • キャッシュの活用: アプリケーション側でシークレットをキャッシュすることで、Secrets ManagerへのAPIリクエスト数を減らすことができます。ただし、キャッシュの有効期限切れや整合性維持には注意が必要です。
  • ローテーション頻度の見直し: ローテーション頻度が高すぎるとAPIリクエスト数が増加し、コスト増につながる可能性があります。セキュリティポリシーとコストのバランスを考慮して、適切なローテーション頻度を設定します。

【実務でどの程度使用されるのか】

AWS Secrets Managerは、セキュリティ意識の高い企業を中心に、実務で広く利用されています。特に、以下のようなケースで活用されています。

  • データベース認証情報の管理: RDS、Aurora、EC2上のデータベースなどの認証情報をSecrets Managerで集中管理し、ローテーションを自動化することで、セキュリティ強化と運用効率化を実現します。
  • APIキー、OAuthトークンの管理: 外部API連携に必要なAPIキーやOAuthトークンをSecrets Managerで安全に管理し、アプリケーションに配布します。
  • マイクロサービスアーキテクチャにおけるシークレット管理: 多数のマイクロサービスが連携するシステムにおいて、サービス間認証に必要なシークレットをSecrets Managerで一元管理し、サービスごとのアクセス制御を容易にします。
  • DevOps/CI/CDパイプラインにおけるシークレット管理: CI/CDパイプラインで利用する認証情報 (デプロイキー、APIキーなど) をSecrets Managerで管理し、コードへの埋め込みを回避します。
  • コンプライアンス要件への対応: PCI DSS、HIPAA、GDPRなどのコンプライアンス要件で求められる機密情報の保護措置として、Secrets Managerが有効です。監査ログ機能もコンプライアンス対応を支援します。

利用状況の具体例

  • 金融機関: 厳格なセキュリティ基準が求められる金融機関では、顧客情報やトランザクション処理に関わる機密情報をSecrets Managerで厳重に管理しています。
  • ECサイト: 顧客のクレジットカード情報や個人情報を扱うECサイトでは、データベース認証情報や決済APIキーなどをSecrets Managerで安全に管理しています。
  • SaaSプロバイダー: 複数の顧客にサービスを提供するSaaSプロバイダーでは、顧客ごとに異なる認証情報をSecrets Managerで効率的に管理しています。

利用規模

Secrets Managerは、スタートアップ企業から大企業まで、規模に関わらず利用されています。小規模なシステムであれば、シンプルな構成で導入できますし、大規模なシステムであれば、DR構成や高度なアクセス制御などを組み合わせて利用できます。

【terraformのコードで記述する場合の基本的内容と実務レベルの内容】

基本的なTerraformコード (シークレットの作成)

resource "aws_secretsmanager_secret" "example" {
  name                    = "my-secret" # シークレット名
  recovery_window_in_days = 7         # 削除保護期間 (日)
}

resource "aws_secretsmanager_secret_version" "example" {
  secret_id     = aws_secretsmanager_secret.example.id
  secret_string = jsonencode({ # シークレットの値 (JSON形式)
    username = "myuser"
    password = "mypassword"
  })
}

コード解説 (基本)

  • resource "aws_secretsmanager_secret" "example": シークレット本体を定義します。
    • name: シークレットの名前を指定します。
    • recovery_window_in_days: シークレットを削除した場合の回復期間 (削除保護) を指定します。
  • resource "aws_secretsmanager_secret_version" "example": シークレットのバージョン (実際の値) を定義します。
    • secret_id: 紐付けるシークレット本体のIDを指定します (aws_secretsmanager_secret.example.idで参照)。
    • secret_string: シークレットの値をJSON形式の文字列で指定します。テキスト形式のシークレットを扱う場合はこちらを使用します。バイナリ形式の場合はsecret_binaryを使用します。

実務レベルのTerraformコード (ローテーション設定、IAMアクセス許可、モジュール化)

# モジュール定義 (secrets-managerモジュール)
module "secrets" {
  source = "./modules/secrets-manager" # モジュールディレクトリ

  secret_name = "my-db-credentials"
  rotation_lambda_arn = module.rotation_lambda.lambda_function_arn # ローテーションLambda関数のARN
  rotation_rules = {
    automatically_after_days = 30 # 30日ごとにローテーション
  }
  policy_statements = [ # シークレットへのアクセス許可 (IAMポリシー)
    {
      actions = ["secretsmanager:GetSecretValue"]
      principals = [
        {
          type        = "AWS"
          identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/my-app-role"] # アプリケーションロール
        }
      ]
    }
  ]
}

# ローテーションLambda関数のモジュール (例)
module "rotation_lambda" {
  source = "./modules/rotation-lambda" # Lambda関数モジュール
  function_name = "my-db-rotation-lambda"
  # ... Lambda関数の設定 ...
}

# データソース (現在のアカウントIDを取得)
data "aws_caller_identity" "current" {}

モジュールディレクトリ構成例

├── modules
│   ├── rotation-lambda
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── secrets-manager
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── main.tf
├── variables.tf
└── outputs.tf

コード解説 (実務レベル)

  • モジュール化: module "secrets" でSecrets Manager関連のリソースをモジュール化しています。これにより、コードの再利用性、可読性、保守性が向上します。
  • ローテーション設定: rotation_lambda_arnrotation_rules を指定することで、自動ローテーションを設定しています。ローテーションLambda関数は別のモジュール (module "rotation_lambda") で定義し、ARNを渡しています。
  • IAMアクセス許可: policy_statements で、シークレットへのアクセスを許可するIAMポリシーを定義しています。アプリケーションロール (arn:aws:iam::...:role/my-app-role) に対してsecretsmanager:GetSecretValue権限を付与しています。
  • データソース: data "aws_caller_identity" "current" で現在のアカウントIDを取得し、IAMポリシー内で利用しています。これにより、アカウントIDをハードコーディングせずに済みます。
  • モジュールディレクトリ構成: モジュールごとにディレクトリを分け、main.tf, variables.tf, outputs.tf を配置することで、Terraformコードを整理しています。

実務におけるTerraformコードの重要事項

  • DR環境への対応: リージョンを跨いだDR環境を構築する場合は、Terraformで複数のリージョンにSecrets Managerリソースを定義し、レプリケーション設定を行う必要があります。
  • 動的なローテーション設定: 環境変数や外部ファイルからローテーション設定 (頻度、スケジュールなど) を動的に読み込むようにTerraformコードを設計することで、柔軟性を高めることができます。
  • IAM連携の強化: より複雑なアクセス制御要件に対応するために、IAMポリシーの詳細な設定 (条件、リソースベースポリシーなど) をTerraformで記述する必要があります。
  • テスト: Terraformコードの変更を適用する前に、terraform plan で変更内容を確認し、必要に応じて terraform apply を実行する前にテスト環境で検証することを推奨します。

上記はあくまで基本的な例であり、実際のシステム要件に合わせてTerraformコードをカスタマイズする必要があります。Terraform Registryで公開されているSecrets Managerモジュール (例: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) を参考にすることも有効です。

Discussion