SSM Parameter Store(SecureString)の値を Lambda(boto3)で安全に取得する手順(超簡易版)

Lambdaのアイキャッチ

概要

APIキーなどの機密情報を CloudFormation テンプレートや Git に直接書かず、事前作成した Parameter Store から Lambda 実行時に安全に取得する構成の備忘録です。

💡 この構成のメリット

  • セキュリティ向上: APIキーが Git や Cfn 履歴に残らず、Inspector や GitLeaks などのセキュリティチェックを完全にクリアできる。
  • 環境ごとの使い回し: 開発(dev)・本番(prod)で同じ CloudFormation テンプレートをそのまま使い回せる。
  • レイヤー不要: AWS Extension レイヤーを使わず boto3 で取得するため、バージョン依存や設定エラーのトラブルが起きない。

手順 1: AWS CLI で Parameter Store に API キーを事前登録

手動または CLI で、あらかじめ SecureString(KMS暗号化)としてパラメータを作成します。
「CloudShell」を用いて実行するのが楽です!

aws ssm put-parameter \
    --name "/my-app/api-key" \
    --value "your-actual-api-key-here" \
    --type "SecureString" \
    --description "API key for My App Lambda"

今回は /my-app/api-key:your-actual-api-key-here で登録しました。

手順 2: CloudFormation で Lambda と IAM ロールをデプロイ

事前に作成したパラメータ名(/my-app/api-key)を指定して読み込む Lambda 構成です。

AWSTemplateFormatVersion: '2010-09-09'
Description: Lambda fetching SSM Parameter using boto3 (No Layers)

Parameters:
  ApiKeyParamName:
    Type: String
    Default: /my-app/api-key
    Description: Parameter Store parameter name

Resources:
  # 1. IAM ロール(SSM読み取り + SecureString復号のためのKMS権限)
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: GetSSMParameterPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - ssm:GetParameter
                Resource: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter${ApiKeyParamName}"
              - Effect: Allow
                Action:
                  - kms:Decrypt
                Resource: "*"

  # 2. Lambda 関数本体
  MyLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: ssm-boto3-test-lambda
      Runtime: python3.12
      Handler: index.lambda_handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Timeout: 10
      Environment:
        Variables:
          API_KEY_PARAM_NAME: !Ref ApiKeyParamName
      Code:
        ZipFile: |
          import os
          import json
          import boto3

          # boto3のSSMクライアントを初期化
          ssm = boto3.client('ssm')
          PARAM_NAME = os.environ.get('API_KEY_PARAM_NAME')

          def get_api_key():
              # WithDecryption=True で SecureString (KMS暗号化) を自動復号して取得
              response = ssm.get_parameter(
                  Name=PARAM_NAME,
                  WithDecryption=True
              )
              return response['Parameter']['Value']

          def lambda_handler(event, context):
              try:
                  api_key = get_api_key()
                  
                  # テスト用出力(ログ確認用)
                  print(f"[DEBUG] boto3で取得したAPIキー: {api_key}")
                  
                  return {
                      'statusCode': 200,
                      'body': json.dumps({'message': 'Success!', 'key_length': len(api_key)})
                  }
              except Exception as e:
                  print(f"[ERROR] 取得失敗: {str(e)}")
                  raise e

手順 3: 動作確認

  1. AWS マンジメントコンソールで作成された Lambda 関数(ssm-boto3-test-lambda)を開く。
  2. 「テスト」 タブを選択する。
  3. イベント JSON はデフォルトのままとし、イベント名を任意(例: Test)で入力して保存する。
  4. 「テスト」 ボタンを実行し、statusCode: 200 が返ること、およびログ出力に API キー([DEBUG] ...)が表示されることを確認する。

📌 まとめ(今回の成果と背景)

開発環境と本番環境で CloudFormation テンプレートを100%使い回すため、「APIキー(値)は事前に SSM Parameter Store に手動登録し、Lambda 側からは boto3 で動的に読み込む」 構成を採用しました。

当初検討していた Extension レイヤーはバージョンや ARN の不一致でトラブルになりやすいため排除し、Python 標準の boto3 を採用。1日1回×4アカウント程度の実行規模であれば API 制限(Throttling)の心配もなく、レイヤーの管理コストゼロで安定運用できます。