[HCP Terraform 実践 その1] Terraform Cloud 触ってみた

## これは何?
Terraform Cloud を初めて触った 〜 Apply までの流れをまとめたものになります。

## 0. 事前準備(GitHub リポジトリの作成 & tfファイルのプッシュ
GitHubリポジトリを作成し、.tfファイルをPushするようにします。
今回の演習で使用したリポジトリは[こちら↓](https://github.com/atsw0q0/test-terraform-cloud)です。

https://github.com/atsw0q0/test-terraform-cloud

## 1. Terraform Cloud 初期設定
やることとしては以下の3点が必要となります.

1. Organizations の作成
1. Projects の作成
1. Workspaces の作成


### 1-1. Organizationsの作成
最初にOrganizationsを作成します.
`Create organization`をクリックします.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/a8f44cc2-34e4-fc59-43db-523e06fb9f83.png)


Organizations 名を入力してOrganizationsを作成します. Organizations名はおそらくTerraform Cloud上で一意の名称を指定する必要があります.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/2e12d23a-0f97-d4d3-d3e1-e3e5740598df.png)


### 1-2. Project の作成
次にTerraform Project の作成のため、作成されたOrganization 下でプロジェクトを作成します. 
`+New Project`でプロジェクトを生成してプロジェクト名を指定します.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/6fe21457-e567-b446-c561-add5163007f1.png)

### 1-3. Workspaces の作成
Project 下でWorkspacesを作成します. 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/fbf83a16-2476-98aa-0a71-0362c459ff28.png)

ワークフローの種類を選択できます.今回はリポジトリなどをトリガーとしたVersion Control Workflowを選択します.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/4b197f39-864c-e572-8853-c6cc532e4339.png)

リポジトリを選択できますので、利用されているリポジトリサービスを選択します.
私の場合はGitHubアカウントを作成しているため、Githubリポジトリを選択します.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/8cb63640-f351-6e66-0d56-cd306685802c.png)


これでワークスペースを作成することができました.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/0ac4f2ec-8e27-460d-6099-2a1e55cef0aa.png)

一旦、これでterraform cloud上の作業は完了です。

## 2. IAMロールの作成
今回はOIDC(Open ID Connect)による AWSの認証情報を取得して、一時認証用トークンを生成するようにします。
詳しくは、以下のリンクを参考に。
https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/aws-configuration


### 2-1. OIDCプロバイダーの設定
OIDCのためのIDプロバイダーを設定します。プロバイダー名は`app.terraform.io`でaudienceは`aws.workload.identity`を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/ce198bd5-321c-9af9-5f95-b4fae9daa701.png)

### 2-2. IAMロールの作成
IDプロバイダーに対して権限借用するためのIAMロールを作成します。
IAMロールの信頼関係は以下の通りに設定します。今回はOrganizations下の全プロジェクト・ワークロードであればアクセスを許可できる強い権限をしているため、適宜制限をかけていただければと思います。
IAMポリシーは、`AdministratorAccess`をアタッチします。
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Principal": {
                "Federated": "arn:aws:iam::123456789012:oidc-provider/app.terraform.io"
            },
            "Condition": {
                "StringEquals": {
                    "app.terraform.io:aud": [
                        "aws.workload.identity"
                    ]
                },
                "StringLike": {
                    "app.terraform.io:sub": [
                        "organization:atsuw0w-test-terraform:project:*:workspace:*:run_phase:*"
                    ]
                }
            }
        }
    ]
}
```

### 2-3. 環境変数の定義
IAMロールの作成が完了したら、TerraformCloud上で環境変数の定義を実施します。
作成したWorkspaces へ移動し、**Workspace variables** で以下のような環境変数を設定します。
AWSへの認証および権限借用するIAMロールを明示的に定義します。

| 環境変数| 説明 | 値 |
|---|---|---|
|TFC_AWS_PROVIDER_AUTH | trueの場合、AWSへの認証を行う. |true|
|TFC_AWS_RUN_ROLE_ARN | 権限借用するためのIAMロールArnを指定. |arn:aws:iam::123456789012:role/[IAMロール名]	|


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/4ece9ec5-6266-2a7e-a809-45a81cf4c34a.png)



## 3. リソース作成 テスト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/cfa5cb35-08a6-d234-ab0f-e8414f226127.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/69336ff2-005e-64f9-6d51-8ea33d1b6f8a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/5d3b50ec-458e-4271-7d97-c5b05d9277e8.png)


## 4. 更新
更新する際は、pull request を投げることで自動的に更新することができます。

以下はfeatureブランチ`feature/create-igw`を作成し、インターネットゲートウェイを作成する定義を追記しました。
```hcl:main.tf
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc.id
  tags = {
    Name = format("%s-%s-igw-%s-%02d", var.pj_tags.name, var.pj_tags.env, var.vpc_prefix.prefix, 1)
    PJ   = var.pj_tags.name
    Env  = var.pj_tags.env
  }
}
```
上記の内容を追記し、GitHubにプッシュ後、featureブランチ → mainブランチへプルリクエストを投げることで、Terraform Cloud上のワークフローのRunsでPlanの内容が実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/4cdaf5d2-3ae1-1de9-b527-4cbae98ca555.png)

Planの中身を見てみると、リソース`aws_internet_gateway.igw`を新規作成するような内容が出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/32bb99e1-d501-43a9-0e30-c2bd370a44b5.png)

mainブランチにMergeすると、Terraform Cloud上でもapplyすることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/86a86fc5-b58c-e196-b5ee-f50c32c7aecb.png)


## 終わりに
Terraform のCI/CDパイプラインを自前で作成する必要なく、簡単にterraform を構築することができました。