はじめに
アノテーション テクニカルサポートの川崎です。
社内育成の素材として、Serverless Framework を使用してデプロイするアプリを、アプリ作成の課題として、チームのメンバーに取り組んでもらっております。
その過程で経験したことを、Serverless Framework のデプロイ手順としてまとめてみます。
今回は、トークンやAPIキーを、最低限、コードのバージョン管理に含めずに利用する方法を確認しました。
git で管理するべきでない機密情報を取り扱う際に、よく利用される手段の1つとして .env があります。 Serverless Framework で .env ファイルを使い、環境変数を設定する手順について確認しました。
ご注意
このブログでは機密情報を .env ファイルに平文のまま記載する方法を説明しています。
AWS の SSM パラメータストアや Secrets Manager を利用し、暗号化することで、 トークンやAPIキーをよりセキュアに処理する手段が用意されていますので、必要に応じてご利用ください。
.env を利用する2つの方法
Serverless Framework には serverless-dotenv-plugin というプラグインがあります。 一方で、Serverless Framework の v3 では .env の利用はネイティブサポートされており、 プラグインを使わなくても .env を利用することができます。
以下では、プラグインを使わない方法を説明していきます。
- .env のネイティブサポートによる方法 ← このブログで説明する方法
- serverless-dotenv-plugin を使う方法
.env のネイティブサポート (serverless-dotenv-plugin を使わない方法)
serverless.yml で「useDotenv: true」を指定することで、 .env から環境変数を読み込む機能を有効化できます。
それでは、手順を見ていきます。
テンプレート「aws-python3」を指定して、Serverless サービスを新規作成します。
% mkdir dotenv1
% cd dotenv1
% sls create --template aws-python3
% rm handler.py
% touch lambda_function.py
テンプレートから生成された handler.py は削除し、lambda_function.py というファイル名で、Lambda Python のサンプルコードを記述します。
今回は、Slack APIを用いて、指定のチャンネルからメッセージを取得する Python の Lambda 関数を作成します。
Slack API のアプリを作成する手順は、本ブログでは触れませんので、 下記ブログ記事などを参考にしていただければと思います。 (Slack API のアプリのスコープも設定する必要があります。)
Slack に関連する処理は、別ファイル slack_requests.py に切り出しています。
5-6行目で、Lambda 関数の環境変数から TOKEN と CHANNEL_ID の値を取得します。 TOKEN と CHANNEL_ID を指定して、Slack API の conversations.history にアクセスし、メッセージを取得します。
lambda_function.py
from slack_requests import get_messages_from_channel
def lambda_handler(event, context):
# チャンネルから最新のメッセージを取得する
messages = get_messages_from_channel()
latest_message = messages[0] if messages else None
return None
slack_requests.py
import os
import json
import requests
TOKEN = os.environ["SLACK_BOT_TOKEN"]
CHANNEL_ID = os.environ["CHANNEL_ID"]
def get_messages_from_channel():
url = "https://slack.com/api/conversations.history"
headers = {"Authorization": f"Bearer {TOKEN}"}
payload = {"channel": CHANNEL_ID}
response = requests.get(url, headers=headers, params=payload)
return response.json().get("messages")
テンプレートから生成された serverless.yml を以下の内容で上書きします。
4行目で「useDotenv: true」を指定して、.env から環境変数を読み込む機能を有効にしています。 デフォルトでは false です。
14-16行目で、Lambda 関数の環境変数を追加しています。
以上の設定を行うことで、.env ファイルに指定した内容を読み込んで、Lambda 関数の環境変数に指定することができます。便利ですね!
※ .env ファイルに指定する内容は、後述します。
serverless.yml
service: dotenv1
frameworkVersion: '3'
useDotenv: true
provider:
name: aws
runtime: python3.11
region: ap-northeast-1
functions:
slack-request:
handler: lambda_function.lambda_handler
environment:
SLACK_BOT_TOKEN: ${env:SLACK_BOT_TOKEN}
CHANNEL_ID: ${env:CHANNEL_ID}
plugins:
- serverless-python-requirements
serverless.yml の設定ができたら、serverless-python-requirements プラグインをインストールします。
Python を使う場合は、ほぼ必須のプラグインですね!
利用する外部モジュール名を、requirements.txt ファイルに記述しておきます。
% sls plugin install -n serverless-python-requirements
% echo requests > requirements.txt
.env ファイルを作成し、SLACK_BOT_TOKEN、CHANNEL_ID の値を記述します。
% touch .env
.env
SLACK_BOT_TOKEN=xoxb-xxxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx
CHANNEL_ID=Cxxxxxxxxxx
git 管理から除外するために、忘れずに .gitignore ファイルに「.env」を追記しておきます。
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# Serverless directories
.serverless
.env
上記の設定ができたら、デプロイを実行します。
% sls deploy --aws-profile sls-user
デプロイが成功したら、invoke コマンドで、デプロイした Lambda 関数を実行してみます。
% sls invoke -f slack-request --aws-profile sls-user
Running "serverless" from node_modules
{
"bot_id": "XXXXXXXXXXX",
"type": "message",
"text": "Slack のテストメッセージ",
"user": "XXXXXXXXXXX",
"ts": "1698998672.511469",
"app_id": "XXXXXXXXXXX",
"blocks": [
{
"type": "rich_text",
"block_id": "xxxxx",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "Slack のテストメッセージ"
}
]
}
]
}
],
"team": "XXXXXXXXXXX",
"bot_profile": {
"id": "XXXXXXXXXXX",
"deleted": false,
"name": "sample-channel1",
"updated": 1692781566,
"app_id": "XXXXXXXXXXX",
"icons": {
"image_36": "https://a.slack-edge.com/xxxxx/img/plugins/app/bot_36.png",
"image_48": "https://a.slack-edge.com/xxxxx/img/plugins/app/bot_48.png",
"image_72": "https://a.slack-edge.com/xxxxx/img/plugins/app/service_72.png"
},
"team_id": "XXXXXXXXXXX"
}
}
Lambda 関数が実行され、指定のチャンネルから最新のメッセージを取得できました!
まとめ
Serverless Framework の v3 では .env の利用方法として、2つの方法があり、 本ブログではネイティブサポートによる方法を説明しました。
- .env のネイティブサポートによる方法
- serverless-dotenv-plugin を使う方法
最初は、どちらを使えばいいのかわからず、少々混乱したのですが、 手順としては、シンプルな方法で実現されているのが確認できました。
参考資料
[1] Resolution of environment variables
[2] Serverless Framework - Upgrading to v3
[3] Serverless Framework - AWS Lambda Guide - Serverless.yml Reference
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。