今更ではあるのですが、最近、少しずつ AWS を個人で触っています。
クラウドワークスさんの約3年半前の以下の記事を今のタイミングで実装した際に、いくつか変更が必要なところがあったので、自分向けの備忘録として残しておこうと思います。
そもそも、今だと目的を達成するためだけであればもっとシンプルな実装方法がある気はしますが、そこはあえて気にしない。
変更した選択条件
[ ~]$ aws --version aws-cli/2.0.8 Python/3.7.4 Darwin/17.7.0 botocore/2.0.0dev12
その他 AWS マネジメントコンソールの入力フォームにもいくつか違っている箇所はありましたが、戸惑うところはあまりなかったので、省略します。
AWS Lambda で curl は叩けなくなった
AWS Lambda から curl コマンドを叩くと command not found になる感じでした。
AWS Lambda の環境に curl コマンドが含まれなくなったみたいです。
ということで、curl を実行している箇所(import の箇所と、notify メソッドの中身)を urllib.request で書き換えます。
具体的には、ここの箇所を、
import json import commands import urllib ... def notify(message, channel, web_hook_url): payload = { "text": message, "channel": channel, "username": "AWSアカウントモニターBot", "icon_emoji": ":ghost:" } escaped_payload = urllib.quote_plus(json.dumps(payload).encode('utf-8')) curl_command = 'curl -s -X POST -d "payload=%s" %s' % (escaped_payload, web_hook_url) return commands.getoutput(curl_command)
こんな感じに書き換えます。
import json import urllib.request import urllib.parse ... def notify(message, channel, web_hook_url): payload = { "text": message, "channel": channel, "username": "AWSアカウントモニターBot", "icon_emoji": ":ghost:" } encoded_payload = urllib.parse.urlencode({'payload': payload}).encode('utf-8') with urllib.request.urlopen(url=web_hook_url, data=encoded_payload) as f: return f.read().decode('utf-8')
AWS CLI で KMS で秘密情報を暗号化しようとすると Invalid base64
エラーになる
AWS CLI で KMS で Slack の Incoming Webhooks の文字列を暗号化しようとすると、こんな感じでエラーになります。
[ ~]$ aws kms encrypt --region us-east-1 --output text --query CiphertextBlob --key-id alias/lambda_encryption --plaintext //hooks.slack.com/services/********/xxxxxxxx/xxxxxxxx Invalid base64: "//hooks.slack.com/services/********/xxxxxxxx/xxxxxxxx"
以下の AWS CLI の注意事項にありますが、セキュリティ上の懸念点の解消のためか、バージョン2から plaintext で渡す文字列は、デフォルトで base64 エンコードしてあげる必要があるみたいです。
base64 エンコードした文字列を指定するのもいいのですが、以下のように fileb://〜 でバイナリの形で標準入力から渡してあげると簡単です。
[ ~]$ aws kms encrypt --region us-east-1 --output text --query CiphertextBlob --key-id alias/lambda_encryption --plaintext fileb://<(echo "//hooks.slack.com/services/********/xxxxxxxx/xxxxxxxx") AQICAHic78b********YsIjaYI=
Python3 なので str と bytes はそのままでは連結できない
KMS で暗号化した Slack の Incoming Webhooks の文字列を AWS Lambda 内で復号する際、以下のコードが示されていますが、そのままだと 'https:' と復号した文字列を連結する箇所で TypeError: can only concatenate str (not "bytes") to str
で怒られます。
def get_web_hook_url(web_hook_url_encrypted): return 'https:' + decrypt(web_hook_url_encrypted) def decrypt(encrypted): import boto3 import base64 return boto3.client('kms').decrypt(CiphertextBlob=base64.b64decode(encrypted))['Plaintext']
復号した文字列の型は str ではなく bytes のため怒られています。そのままでは連結できないため decode で str に変換して連結します。
def get_web_hook_url(web_hook_url_encrypted): return 'https:' + decrypt(web_hook_url_encrypted) def decrypt(encrypted): import boto3 import base64 return (boto3.client('kms').decrypt(CiphertextBlob=base64.b64decode(encrypted))['Plaintext']).decode('utf-8')
まとめ
ということで、少し変更するだけで、とりあえず動かすことができました。しあわせです。