外部からawsのインスタンスの状態確認などを行うのに、インスタンスへ接続してコマンドをたたくのがめんどくさい場合に、簡単かつ安全にaws cliを操作したい場合のために、slackのslash commandを利用できるようにしました。
目次
lambda用資材の準備
pipのインストール
sudo yum install epel-release sudo yum install python-pip --enablerepo=epel sudo pip install --upgrade pip
アップロード用モジュールの作成
mkdir aws_cli
cd aws_cli
pip install awscli -t ./
pip install colorama -t ./
pip install pyasn1 -t ./
pip install simplejson -t ./
pip install argparse -t ./
pip install pyyaml -t ./
awsコマンド実行ソース
ソースファイル名:aws
#!/usr/bin/python import sys import os if os.environ.get('LC_CTYPE', '') == 'UTF-8': os.environ['LC_CTYPE'] = 'en_US.UTF-8' import awscli.clidriver def main(): return awscli.clidriver.main() if __name__ == '__main__': sys.exit(main())
lambda用関数のソース
ソースファイル名:lambda_function.py
import commands
import json
import os
from cStringIO import StringIO
import re
import logging
from base64 import b64decode
from urllib2 import Request, urlopen, URLError, HTTPError
from time import sleep
logger = logging.getLogger()
logger.setLevel(logging.INFO)
print('Loading function')
def _(cmd):
return commands.getoutput(cmd)
def lambda_handler(event, context):
logger.info("Event: " + str(event))
if event['token'] != 'slack slash commandで設定された値':
return("error")
etext = event['text']
ans = _("./aws " + etext)
response_url = event['response_url']
slack_message = {
'channel': '@%s' % event['user_name'],
'response_type': 'ephemeral',
'isDelayedResponse': 'true',
'text': ans
}
logger.info("Send message to %s %s", response_url, slack_message)
req = Request(response_url)
req.add_header('Content-Type', 'application/json')
response = urlopen(req, json.dumps(slack_message))
response.read()
logger.info("Message posted to %s", slack_message['channel'])
return("ok")
slack slash commandで設定された値を設定するため、1回作った後に再度変更する必要があります。
資材をzipに固める
chmod 755 -R *
zip -r ../aws_cli.zip *
lambdaの設定

先ほど作ったzipファイルをアップロードします。

aws cliの実行に時間がかかるため、タイムアウトを5分に設定します。

lambdaのロールに自分が制御したいサービスの権限を付加します。
この例では、EC2とS3のアクセス権を追加しています。
api gatewayの設定

GETメソッドを追加します

GETメソッドリクエストのURLクエリ文字列パラメータにslackから渡されるパラメータを追加します。
channel_name
user_id
command
text
team_id
token
channel_id
team_domain
response_url
user_name

GET統合リクエストを編集します。

マッピングテンプレートにlambda関数へ引き渡すパラメータをセットします。
{
"channel_name" : "$input.params('channel_name')",
"user_id" : "$input.params('user_id')",
"command" : "$input.params('command')",
"text" : "$input.params('text')",
"team_id" : "$input.params('team_id')",
"token" : "$input.params('token')",
"channel_id" : "$input.params('channel_id')",
"team_domain" : "$input.params('team_domain')",
"response_url" : "$input.params('response_url')",
"user_name" : "$input.params('user_name')",
"apiId" : "$context.apiId"
}

ステージングを行います。

URLの呼び出しを控えておきます。slackの設定で使用します。
slack slash commandの設定
slackにログインした後、下のURLへアクセスしてください。
https://my.slack.com/services/new/slash-commands

コマンドを入力して、追加してください。

API Gatewayで取得したURLを設定してください。
トークンを、lambda_function.pyに設定して、zipに固めなおし、lambdaへ再アップロードしてください。
使用例
ec2のインスタンスの状態を取得
/aws ec2 describe-instances --query 'Reservations[*].Instances[*].[Placement.AvailabilityZone, State.Name, InstanceId]' --output text
結果
ap-northeast-1a stopped i-04
ap-northeast-1a running i-0a
S3バケットを表示
/aws s3 ls
結果
2019-03-27 05:39:00 aws-athe
2019-02-07 04:02:40 aws-logs