TerraformでService Accountのprivate keyをFastlyと共有する

つい先日(2019年6月28日)にTerraformのFastly Providerでv0.12のサポート版がリリースされました:tada:
https://github.com/terraform-providers/terraform-provider-fastly/blob/master/CHANGELOG.md#080-june-28-2019

Terraform v0.12からは待望の[jsonencode関数](https://www.terraform.io/docs/configuration/functions/jsondecode.html)が使えるようになっています。
これらを使うことでTerraformでGCPのService Accout KeyとFastly Serviceとをシームレスに連携させることができます。
具体的にみていきましょう。

## `fastly_service_v1` resource

FastlyのログをGCSやBigQueryにexportする場合、`fastly_service_v1`の[gcslogging](https://www.terraform.io/docs/providers/fastly/r/service_v1.html#gcslogging)や[bigquerylogging](https://www.terraform.io/docs/providers/fastly/r/service_v1.html#bigquerylogging)を使用します。
この場合、連携に使用するService Accountの認証情報を`secret_key`というattributeで渡す必要があります。
あるいは環境で`FASTLY_GCS_SECRET_KEY`や`FASTLY_BQ_SECRET_KEY`で指定する必要がありました。

## `google_service_account_key` resource

一方で、Service AccountやそのkeyはGoogle providerで提供されている[google_service_account](https://www.terraform.io/docs/providers/google/r/google_service_account.html), [google_service_account_key](https://www.terraform.io/docs/providers/google/r/google_service_account_key.html) resourceで管理可能です。

前述の`jsondecode`関数を使用することでこれらをシームレスに扱えるようになりました。

## `jsondecode`を使った連携

以下のような`google_service_account_key`があるとします。

```
resource "google_service_account" "fastly-logs" {
  account_id   = "fastly-logs"
  display_name = "Fastly Logs"
}

resource "google_service_account_key" "fastly-key" {
  service_account_id = google_service_account.fastly-logs.name
}
```

例として`gcsloggin`での連携を考えます。
Bucketの生成とService Accountへの権限を付与も以下のように管理できます。

```
resource "google_storage_bucket" "fastly-logs" {
  name     = "my-project-fastly-logs"
  location = "asia-northeast1"
}

resource "google_storage_bucket_iam_member" "fastly-logs-viewer" {
  bucket = google_storage_bucket.fastly-logs.name
  role   = "roles/storage.objectViewer"
  member = "serviceAccount:${google_service_account.fastly-logs.email}"
}

resource "google_storage_bucket_iam_member" "fastly-logs-creator" {
  bucket = google_storage_bucket.fastly-logs.name
  role   = "roles/storage.objectCreator"
  member = "serviceAccount:${google_service_account.fastly-logs.email}"
}
```

そうすると`fastly_service_v1`は以下のように設定できるようになります。

```
resource "fastly_service_v1" "my-service" {
  name        = "my-service"
  ...
  gcslogging {
    name        = "My Service logging"
    email       = google_service_account.fastly-logs.email
    bucket_name = google_storage_bucket.fastly-logs.name
    secret_key  = jsondecode(base64decode(google_service_account_key.fastly-key.private_key)).private_key
    format      = "%h %l %u %t \"%r\" %\u003es %b"
  }
}
```

途中はしょってますが、重要なのは`gcslogging.secret_key`に設定した長文です。
`google_service_account_key.private_key`はbase64エンコードされたJSON文字列がはいっています。
なので、`base64decode`してから`jsondecode`することで必要な`private_key`を取り出して渡しています。
v0.11までは`jsonencode`関数はありましたが、`jsondecode`関数はなく、この連携ができませんでした。

ちなみに以前のFastly providerではこの`secret_key`がplan時に毎回差分が発生し、keyが漏れようになっていたので、`lifecyle.ignore`を使っていたりしましたが、これも不要になりました。

(追記 2019/10/31)
Providerのドキュメントによると

> A typical format for the key is PEM format, containing actual newline characters where required.

https://www.terraform.io/docs/providers/fastly/r/service_v1.html#secret_key

とあるのでちゃんと改行いれると差分でなくなるらしい(自分では未確認)。