Serverless Framework でクレデンシャル情報を扱う Lambda ファンクションを作成する

Serverless Framework, AWS Secrets Manager を使ってクレデンシャル情報を扱う Lambda ファンクションの作り方を紹介します。
2020.07.07

こんばんは!黒糖饅頭がブームの です。

はじめに

最近、Serverless Framework を使って改善業務に取り組んでいます。 取り組んでいる中で、Serverless Framework でクレデンシャル情報を扱う Lambda ファンクションを作成する方法を確認しました。 今回はこちらの方法の一つをご紹介します。

目標

AWS Secrets Manager から Slack チャンネルの Webhook URL を取得して、 Slack チャンネルにメッセージを投稿する Lambda ファンクションを Serverless Framework で作成します。

やってみた

以下の流れで作業します。

  1. Slack 側の準備
  2. AWS Secrets Manager の設定
  3. Serverless Framework のサービス作成
  4. Serverless Framework のサービスデプロイ
  5. 動作確認

1. Slack 側の準備

Incoming Webhook の設定

次のページを参考に Incoming Webhook の設定をしてください。

Slack での Incoming Webhook の利用

https://hooks.slack.com/services/XXX/YYY/ZZZ のような形式の Webhook URL を確認しておきます。

2. AWS Secrets Manager の設定

マネジメントコンソールから確認した Slack のクレデンシャル情報を登録します。

  • SLACK_WEBHOOK_URL:確認した Webhook URL

シークレットの名前を付けます。ここでは、dev/slack とします。

今回は自動ローテーションは不要なので、自動ローテーションを無効にするにチェック入れます。

シークレットが正常に保存されれば OK です。

3. Serverless Framework のサービス作成

Serverless Framework 実行環境構築は省略します。 構築方法は以下を参照ください。

初めてのサーバーレスアプリケーション開発 ~Serverless Framework を使ってAWSリソースをデプロイする~ -> Serverless Framework実行環境構築

サービス作成

Serverless Framework のサービスを作成します。 今回は slack-post-serviceというサービス名で、Python 3.8の Lambda ファンクションを作成します。

$ serverless create --template aws-python3 --path slack-post-service
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "{省略}"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.72.0
 -------'

Serverless: Successfully generated boilerplate for template: "aws-python3"

プラグインインストール

この後登場する Lambda ファンクションで用いる外部モジュールの為に必要なプラグイン(serverless-python-requirements)をインストールします。

$ sls plugin install -n serverless-python-requirements

serverless.yml の編集

serverless.yml でサービスを定義します。

service: slack-post-service

provider:
  name: aws
  runtime: python3.8
  region: ap-northeast-1
  profile: ${opt:profile, "default"}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - secretsmanager:GetSecretValue
      Resource:
        - "*"

plugins:
  - serverless-python-requirements

functions:
  post_content:
    handler: handler.post_content
    environment:
      SECRET_NAME: dev/slack

ハイライトの箇所がポイントです。

  • iamRoleStatements で AWS Secrets Manager へのアクセスを許可しています(必要に応じて Resource を絞ってください)
  • Lambda ファンクションの環境変数として、作成したシークレットの名前を記載

handler.py の編集

handler.py で Slack にメッセージを POST する Lambda ファンクションを作成します。

import os
import boto3
import json
import requests

# Get credentials
secret_name = os.environ['SECRET_NAME']
secretsmanager_client = boto3.client('secretsmanager', region_name='ap-northeast-1')
resp = secretsmanager_client.get_secret_value(SecretId=secret_name)
secret = json.loads(resp['SecretString'])

SLACK_WEBHOOK_URL = secret['SLACK_WEBHOOK_URL']

def post_content(event, context):
    payload = {
        "text": "テスト投稿"
    }
    content = json.dumps(payload)
    response = requests.post(SLACK_WEBHOOK_URL, data=content)
    return

ハイライトの箇所がポイントです。

  • serverless.yml で設定した Lambda ファンクションの環境変数からシークレットの名前を取得
  • シークレットの名前を元にクレデンシャル情報(Webhook URL)を取得

4. Serverless Framework のサービスデプロイ

デプロイ

サービスをデプロイします。

$ cd slack-post-service/
$ sls deploy -v
{省略}

5. 動作確認

Lambda ファンクションを実行する

デプロイされたLambdaファンクションを実行します。

sls invoke -f post_content

対象の Slack を確認すると、メッセージが投稿されていることが確認できました!

おわりに

誰かの参考になると幸いです。それでは良い夜を!

更新履歴

  • プラグインのインストール方法を変更しました(2020/10/16)