かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

別途作成しておいた IAM Role、S3 Bucket を複数の Serverless Framework のプロジェクトから利用できるのか?

概要

記事一覧はこちらです。

Servlerless Framework で作成したプロジェクトで deploy すると python-first-lambda-dev-ap-northeast-1-lambdaRole という IAM Role と python-first-lambda-dev-serverlessdeploymentbucke-7j3614vgkvv3 という S3 Bucket が作成されました。

デフォルトではプロジェクト毎に IAM Role、S3 Bucket が作成されるようですが、別途作成しておいた IAM Roke、S3 Bucket を複数のプロジェクトから利用することができるのか確認してみます。

参照したサイト・書籍

  1. Serverless Framework: Reusing S3 bucket for multiple projects deploy
    https://medium.com/@oieduardorabelo/reusing-s3-bucket-for-multiple-serverless-framework-projects-deploy-828e3a45f713

  2. Custom IAM Roles
    https://www.serverless.com/framework/docs/providers/aws/guide/iam/#custom-iam-roles

目次

  1. delploy した時の IAM Role はどのような設定か?
  2. delploy した時の S3 Bucket には何がアップロードされているのか?
  3. share-s3bucket-with-multi-servces プロジェクトを作成する
  4. Terraform で ksbysample-serverless-lambdaRole、ksbysample-serverless-deploymentbucket を作成する
  5. Serverless Framework のサブプロジェクトを2つ作成する
  6. deploy してみる
  7. remove してみる

手順

delploy した時の IAM Role はどのような設定か?

python-first-lambda-dev-ap-northeast-1-lambdaRole には python-first-lambda-dev-lambda という名前のインラインポリシーがアタッチされていて、以下の内容でした。

f:id:ksby:20200524130344p:plain

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogStream",
        "logs:CreateLogGroup"
      ],
      "Resource": [
        "arn:aws:logs:ap-northeast-1:446693287859:log-group:/aws/lambda/python-first-lambda-dev*:*"
      ],
      "Effect": "Allow"
    },
    {
      "Action": [
        "logs:PutLogEvents"
      ],
      "Resource": [
        "arn:aws:logs:ap-northeast-1:446693287859:log-group:/aws/lambda/python-first-lambda-dev*:*:*"
      ],
      "Effect": "Allow"
    }
  ]
}

また信頼関係で以下のポリシーが設定されています。

f:id:ksby:20200524130440p:plain

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

delploy した時の S3 Bucket には何がアップロードされているのか?

f:id:ksby:20200524130838p:plain

serverless/python-first-lambda/dev/1590287550668-2020-05-24T02:32:30.668Z の下に以下のファイルがアップロードされています。

  • compiled-cloudformation-template.json
  • python-first-lambda.zip

プロジェクト名がパスの途中に入っているので、複数のプロジェクトで利用しても問題は出ないと思われます。

share-s3bucket-with-multi-servces プロジェクトを作成する

以下の手順で share-s3bucket-with-multi-servces プロジェクトを作成します。具体的な手順は IntelliJ IDEA+Node.js+npm+serverless framework+Python の組み合わせで開発環境を構築して AWS Lambda を作成してみる 参照。

  • share-s3bucket-with-multi-servces の Empty Project を作成する。
  • Python の仮想環境を作成する。
  • Serverless Framework をローカルインストールする。
  • .envrc を作成する。

Terraform で ksbysample-serverless-lambdaRole、ksbysample-serverless-deploymentbucket を作成する

Serverless Framework でも IAM Role、S3 Bucket を作成できるようなのですが、Terraform を使うことにします(個人的な好みで深い理由はありません)。

Terraform の実行環境は tfenv+aws-vault+direnv を組み合わせて Windows 上に Terraform の実行環境を構築する の手順で構築しています。

terraform は最新の 0.12.25 を使用します。

f:id:ksby:20200524172528p:plain

プロジェクトのルートディレクトリの下に .terraform-version を作成し、その中に 0.12.25 と記述します。

プロジェクトのルートディレクトリの下に terraform/shared-resources ディレクトリを作成し、その下に main.cf を作成して以下の内容を記述します。

  • IAM Role 名は ksbysample-serverless-lambdaRole
  • IAM Role の Policy で指定する CloudWatch ロググループは /aws/lambda/* で指定します。
  • S3 Bucket 名は ksbysample-serverless-deploymentbucket
provider "aws" {
  region = "ap-northeast-1"
}

///////////////////////////////////////////////////////////////////////////////
// IAM Role
//
data "aws_iam_policy_document" "assume_role_lambda" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["lambda.amazonaws.com"]
    }
  }
}
resource "aws_iam_role" "lambda_role" {
  name               = "ksbysample-serverless-lambdaRole"
  assume_role_policy = data.aws_iam_policy_document.assume_role_lambda.json
}
data "aws_iam_policy_document" "lambda_policy" {
  statement {
    effect = "Allow"
    actions = [
      "logs:CreateLogStream",
      "logs:CreateLogGroup",
      "logs:PutLogEvents"
    ]
    resources = ["arn:aws:logs:ap-northeast-1:*:log-group:/aws/lambda/*:*"]
  }
}
resource "aws_iam_role_policy" "lambda_policy" {
  name   = "lambda_policy"
  role   = aws_iam_role.lambda_role.id
  policy = data.aws_iam_policy_document.lambda_policy.json
}

///////////////////////////////////////////////////////////////////////////////
// S3 Bucket
//
resource "aws_s3_bucket" "serverless_deployment_bucket" {
  bucket        = "ksbysample-serverless-deploymentbucket"
  force_destroy = true
}
resource "aws_s3_bucket_public_access_block" "serverless_deployment_bucket" {
  bucket = aws_s3_bucket.serverless_deployment_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

以下のコマンドを実行して IAM Role、S3 Bucket を作成します。

  • tf init
  • tf plan(ここのキャプチャは省略)
  • tf apply

f:id:ksby:20200524183507p:plain f:id:ksby:20200524183729p:plain f:id:ksby:20200524183828p:plain f:id:ksby:20200524183920p:plain

IAM Role は serverless.yml に指定する時に ARN が必要になるので画面で確認します。

f:id:ksby:20200524191841p:plain

また .gitignore に以下の設定を追加します。

..........

# Ignore terraform
.terraform/
terraform.tfstate*
terraform.tfvars

Serverless Framework のサブプロジェクトを2つ作成する

プロジェクトのルートディレクトリの下に services ディレクトリを作成し、その下に service-a、service-b サブプロジェクトを作成します。

まずは service-a から。npx sls create --template aws-python3 --path service-a を実行します。

f:id:ksby:20200524190026p:plain

services/service-a/serverless.yml を以下のように変更します(コメントの部分は取り除いています)。

service: service-a

provider:
  name: aws
  runtime: python3.8

  stage: dev
  region: ap-northeast-1

  role: arn:aws:iam::446693287859:role/ksbysample-serverless-lambdaRole
  deploymentBucket:
    name: "ksbysample-serverless-deploymentbucket"

functions:
  hello:
    handler: handler.hello
  • IAM Role は provider - role で指定します。
  • S3 Bucket は provider - deploymentBucket - name で指定します。

次に service-b です。npx sls create --template aws-python3 --path service-b を実行します。

f:id:ksby:20200524193027p:plain

services/service-b/serverless.yml を以下のように変更します(コメントの部分は取り除いています)。

service: service-b

provider:
  name: aws
  runtime: python3.8

  stage: dev
  region: ap-northeast-1

  role: arn:aws:iam::446693287859:role/ksbysample-serverless-lambdaRole
  deploymentBucket:
    name: "ksbysample-serverless-deploymentbucket"

functions:
  hello:
    handler: handler.hello

deploy してみる

まずは service-a から deploy します。service-a のディレクトリに移動してから aws-vault exec $AWS_PROFILE -- bash -c "npx sls deploy -v" を実行します。

f:id:ksby:20200525233012p:plain

以前は表示されていた以下のメッセージは表示されなくなりました。

  • CREATE_IN_PROGRESS - AWS::S3::Bucket
  • CREATE_IN_PROGRESS - AWS::IAM::Role

AWS マネジメントコンソールで確認すると service-a-dev-hello が作成されており実行ロールに ksbysample-serverless-lambdaRole がセットされています。

f:id:ksby:20200525234328p:plain

次に service-b を deploy します。service-b のディレクトリに移動してから aws-vault exec $AWS_PROFILE -- bash -c "npx sls deploy -v" を実行します。

f:id:ksby:20200525233930p:plain

こちらも AWS::S3::BucketAWS::IAM::Role の CREATE_IN_PROGRESS は表示されません。

AWS マネジメントコンソールで確認すると service-b-dev-hello が作成されており実行ロールに ksbysample-serverless-lambdaRole がセットされています。

f:id:ksby:20200525234408p:plain

ksbysample-serverless-deploymentbucket 見ると service-a、service-b の compiled-cloudformation-template.json、zip ファイルがアップロードされていました。

f:id:ksby:20200525234504p:plain

service-a、service-b それぞれで aws-vault exec $AWS_PROFILE -- bash -c "npx sls invoke -f hello" を実行すると結果が返ってきます。

f:id:ksby:20200525235117p:plain

プロジェクト毎に IAM Role、S3 Bucket は作成されず Terraform で作成したものが利用されていました。

remove してみる

service-a、service-b で aws-vault exec $AWS_PROFILE -- bash -c "npx sls remove -v" を実行します。

f:id:ksby:20200525235824p:plain

どちらも IAM Role、S3 Bucket の DELETE_IN_PROGRESS は表示されませんでした。

AWS マネジメントコンソールで確認すると ksbysample-serverless-lambdaRole、ksbysample-serverless-deploymentbucket のどちらも残っています。

f:id:ksby:20200526000024p:plain f:id:ksby:20200526000225p:plain

作成した IAM Role と S3 Buckettf destroy を実行して削除します。

履歴

2020/05/26
初版発行。