SSMのパラメータストアを活用して Lambda で機密情報 (SecureString) を扱う with AWS SAM

SSMのパラメータストアを活用して、Lambdaで機密情報(Secure String)を扱ってみました。 サンプルとして、SlackのWebhookURLをパラメータストアに格納してみました。
2019.07.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Slackにメッセージを通知するLambdaを作っていると、Webhook URLの扱いに困ります。

ソースコード内にべた書きしたくないので、デプロイ時に環境変数として与えていました。

この運用もめんどくさいと感じていたところ、「SSMのパラメータストアを使えばいいんじゃね?」となったので、試してみました。

おすすめの方

  • Lambdaでパラメータストア(安全な文字列)を使いたい
  • AWS SAMでパラメータストア(安全な文字列)を使いたい

目次

環境

項目 バージョン
macOS Mojave 10.14.5
AWS CLI aws-cli/1.16.174 Python/3.6.1 Darwin/18.6.0 botocore/1.12.164
AWS SAM CLI 0.17.0
Python 3.6

AWS SAMのサーバーレスアプリケーションを用意する

下記のサーバーレスアプリケーションを流用します。

今のWebhook URLの扱い

template.yamlでLambdaの環境変数として定義しています。

template.yaml(一部抜粋)

Parameters:
  SlackWebhookUrl:
    Type: String
    Default: hoge

Resources:
  NotifyPeriodicFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: periodic.lambda_handler
      Runtime: python3.6
      Environment:
        Variables:
          # このURLはコミット&公開したくないため、デプロイ時にコマンドで設定する
          SLACK_WEBHOOK_URL: !Ref SlackWebhookUrl
      Events:
        NotifySlack:
          Type: Schedule
          Properties:
            Schedule: cron(1/10 23 * * ? *) # 日本時間AM8時1分から10分毎に毎日通知する

環境変数の値は、デプロイ時にparameter-overridesオプションで渡しています。

sam deploy \
    --template-file packaged.yaml \
    --stack-name NotifyTrainDelayToSlack \
    --capabilities CAPABILITY_IAM \
    --parameter-overrides SlackWebhookUrl=https://hooks.slack.com/services/xxxxxxxxxxxxx

これをパラメータストアの利用に置き換えます!

パラメータストアを利用する

AWS側の設定

System Managerにアクセスします。

System Managerを検索する

左側メニューの最下部にある「パラメータストア」を選択します。

パラメータストアを選択する

「パラメータストアの作成」を選択します。

パラメータの作成を選択する

いろいろと入力します。

項目 内容
名前 NotifyTrainDelayToSlack-WebhookURL
説明 適当に入力
利用枠 標準
タイプ 安全な文字列
KMS の主要なソース 現在のアカウント
実際のWebhookURL

入力後、右下の「パラメータの作成」を選択します。

パラメータの作成を選択する

パラメータストアにWebhookURLを保存する作業は、以上で完了です!

SAMテンプレートの修正

変更点は下記です。

  • Lambdaの環境変数をバッサリ削除する
    • SecureStringは、CloudFormationで未サポートのため
  • AmazonSSMReadOnlyAccessのポリシーを明示的に定義する

template.yaml(一部抜粋)

Resources:
  NotifyPeriodicFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: periodic.lambda_handler
      Runtime: python3.6
      Policies:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess
      Events:
        NotifySlack:
          Type: Schedule
          Properties:
            Schedule: cron(1/10 23 * * ? *) # 日本時間AM8時1分から10分毎に毎日通知する

Lambdaコードの修正

下記のようにして、パラメータストアからWebhookURLを取得します。

periodic.py(一部抜粋)

import boto3

ssm = boto3.client('ssm')

def get_notify_url() -> str:
    # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter
    response = ssm.get_parameter(
        Name='NotifyTrainDelayToSlack-WebhookURL',
        WithDecryption=True
    )
    return response['Parameter']['Value']

動作確認

Lambdaを手動実行させます。

Slackに通知された!

無事に通知されました!!

Slashコマンドによる通知も問題なしです。

さいごに

サクッと使えるのがありがたいですね。

全体のコードはGitHubにあります。

参考