AWS Copilot で生成されるタスクロールに任意のポリシーをアタッチする
2021-01-27AWS Copilot で ECS で実行されるアプリケーションを管理する際、タスクロールもよしなに作ってくれます。今回は、そのタスクロールに任意の IAM ポリシーをアタッチしてみます。
目次
概要
AWS Copilot で生成されるタスクロールに、任意の IAM ポリシーをアタッチします。
前回のブログを書いた際に AWS の中の人からリプをもらったので、実際にやってみます。
Thank you 🙏 for the awesome blog post! You can also modify the task role using an Addons template https://t.co/Gvnq8YPw23
— Efe Karakus (@efekarakus) January 23, 2021
サンプルのアプリケーションとしては、 AWS アカウント内の S3 バケット名リストを返すような API を Go で実装してみます。その際に、最近 GA になった SDK for Go v2 も使ってみます。
アプリケーションの実装
まずは、 S3 バケット名のリストを返すような API を実装します。フレームワークとして echo を使って、 AWS SDK は v2 を使います。
labstack/echo: High performance, minimalist Go web framework
package main
import (
"context"
"net/http"
"os"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/labstack/echo/v4"
)
type HelloResponse struct {
Message string `json:"message"`
}
type BucketsResponse struct {
Buckets []string `json:"buckets"`
}
func main() {
e := echo.New()
e.GET("/", hello)
e.GET("/buckets", buckets)
e.Logger.Fatal(e.Start(":1323"))
}
func hello(c echo.Context) error {
return c.JSON(http.StatusOK, HelloResponse{
Message: "Hello ECS!",
})
}
func buckets(c echo.Context) error {
region := os.Getenv("AWS_DEFAULT_REGION")
if region == "" {
c.Echo().Logger.Error("Environment variable AWS_DEFAULT_REGION is undefined.")
return c.JSON(http.StatusInternalServerError, nil)
}
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region))
if err != nil {
c.Echo().Logger.Error("Failed to laod AWS deault config.", err.Error())
return c.JSON(http.StatusInternalServerError, nil)
}
s3client := s3.NewFromConfig(cfg)
out, err := s3client.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
if err != nil {
c.Echo().Logger.Error("Failed to list buckets.", err.Error())
return c.JSON(http.StatusInternalServerError, nil)
}
var buckets []string
for _, b := range out.Buckets {
buckets = append(buckets, aws.ToString(b.Name))
}
return c.JSON(http.StatusOK, BucketsResponse{
Buckets: buckets,
})
}
エンドポイントは 2 つ用意しています。
GET /
:{"message":"Hello ECS!"}
GET /buckets
:{"buckets":["bucket1",...,"bucket999"]}
SDK for Go v2 の話を少し書いておくと、v2 では各クライアントの生成部分とメソッド実行時の引数 (第1引数に context を受け取るようになった) が変わっています。その他、パッケージの構成やメソッドについても細かい変更があるようです。
例えば *string
を string
に変換する際、v1 では aws.StringValue()
を使っていましたが、 v2 では aws.ToString()
を使うようになっています。
Copilot にデプロイする際の Dockerfile は下記内容で準備します。
FROM golang:1.15.5-alpine3.12 as build
ENV GOPATH=
ADD go.mod go.sum ./
RUN go mod download
ADD . .
RUN go build -o /main
ENTRYPOINT [ "/main" ]
Copilot でアプリのセットアップ
manifest.yml を作成
copilot init
コマンドで manifest.yml
を作成します。前回と違って今回はワークロードに Load Balanced Web Service を選択します。また、 Port にはコンテナ側で待ち受けるポート番号を指定します。今回であれば 1323
で echo のサーバーを起動しているので 1323
を指定します。
$ copilot init
...
Use existing application: No
Application name: list-s3-buckets
Workload type: Load Balanced Web Service
Service name: list-s3-buckets-app
Dockerfile: ./Dockerfile
no EXPOSE statements in Dockerfile ./Dockerfile
Port: 1323
...
この時点で下記のようなディレクトリ構成になっています。
.
├── Dockerfile
├── copilot
│ └── list-s3-buckets-app
│ └── manifest.yml
├── go.mod
├── go.sum
└── main.go
任意の IAM ポリシーを追加
今回のアプリケーションでは、 S3 のバケット一覧を取得する権限が必要になります。 IAM のアクション名でいうと s3:ListAllMyBuckets
です。このアクションを許可する IAM ポリシーを作成して、 Copilot によって生成されるタスクロールにアタッチします。
そのために、 copilot/list-s3-buckets-app
配下に addons
ディレクトリを作成し、その中に CloudFormation のテンプレートファイルを作成します。今回であれば s3-list-bucket-policy.yml
です。
.
├── Dockerfile
├── README.md
├── copilot
│ └── list-s3-buckets-app
│ ├── addons
│ │ └── s3-list-bucket-policy.yml
│ └── manifest.yml
├── go.mod
├── go.sum
└── main.go
テンプレートファイルの内容は下記の通りです。
Parameters:
App:
Type: String
Description: Your application's name.
Env:
Type: String
Description: The environment name for the service.
Name:
Type: String
Description: The name of the service.
Resources:
ListBucketPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: ListBucketActions
Effect: Allow
Action:
- s3:ListAllMyBuckets
Resource: "*"
Outputs:
ListBucketPolicyArn:
Description: "The ARN of the ManagedPolicy to attatch to the task role."
Value: !Ref ListBucketPolicy
CFn テンプレートを作成するうえで注意したいのは下記の 2 点です
Parameters
としてApp
,Env
,Name
を定義する- 定義したリソースの ARN を
Outputs
で出力する
その他、追加のリソースの定義については下記のドキュメントを参照してください。
Additional AWS Resources - AWS Copilot CLI
デプロイ
test
環境を作ってデプロイします。
$ copilot env init --name test --profile default --default-config
$ copilot deploy --env test
前回の Job の場合と違って、 Service のほうがデプロイに時間がかかる印象です。(10分弱)
確認
デプロイされたアプリケーションの URL はデプロイ時にも出力されますが、再度確認するためには copilot svc show
コマンドを実行します。
$ copilot svc show
Only found one service, defaulting to: list-s3-buckets-app
About
Application list-s3-buckets
Name list-s3-buckets-app
Type Load Balanced Web Service
Configurations
Environment Tasks CPU (vCPU) Memory (MiB) Port
----------- ----- ---------- ------------ ----
test 1 0.25 512 1323
Routes
Environment URL
----------- ---
test http://list-Publi-1JMT8L0BFYS47-390312034.ap-northeast-1.elb.amazonaws.com
Service Discovery
Environment Namespace
----------- ---------
test list-s3-buckets-app.list-s3-buckets.local:1323
Variables
Name Container Environment Value
---- --------- ----------- -----
COPILOT_APPLICATION_NAME list-s3-buckets-app test list-s3-buckets
COPILOT_ENVIRONMENT_NAME " " test
COPILOT_LB_DNS " " list-Publi-1JMT8L0BFYS47-390312034.ap-northeast-1.elb.amazonaws.com
COPILOT_SERVICE_DISCOVERY_ENDPOINT " " list-s3-buckets.local
COPILOT_SERVICE_NAME " " list-s3-buckets-app
httpie で確認してみます。
$ http http://list-Publi-1JMT8L0BFYS47-390312034.ap-northeast-1.elb.amazonaws.com
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 25
Content-Type: application/json; charset=UTF-8
Date: Tue, 26 Jan 2021 14:21:40 GMT
{
"message": "Hello ECS!"
}
$ http http://list-Publi-1JMT8L0BFYS47-390312034.ap-northeast-1.elb.amazonaws.com/buckets
HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json; charset=UTF-8
Date: Tue, 26 Jan 2021 14:28:33 GMT
Transfer-Encoding: chunked
{
"buckets": [
"bucket_00001",
...
"bucket_99999"
]
}
CLI で http リクエストするなら HTTPie が便利 - michimani.net
まとめ
AWS Copilot で ECS で実行されるアプリケーションをデプロイする際に、作成されるタスクロールに任意の IAM ポリシーをアタッチしてみた話でした。
これどうするんかなーと思っていたところで解決案をもらったわけですが、めちゃくちゃ簡単に任意のポリシーをアタッチできました。まあ、ドキュメントにしっかりと書いてあったんですが。もし同じ内容でお困りの方がいたら参考にしてみてください。
今回のコードは GitHub に置いています。
hello-ecs/list-s3-buckets at master · michimani/hello-ecs
comments powered by Disqus