【AWS lambda】Terraformでlambda関数を作成してみよう【Terraform】

# Terraform で AWS Lambda Function を作成してみよう

Terraform で AWS Lambda 関数(Hello,Lambda!)を 一番簡単な構成で作成してみます

## バージョン

試してみたバージョンは以下の通りです

| Name      | Version |
| --------- | ------- |
| terraform | 1.1.5   |
| aws       | 4.0     |

## 構築リソース

- lambda function
- IAM role

IAMロールはlambdaがAWSリソースに変更を与えるために必要になります
今回はHello,Lambdaを表示するだけなのでほぼ何も権限を付与してません

## 手順

### 1. IAMロールを定義

IAMロール作成は`Module`を使います

IAMロールをterraformで作成するには、
`aws_iam_role`, `aws_iam_policy`, `aws_iam_role_policy_attachment`
の3つを定義する必要があって面倒です
これらをmoduleとしてまとめたものを利用すれば、必要な変数を定義するだけで一式作成できます

[Terraform Registry / iam](https://registry.terraform.io/modules/terraform-aws-modules/iam/aws/latest)
↑のiam-assumable-roleを参考にして作成します

```s:../modules/aws/iam/iam_role.tf
resource "aws_iam_role" "this" {
  name = var.role_name
  description = var.role_description
  assume_role_policy = data.aws_iam_policy_document.this.json
}

data "aws_iam_policy_document" "this" {
  statement {
    effect = "Allow"
    actions = ["sts:AssumeRole"]

    principals {
      type = "Service"
      identifiers = var.trusted_role_services
    }
  }
}

resource "aws_iam_policy" "this" {
  count = length(var.policy_names)
  name = element(var.policy_names, count.index)
  policy = file(element("${var.policy_json_files}", count.index))
}

resource "aws_iam_role_policy_attachment" "this" {
  count = length(var.policy_names)
  role = aws_iam_role.this.name
  policy_arn = aws_iam_policy.this[count.index].arn
}
```

module定義したら、これをimportします

```s:tf
module "lambda_role" {
  source = "../modules/aws/iam/iam_role"

  role_name = "LambdaServiceRole"
  role_description = "service role for lambda."

  trusted_role_services = [
    "lambda.amazonaws.com"
  ]

  policy_names = [
    "LambdaBasePolicy"
  ]

  policy_json_files = [
    "./policy_json_files/lambda_base_policy.json"
  ]
}
```

policyのjsonファイルは↓の通りです

```json:files/lambda_base_policy.json
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Effect": "Allow",
          "Action": "logs:CreateLogGroup",
          "Resource": "*"
      },
      {
          "Effect": "Allow",
          "Action": [
              "logs:CreateLogStream",
              "logs:PutLogEvents"
          ],
          "Resource": [
              "*"
          ]
      }
  ]
}
```

ここまで作ったら apply します

```shell
$ terraform init
$ terraform plan
$ terraform apply
```

### 2. lambda function を定義

lambdaは↓の通りで定義します

```s:lambda.tf
resource "aws_lambda_function" "lambda_function01" {
  function_name = "function01"
  role = module.lambda_role.arn
  
  filename = "./files/function.zip"
  handler = "function.lambda_handler"
  source_code_hash = filebase64sha256("./files/function.zip")
  runtime = "python3.9"
}
```

このPCにあるファイルを参照して構築する方法です
S3バケットから読み込むほうが実務的でしょうか

- filename : ローカルPC内のファイルパスを指定します
- handler : handlerを指定します
- source_code_hash : `filebase64sha256()`によってハッシュ化した値を入れることができます
- runtime : 今回はpython3.9を選択しました

### 3. ファイル用意

ソースコードを用意します

```shell
$ mkdir files
$ touch files/function.py
```

```py
import json

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
```

zip圧縮します

```shell
$ zip files/function.zip files/function.py
```

### 4. 関数作成

```
$ terraform plan
$ terraform apply
```

で関数が無事作成されたらOK

## この後について

IAMロールには最小の権限しか付与していないため、
コードによって付与する権限を追加していく必要があるかと思います

とりあえずterraformでlambdaを作る経験値をためるための記事でした～