はじめに
CICDの一環でGoのLambdaをSlackから呼び出す仕組みを構築したのでその備忘録を残す。
(Goは初見だったので少しGoを触った所も書き残した。)
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
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
実行結果は以下のようになる。
CIでGoを動かすのに使ったのはこれ。
# Execute Go code
go run .
Hello, World!
hello world②(他のパッケージを呼び出す)
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: ®ion,
})
}
のようにAWSのSDKを使いセッションを作る時、Config
のRegion
は*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 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
Lambdaを実行してみる
AWS公式からコピペしてきたコードでは以下のようにeventオブジェクトを定義しているので、
type MyEvent struct {
Name string `json:"name"`
}
以下のようなJSONをLambdaのイベントドキュメントに記載して「テスト」をすると、
{"name": "Hoge"}
以下の画像のように"Hello Hoge!"
がLambda関数から返却される。
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を実行する
参考文献
-
https://stackoverflow.com/questions/66894200/go-go-mod-file-not-found-in-current-directory-or-any-parent-directory-see-go
Goのmodule管理の仕組みであるgo.mod
がない時にbuildすると起きるエラー。
これは以下のコマンドを実行する事で解決できる1。 ↩