LoginSignup
4
2

More than 1 year has passed since last update.

AWS ChatbotでSlackからLambda関数(Go)を呼び出す 

Last updated at Posted at 2021-08-10

はじめに

CICDの一環でGoのLambdaをSlackから呼び出す仕組みを構築したのでその備忘録を残す。
(Goは初見だったので少しGoを触った所も書き残した。)

Slack-AWS Chatbot Lambda実行.png

Goを使ってみる

install

https://golang.org/doc/install からDowloadしてくる。
go versionでGoのバージョンが表示されればOK。

C:\Users\user>go version
go version go1.16.7 windows/amd64

hello world

はじめてのGo

hello
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

実行結果は以下のようになる。
CIでGoを動かすのに使ったのはこれ

# Execute Go code
go run .
Hello, World!

hello world②(他のパッケージを呼び出す)

別のmoduleを利用する

hello
package main

import "fmt"
import "rsc.io/quote"

func main() {
    fmt.Println("Hello, World!")
    fmt.Println(quote.Go())
}
# Execute Go code
go run .
Hello, World!

Goの言語仕様について

以下のサイトが分かりやすく参考にさせて頂いた

:=

変数の宣言+代入を同時に実行する(変数の宣言を省略している)

&

変数の値そのものではなくポインターを渡すために使う

Goには変数の型にポインタータイプ(Pointer types)というものがあり、他の言語でいう参照型になる変数が明確に型として定義されている
ので、例えば文字列でも以下のように2パターンを見かける

  • string
    純粋に値そのものが格納された変数(リテラル)
  • *string
    値ではなくstringの変数が可能されているメモリのポインターが格納された変数

具体的には、

import(
   "github.com/aws/aws-sdk-go/aws/session"
)

func aws() {
   region := os.Getenv("REGION")

   mySession, err := session.NewSession(&aws.Config{
      Region: &region,
   })
}

のようにAWSのSDKを使いセッションを作る時、ConfigRegion*stringとなっているのでこれはポインターの参照を与える必要がある
この時に、&を使って渡すとstringのポインター(*string)を渡す事ができる

・参考:https://github.com/aws/aws-sdk-go/blob/0caab5abe6b25070faba0ecd2b870288d392c5d8/aws/config.go#L33

GoのLambda関数を作成しDeploy

関数の作成

AWS公式をみてまずはコピペでLambda関数を作ってみる。
https://github.com/yuta-katayama-23/Go/commit/725f6887f47693ce3c9c5249fb98737bff017dd6#diff-decea487f8d3f70e6cd009e31ddbd0aacfd2258125f30b612a6c6415b81dce14

このソースをAWS公式に載っている手順でzipを作成しLambda関数をDeployする。

Deploy(zip作成手順)

.zip ファイルアーカイブを使用して Go Lambda 関数をデプロイするに書かれている通りにやれば簡単にできる。

1、build-lambda-zip ツールを GitHub からダウンロード

go.exe get -u github.com/aws/aws-lambda-go/cmd/build-lambda-zipを cmd で実行する(初回のみ)。
これでgoのLambdaを作成するためのツールをローカルにダウンロードする。

2、build-lambda-zip ツールで zip を作成

set GOOS=linuxを cmd で実行し環境変数を設定する。
続いて以下のコマンドを順に実行して zip を作成する。

go build -o main main.go
%USERPROFILE%\Go\bin\build-lambda-zip.exe -output main.zip main

zip 作成後は AWS Management console から zip を upload して Deploy をする。

【参考】go build -o main main.goでエラー『go.mod file not found in current directory or any parent directory; see 'go help modules'』

Goのmodule管理の仕組みであるgo.modがない時にbuildすると起きるエラー。
これは以下のコマンドを実行する事で解決できる1

go env -w GO111MODULE=off

上記のコマンドを実行する事で、Go Modulesを無効にしGOPATHモード(go getしたものが$GOPATH/srcに入るがそれを参照する)でbuildできるので、go.modがないというエラーは起きなくなる。

参考:モジュール対応モードへの移行を検討する
参考:Go Modules

【参考】zip 作成時に他の設定ファイルなどを取り込みたい時

以下のように、zip 化する際にその対象のファイルを指定すればよい。

C:\Users\user\go\bin\build-lambda-zip.exe -output main.zip main config.yaml

参考:https://stackoverflow.com/questions/56607738/cannot-read-json-file-after-uploading-go-package-into-aws-lambda

Lambdaを実行してみる

AWS公式からコピペしてきたコードでは以下のようにeventオブジェクトを定義しているので、

type MyEvent struct {
        Name string `json:"name"`
}

以下のようなJSONをLambdaのイベントドキュメントに記載して「テスト」をすると、

{"name": "Hoge"}

以下の画像のように"Hello Hoge!"がLambda関数から返却される。
image.png

SlackからAWS Chatbotを呼び出しLambdaを実行

SlackからAWS Chatbotを呼び出すための設定の仕方はこれが分かりやすいのでそれを参照。

IAMについて

AWS Chatbot専用のアカウントを作成するのに必要なIAM roleは以下。
後で気づいたが別にAWS Chatbotの設定をするユーザに制限をかける必要はない気がする・・・が一応調べたのでおまけ程度に載せておく。

  • chatbot:
    • chatbot:GetSlackOauthParameters
      「チャットクライアントを設定」で「チャットクライアント」をSlackに設定後、「クライアント設定」をクリックしてSlackとの連携のための認証を設定するための権限(これないとSlackとの連携のための認証許可のページまで遷移できない)
    • chatbot:RedeemSlackOauthCode
      SlackとAWS Chatbotとの連携の認証をSlackの画面で「許可」した後にSlackの認証情報をAWS側に償還するための権限(Redeemが償還する・請け出すとかいう意味らしい)
    • chatbot:DescribeSlackWorkspaces
      「Slack チャネルを設定」の「Slack チャネル」でSlackのチャンネルIDを取得するために必要なワークスペースの情報をロードするための権限
    • chatbot:DescribeSlackChannels
      「Slack チャネルを設定」の「Slack チャネル」でSlackのパブリックチャンネルのチャンネルIDを取得するための権限
    • chatbot:CreateSlackChannelConfiguration
      「Slack チャネルを設定」の「設定」ボタンをクリックしてAWSチャットボットにSlackチャネル設定を作成するための権限
    • chatbot:DescribeSlackChannelConfigurations
      AWSアカウントのすべてのAWSチャットボットSlackチャネル設定を一覧表示するための権限
  • iam:
    • iam:CreateRole
      「Slack チャネルを設定」の「アクセス許可」でIAMロールを作成するための権限
    • iam:CreatePolicy
      「Slack チャネルを設定」の「アクセス許可」でIAMロールを作成する時に必要になるポリシーを作成する権限
    • iam:AttachRolePolicy
      「Slack チャネルを設定」の「アクセス許可」でIAMロールにポリシーをアタッチするための権限
    • iam:PassRole
      サービスにロールを渡す許可を付与するための権限(今回だとAWS Chatbotへ権限を付与する)

インラインポリシーとしては以下のような感じになる。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "chatbot:DescribeSlackWorkspaces",
                "chatbot:RedeemSlackOauthCode",
                "chatbot:CreateSlackChannelConfiguration",
                "chatbot:DescribeSlackChannels",
                "chatbot:DescribeSlackChannelConfigurations",
                "chatbot:GetSlackOauthParameters"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "iam:CreatePolicy",
                "iam:PassRole",
                "iam:CreateRole",
                "iam:AttachRolePolicy"
            ],
            "Resource": [
                "arn:aws:iam::XXXXXXXXXX:role/*",
                "arn:aws:iam::XXXXXXXXXX:policy/*"
            ]
        }
    ]
}

Slackからの@awsコマンドでLambdaを実行する

image.png

参考文献

4
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2