目標
- Chatworkに定期的に固定メッセージを流す
- AWS Lambdaを使う
herokuとheroku scheulerを使えば同じことが、無料で実現できます。AWS Lambdaを使うのは趣味です。
Heroku Schedulerを使ってChatworkに定期ポストする - Qiita
作戦
- Amazon CloudWatch Eventsを使ってLambda関数を定期実行
- AWS Key Management Serviceを使ってChatworkのAPI Tokenを安全に管理
- ledsun/post-chatwork-messageを使ってChatworkに投稿
KMSを使う必要性について
Environment Variables - AWS Lambda
によると
環境変数を使用する Lambda 関数を作成するか、または更新する場合、AWS Lambda は AWS Key Management Service を使用してそれらを暗号化します
とあるので環境変数のkeyとvalueはKMSを使って暗号化されているはずです。ただし
ただし、環境変数に機密情報を保存する必要がある場合は、Lambda 関数をデプロイする前にその情報を暗号化することを強く推奨します
と、あります。今回は素直にKMSを使ってChatwork API Tokenを暗号化します。
必要な権限
- ClowdWatch Events: イベントの作成
- KMS: マスターキーの作成とChatwork API Tokenの暗号化
- Lambda: 作成と実行します
- IAM Role作成: lambda関数作成時にroleを作成します
実装
AWS Key Management ServiceへのChatwork API Tokenの保存
AWS Key Management Serviceで暗号化した文字列をNode.jsで復号化する - Qiitaの手順でChatwork API Tokenを暗号化した文字列を作成します。
lambda関数の作成
ソースコード
const AWS = require('aws-sdk')
const postChatworkMessage = require('post-chatwork-message')
const encryptedToken = process.env.ENCRYPTED_CHATWORK_API_TOKEN
const message = 'hello'
exports.handler = function(event, context) {
new AWS.KMS({
region: 'ap-northeast-1'
})
.decrypt({
CiphertextBlob: new Buffer(encryptedToken, 'base64')
}, (err, data) => {
if (err) {
console.log(err)
return context.fail(err)
}
postChatworkMessage(data.Plaintext.toString(), process.env.CHATWORK_ROOM_ID, message)
})
}
圧縮
lambda関数をアップロードするためにzipファイルを作成します。
npm i aws-sdk post-chatwork-message
zip deploy_package index.js -r node_modules
deploy_package.zipができます。
npmはversion3以降、依存ライブラリーをnode_modulesディレクトリ配下にフラットに展開します。
個別のモジュールではなく、node_modulesディレクトリ全体を圧縮ファイルに入れます。
アップロード
- Lambda Management Consoleを開く
TriggerにCloudWatch Eventsを選択
Rule nameに
hourly
を入力Rule descriptionに
hourly test
を入力Schedule expressionで
rate(1 hour)
を選択Enable triggerをチェック
Nameに
hourly-test
を入力Code entry typeを
Upload a .Zip file
に変更Environment variablesに
ENCRYPTED_CHATWORK_API_TOKEN
:暗号化したChatwork Token文字列を入力Environment variablesに
CHATWORK_ROOM_ID
:投稿したいChatwork room id(数字のみ)を入力Nextボタンをクリック
Create functionボタンをクリック
作成したIAMロールにKMSの参照権限を設定
- IAM Management Consoleを開く
AWS サービスで
AWS Key Management Service
を選択アクションで
Decrypt
を選択Amazon リソースネーム(ARN)にChatwork API Tokenを暗号化したときに表示されるKey Idの文字列を入力
次のステップボタンをクリック
ポリシーの適用ボタンをクリック
KMSの参照権限がない場合は以下のようなエラーが起きます
START RequestId: 586c96ad-cc45-11e6-86ad-a3780462e53e Version: $LATEST
2016-12-27T15:01:30.301Z 586c96ad-cc45-11e6-86ad-a3780462e53e { [AccessDeniedException: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access.]
message: 'The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access.',
code: 'AccessDeniedException',
time: Tue Dec 27 2016 15:01:30 GMT+0000 (UTC),
requestId: '5929f33e-cc45-11e6-9514-1130ca261caa',
statusCode: 400,
retryable: false,
retryDelay: 55.074393190443516 }
END RequestId: 586c96ad-cc45-11e6-86ad-a3780462e53e
REPORT RequestId: 586c96ad-cc45-11e6-86ad-a3780462e53e Duration: 977.18 ms Billed Duration: 1000 ms Memory Size: 128 MB Max Memory Used: 32 MB
追記: Policy templatesを使う
Roleを作成する際に、Policy templatesにKMS decryption permissions
を選択すると、KMSの参照権限を設定できます。
設定されるポリシーは次の通りです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:ap-northeast-1:275624216953:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:ap-northeast-1:275624216953:log-group:/aws/lambda/seven-trumpets:*"
]
}
]
}
Resourceを特定のものに制限したい場合は、手動で設定します。
動作確認
Testボタンを押すと、試しに投稿できます。
Input test eventは使っていません、何を入力しても構いません。