Terraform Cloud で Google Cloud プロジェクトを作成する

# Terraform Cloud で Google Cloud プロジェクトを作成する

## はじめに
社内で Google Cloud プロジェクトを新規で用意する場合、現在はプロジェクト作成権限を持ったユーザが手動で行っています。
今回は Terraform Cloud を使ってプロジェクト作成を自動でできるようにしました。

## 構築手順
### Terraform Cloud 環境設定
Terraform Cloud のセットアップをします。
terraform Cloud の Organization はすでに用意されていたものを使うことになっていたので、Workspace の作成から始めます。
今回は CLI-driven workflow を選びます。

![create terraform workspace.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/72e19235-8590-5560-65cb-5992075bbbcb.png)


Workspace 名と紐づくプロジェクトを指定し、「Create workspace」より Workspace を作成します。

![create terraform workspace config.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/5e378b1b-73f0-0ad1-6631-206eb8a863eb.png)


### Terraform CLI のセットアップ
ローカルマシンに Terraform CLI をインストールし、Terraform Cloud に接続できるようにします。

以下URLから CLI 用の Zip ファイルをダウンロードし、任意の場所に展開します。

https://developer.hashicorp.com/terraform/downloads

![install terraform cli.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/8d8733d1-4ed5-a1c3-f49d-e624b9c3e199.png)


展開したパス上でコマンドプロンプトを開き、`terraform login` コマンドを実行します。

![terraform login.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/40c28b14-a8ed-9361-05df-a456a9b459b2.png)


`yes` を入力すると自動的に Terraform Cloud の Token ページが開きます。初めて接続する場合はトークンを新規作成し、トークン文字列をコマンドプロンプトに入力します。

![terraform login token.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/4b6f8816-5897-d208-a224-30695dee8d36.png)

`terraform workspace` コマンドで接続する Workspace を指定できますが、後述のテンプレートの中で記述するためこのコマンドは不要かもしれません。

https://developer.hashicorp.com/terraform/cli/commands/workspace/select

テンプレートを保存するフォルダを作成し、そのフォルダ上でコマンドプロンプトを開き、`terraform init` を実行します。

### Google Cloud サービスアカウントの準備
Terraform で Google Cloud のリソースを作成するには、リソース作成に必要な権限をもつサービスアカウントのキーが必要になります。

サービスアカウントはプロジェクトごとに作成できます。組織に直接紐づくサービスアカウントは作成できません。
下記記事を参考に、任意のプロジェクトでサービスアカウント作成後、`gcloud organizations add-iam-policy-binding` コマンドで2つのロール `roles/resourcemanager.projectCreator` と `roles/billing.user` を付与しました。

https://hatappi.blog/entry/2020/08/22/135238

ロールを付与したサービスアカウントのキーを新規発行します。
今回はキー連携を行っていますが、画像の通り Workload Identity 連携のほうがより安全とのことです。

![service account key.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/5d5b4125-4fc8-d1c7-5905-b3f83011af01.png)


また、サービスアカウントを作成したプロジェクトで Cloud Billing API が有効化されていない場合は有効化します。
プロジェクト作成のプロバイダーに請求先アカウントIDを指定する場合、Cloud Billing API が無効化状態だと以下のエラーが発生します。

```
Error: failed pre-requisites: failed to check permissions on billing account "billingAccounts/<Billing ID>": googleapi: Error 403: Cloud Billing API has not been used in project <Project ID> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudbilling.googleapis.com/overview?project=<Project ID> then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry. Details: [ { "@type": "type.googleapis.com/google.rpc.Help", "links": [ { "description": "Google developers console API activation", "url": "https://console.developers.google.com/apis/api/cloudbilling.googleapis.com/overview?project=<Project ID>" } ] }, { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "domain": "googleapis.com", "metadata": { "consumer": "projects/<Project ID>", "service": "cloudbilling.googleapis.com" }, "reason": "SERVICE_DISABLED" } ] , accessNotConfigured
with google_project.new_project
```

### テンプレートの作成
プロジェクトを作成するテンプレートを作成します。

まず接続先の Workspace と使用するプロバイダーを指定します。

``` terraform.tf
terraform {
  cloud {
    organization = "<Organaization Name>"

    workspaces {
      name = "google-cloud"
    }
  }

  required_providers {
    google = {
      source = "hashicorp/google"
      version = "4.51.0"
    }
  }
}
```

続いて、プロジェクト作成プロバイダーに関するテンプレートを追加します。

https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/google_project

認証に必要な先述でダウンロードしたサービスアカウントのキー文字列とプロジェクト作成プロバイダーの引数となる新規作成するプロジェクトID、プロジェクト名、紐づける組織ID、紐づける請求先アカウント（任意）を追加します。
このうち、サービスアカウントのキー文字列・紐づける組織ID・紐づける請求先アカウントは不変であり、特にキー文字列は平文で持ちたくありません。
なのでこの3つを Terraform Cloud の環境変数として登録しました。

Workspace の Variables より、Terraform variables として作成します。意図せぬところで値が見えないように、Sensitive で作成します。

![terraform variables.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426544/c57e6232-c047-4fa8-c12a-55c808b5f99c.png)


テンプレートでは、`variable "<変数名>" {}` で変数宣言し、変数を使う場合は `${var.<変数名>}` を指定します。

``` main.tf
variable "GOOGLE_CREDENTIALS" {}
variable "ORGNIZATION_ID" {}
variable "BILLING_ACCOUNT" {}

provider "google" {
  credentials = "${var.GOOGLE_CREDENTIALS}"
}

resource "google_project" "new_project" {
  name       = "<Project Name>"
  project_id = "<Project ID>"
  org_id     = "${var.ORGNIZATION_ID}"
  billing_account = "${var.BILLING_ACCOUNT}"
}
```

テンプレート作成は以上です。
わたしはプロバイダー指定部分とリソース作成部分でテンプレートを分けたかったので別ファイルにしましたが、1ファイルに合わせて記述しても問題ないと思います。

### 実行
テンプレートを実行しプロジェクト作成ができるか確認します。

`terraform init` を実行したコマンドプロンプトに戻り、`terraform validate` でテンプレートの構文チェック、`terraform apply` でテンプレートを実行します。
`terraform plan` で作成されるリソースを確認する（いわゆる dry run）こともできます。

## 参考
https://developer.hashicorp.com/terraform/tutorials

以上です。どなたかの参考になれば幸いです。