📌

GCPのIAMをTerraformとCIツールを使用して扱う時につらみなこと3選

2021/12/25に公開

皆様クリスマスはいかがお過ごしでしょうか。私は今記事を書いています。最高の年末を過ごしています。最高です。

はじめに

Terraform

TerraformとCIツールを組み合わせると、コンソールポチって事故らずに、コードを書いて、レビューしてもらってマージしたら勝手にリソースが作られて便利ですよね。

ただ、上記の技術でGCPのIAM周りを扱っていた時に何回かハマったので、
解決策は書いておらず投げやりな感じになってますが、こういうことがあるよっていうことをお知らせして犠牲者を減らすため、
今回はそのことを記事にしようかなという思いです。

自分はGitHub Actionsしか使ったことがないので、
以下ではGitHub actionsを扱っていることとしますが、
他のCIツールでも同様に言えることだとは思っていますのでタイトルはCIツールに広げました。

GCP

対象読者

GCPとTerraformとCIツールを使用してインフラを管理している人たちで、やり始めて間もない人たちとか、ちょっとだけやってる人たち。

1.カスタムロールの作成や追記が面倒でつらみ

GitHub ActionsなどCIツールにTerraformの実行、もっというとGCPのリソースの適用をさせる場合はサービスアカウントを使用する必要があります。

そのサービスアカウントには各種適用したいリソースまわりの権限が必要です。

オーナー権限等、強い権限をつければ全く起こらないんですが、鍵が漏えいした時などに大変なことになりそうなので基本的にはやめておきたいと思うので、カスタムロールを使うことになるかなと思います。

こんな感じ

iam_custom_role.tf
resource "google_project_iam_custom_role" "github_actions" {
  # ... 省略 ...
  permissions = [
    # Cloud Storage
    "storage.objects.create",
    "storage.objects.delete",
    "storage.objects.get",
    "storage.objects.list",
    "storage.buckets.get",
    ...
    ]

https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam_custom_role

上記のように、カスタムロールを作成して1つでGitHub ActionsのIAMを管理した場合、GCPのIAMの調べ方がややこしいなと思ってます。

https://cloud.google.com/iam/docs/understanding-roles

上記に全てのIAMが載っているように見えるんですが、例えばCloud Runの管理者の場合、

recommender.locations.*
resourcemanager.projects.get
resourcemanager.projects.list
run.*

と記述されているんですよね。
これの何が問題かというと、Terraformではアスタリスクを使用してIAMの付与ができません。
そのため、カスタムロールを使う場合はこの情報だけでは追加できません。

自分はGitHub ActionsをIAMをカスタムロールで管理しているので、この場合、以下のように検索しています。
1
手順1
2
手順2
3
手順3
4
実際にここからIAMを追加するわけではないので、変更はせず破棄してください。
手順4

もっといい方法あれば教えてください(投げやり)

代替案

https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam

(サービスアカウントへのIAM付与は、基本的に自分はgoogle_project_iam_memberを使用しています。bindingだと上書きされる?みたいな感じだったので。)

iam.tf
resource "google_project_iam_member" "github_actions_cloud_run" {
  role    = "roles/run.admin"
  member  = "serviceAccounts:[SERVICE_ACCOUNT_EMAIL]"
}

上記を各リソースごとにサービスアカウントに付与する、ということが考えられます。(一気に複数のロール付与できるようにしたい・・・)

書いてて、こっちの方が楽なんじゃないかとは思ってきました。
やったことはないですが、どちらでも良いとは思います。

2.実行アカウントにIAM付け忘れるとplanは通るけどapplyは落ちてつらみ

あるあるですね。

1で示したように、手動で毎回新規リソースごとにIAM追加という形で管理していると、たまに権限を付け忘れることがあります。

そして、今までそのプロジェクトで追加したことのない新規リソースを作成する際はRead権限は不要なのでterraform planをした時には落ちないんですが、terraform applyでリソースを作成しようとした時に落ちます。

こんなやつ

failed to create instance cloud_run_my_app: googleapi: Error 403: The client is not authorized to make this request., notAuthorized

apply段階で権限がないと言われます。

これだけならまだマシなんですが、1度tfstateに新規リソースに関することが書き込まれてしまった場合、
今度はterraform planでもそのリソースのRead権限が必要になって、落ちてしまう、ということが発生します。
こうなると手動で権限だけapplyするか、コンソール上を操作するしかないです。

ざっくり理由)
terraform planはあくまでtfファイルの構文上のチェック等を行ってくれるのみなので、各プラットフォーム上のリソース適用として適切かどうかまでは見てくれません。そのため、planは通るけどapplyで落ちる、みたいなことが発生します。

補足)
自分も使ったことはなく、上記のIAMは問題は解決するか不明ですが、tflintである程度planが通ってapplyが落ちるというのは防げそうです。

https://github.com/terraform-linters/tflint

3.権限付与と実行を同時に行うと落ちてつらみ

上の1、2、の問題を乗り越え、いよいよ適用だ!と思ってapplyしても、また落ちた・・・
こんな経験はないですか?あるでしょう。

GCPのIAMは
https://cloud.google.com/iam/docs/granting-changing-revoking-access#single-role

この辺にも書いている通り、有効になるまでタイムラグがあります。
Terraformで同時にリソースを適用してしまうと、Terraform上ではIAMの付与が完了しても、GCPではまだ有効になっていないので、同時に実行されているリソースの適用で落ちます。

これ最初気づかないとIAM付けたのに落ちて、原因分からずハマりませんか?(ハマります)

なので、落ちた後に、applyをもう1度回してあげると、通ります。(大体すぐやっても通りますが、通らない場合は1、2分空けてからやるのが良いと思います)

おわりに

読んでいただいてありがとうございました。
自分はまだまだインフラに詳しくないのでこれからって感じですが、
もっとこうした方がいいというご指摘や、これはどうなのかというご質問があればぶん投げてください。

おわり

Discussion