Help us understand the problem. What is going on with this article?

AWS LambdaからChatworkに定時通知する

目標

  1. Chatworkに定期的に固定メッセージを流す
  2. AWS Lambdaを使う

herokuとheroku scheulerを使えば同じことが、無料で実現できます。AWS Lambdaを使うのは趣味です。
Heroku Schedulerを使ってChatworkに定期ポストする - Qiita

作戦

  1. Amazon CloudWatch Eventsを使ってLambda関数を定期実行
  2. AWS Key Management Serviceを使ってChatworkのAPI Tokenを安全に管理
  3. 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関数の作成

ソースコード

index.js
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ディレクトリ全体を圧縮ファイルに入れます。

アップロード

  1. Lambda Management Consoleを開く
  2. Blank Functionを選択
    スクリーンショット 2017-01-04 19.01.43.png

  3. TriggerにCloudWatch Eventsを選択

  4. Rule nameにhourlyを入力

  5. Rule descriptionにhourly testを入力

  6. Schedule expressionでrate(1 hour)を選択

  7. Enable triggerをチェック

  8. Nextボタンをクリックスクリーンショット 2017-01-04 19.06.04.png

  9. Nameにhourly-testを入力

  10. Code entry typeをUpload a .Zip fileに変更

  11. Uploadボタンを押してdeploy_package.zipを選択スクリーンショット 2017-01-04 19.12.15.png

  12. Environment variablesにENCRYPTED_CHATWORK_API_TOKEN:暗号化したChatwork Token文字列を入力

  13. Environment variablesにCHATWORK_ROOM_ID:投稿したいChatwork room id(数字のみ)を入力スクリーンショット 2017-01-04 19.44.28.png

  14. Role nameにchatwork-hourly-testを入力スクリーンショット 2017-01-04 19.13.44.png

  15. Nextボタンをクリック

  16. Create functionボタンをクリック

作成したIAMロールにKMSの参照権限を設定

  1. IAM Management Consoleを開く
  2. インラインポリシーを開いて、「作成するには、ここをクリックしてください。」をクリックスクリーンショット 2017-01-04 19.17.34.png

  3. 選択ボタンをクリックスクリーンショット 2017-01-04 19.27.05.png

  4. AWS サービスでAWS Key Management Serviceを選択

  5. アクションでDecryptを選択

  6. Amazon リソースネーム(ARN)にChatwork API Tokenを暗号化したときに表示されるKey Idの文字列を入力

  7. ステートメントを追加ボタンをクリックスクリーンショット 2017-01-04 19.29.51.png

  8. 次のステップボタンをクリック

  9. ポリシーの適用ボタンをクリック

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は使っていません、何を入力しても構いません。

参考

ledsun
編集リクエスト、コメント大歓迎です。
luxiar
Ruby on Rails専門のWebアプリケーション開発に特化した町田の受託開発企業です
http://www.luxiar.com/index.html
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした