Terraform での Fastly ログ設定の GCP 向け認証情報設定のワークアラウンド

# はじめに

Terraform の Fastly Provider を用いて Fastly の設定をし、 logging を GCS もしくは BigQuery に設定するときは、 GCP の JSON 鍵のうち、 `private_key` の PEM を設定する必要があります。


下記サンプルの `private_key` を環境変数へ設定する必要があるのですが、 改行が `¥n` のエスケープシーケンスで表現されたものになっています。

```json
{
  "type": "service_account",
  "project_id": "project-id",
  "private_key_id": "some_number",
  "private_key": "-----BEGIN PRIVATE KEY-----\n....=\n-----END PRIVATE KEY-----\n",
  "client_email": "<api-name>api@project-id.iam.gserviceaccount.com",
  "client_id": "...",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/...<api-name>api%40project-id.iam.gserviceaccount.com"
}
```

これをそのまま `FASTLY_GCS_SECRET_KEY` もしくは `FASTLY_BQ_SECRET_KEY` に設定しても terraform の設定差分がでます。 provider plugin のドキュメントをよく読むと[^1]改行文字を含んだ形で環境変数に設定する必要があったのですが、設定していなかったため `terraform plan` や `terraform apply` の度に差分が出てしまっていました。


以下は `gcslogging` を利用した時の `terraform plan` 時の出力例です。変更前の `secret_key` が出力されるのもあまりよろしく有りません。

```shell-session
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  ~ fastly_service_v1.someservice
      gcslogging.1121940307.bucket_name:        "<bukcetname>" => ""
      gcslogging.1121940307.email:              "<api-name>api@project-id.iam.gserviceaccount.com" => ""
      gcslogging.1121940307.format:             "<logging jsonformat>" => ""
      gcslogging.1121940307.gzip_level:         "0" => "0"
      gcslogging.1121940307.message_type:       "blank" => ""
      gcslogging.1121940307.name:               "GCS export" => ""
      gcslogging.1121940307.path:               "<path>" => ""
      gcslogging.1121940307.period:             "3600" => "0"
      gcslogging.1121940307.placement:          "" => ""
      gcslogging.1121940307.response_condition: "" => ""
      gcslogging.1121940307.secret_key:         "-----BEGIN PRIVATE KEY-----\n....=\n-----END PRIVATE KEY-----\n" => ""
      gcslogging.1121940307.timestamp_format:   "%Y-%m-%dT%H:%M:%S.000" => ""
      gcslogging.4265669124.bucket_name:        "" => "<bukcetname>"
      gcslogging.4265669124.email:              "" => "<api-name>api@project-id.iam.gserviceaccount.com"
      gcslogging.4265669124.format:             "" => "<logging jsonformat>"
      gcslogging.4265669124.gzip_level:         "" => "0"
      gcslogging.4265669124.message_type:       "" => "blank"
      gcslogging.4265669124.name:               "" => "GCS export"
      gcslogging.4265669124.path:               "" => "<path>"
      gcslogging.4265669124.period:             "" => "3600"
      gcslogging.4265669124.placement:          "" => ""
      gcslogging.4265669124.response_condition: "" => ""
      gcslogging.4265669124.secret_key:         <sensitive> => <sensitive> (attribute changed)
      gcslogging.4265669124.timestamp_format:   "" => "%Y-%m-%dT%H:%M:%S.000"
```

CircleCI 上で terraform docker 公式イメージ上を実行していたのですが、 CircleCI は改行入り環境変数を設定できないためなにか考える必要がありました。


# ワークアラウンド設定方法

本記事での terraform バージョンは以下で、公式 docker イメージを利用してます。CircleCIでの実行を想定したものと思ってください。 Github Actions では、 Secrets に改行文字が入れられるみたいなので、そちらのほうが良いかもしれません。そのため、何かしらの方法で改行文字を動的に展開して環境変数を設定します。

```
Terraform v0.12.7
+ provider.fastly v0.9.0
```


## 改行入 PEM を Base64 でエンコードして、CI 中でデコードして環境変数を設定する

CircleCI のドキュメント[^2]にあるとおりに改行入 PEM を BASE64 でエンコードして展開する方法があります。

### linux 

```shell-session
$ base64 --wrap=0 -----BEGIN PRIVATE KEY-----\n....=\n-----END PRIVATE KEY-----\n
```

### mac

```
$ base64 -----BEGIN PRIVATE KEY-----\n....=\n-----END PRIVATE KEY-----\n
```

出力された BASE64 エンコード結果を `FASTLY_GCS_SECRET_KEY` もしくは `FASTLY_BQ_SECRET_KEY` に設定します。

その上で terraform 実行前に環境変数設定します。

```shell-session
$ export FASTLY_GCS_SECRET_KEY=$(base64 --decode $FASTLY_GCS_SECRET_KEY)
$ terraform plan
```


## 改行文字を動的に展開して環境変数を設定する

terraform 実行の直前に echo で展開した環境変数を上書き設定する方法です。

```shell-session
$ export FASTLY_GCS_SECRET_KEY=$(echo -e $FASTLY_GCS_SECRET_KEY)
$ terraform plan
```

こちらのほうが手数が少ないので簡単かと思います。


[^1]: [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)
[^2]: https://circleci.com/docs/2.0/env-vars/#encoding-multi-line-environment-variables