概要
IAPを経由した、CloudRunへの通信を行う場合、service-[PROJECT-NUMBER]@gcp-sa-iap.iam.gserviceaccount.com
というサービスアカウントに対して、roles/run.invoker
というロールを付与する必要があります。
今回、backend service
をTerraformで作成時にIAPを有効化した場合に、service-[PROJECT-NUMBER]@gcp-sa-iap.iam.gserviceaccount.com
のサービスアカウントが作られず、ロールの付与がそもそもできないという事象が発生しました。そこで、その事象の再現と回避方法をご紹介します。
上記SAへの権限付与の必要性については公式ドキュメントをご参照ください。
事象の再現
まずは事象の再現方法を紹介します。プロジェクトに対応するservice-[PROJECT-NUMBER]@gcp-sa-iap.iam.gserviceaccount.com
がまだ有効となっていないことが前提となります。
Terraform定義
まずは、事象が発生したTerraform定義のサンプルをご紹介します。以下はbackend service
を含めたCloudRunフォワーディングするLB全体のTerraform定義のサンプルです。LB以外のリソースは省略しています。
resource "google_compute_region_network_endpoint_group" "sample_neg" {
name = "sample_neg"
network_endpoint_type = "SERVERLESS"
region = "asia-northeast1"
cloud_run {
service = "sample-cloud-run-service"
}
}
resource "google_compute_ssl_policy" "sample_ssl_policy" {
name = "min-tls-1-2"
profile = "MODERN"
min_tls_version = "TLS_1_2"
}
resource "google_compute_backend_service" "sample_backend_service" {
name = "sample_backend_servie"
load_balancing_scheme = "EXTERNAL_MANAGED"
protocol = "HTTPS"
backend {
balancing_mode = "UTILIZATION"
group = google_compute_region_network_endpoint_group.sample_neg.self_link
}
iap {
enabled = true # ※ここでIAPをONに指定しています※
oauth2_client_id = "Oauth2のClientID"
oauth2_client_secret = "Oauth2のSecret"
}
}
resource "google_compute_url_map" "sample_url_map" {
name = "sample-url-map"
default_service = google_compute_backend_service.sample_backend_service.self_link
}
resource "google_compute_managed_ssl_certificate" "sample_ssl_certificate" {
name = "sample-ssl-certificate"
managed {
domains = ["ドメイン名"]
}
}
resource "google_compute_target_https_proxy" "sample_target_https_proxy" {
name = "sample-target-https-proxy"
url_map = google_compute_url_map.sample_url_map.self_link
ssl_certificates = [google_compute_managed_ssl_certificate.sample_ssl_certificate.self_link]
ssl_policy = google_compute_ssl_policy.sample_ssl_policy.name
}
resource "google_compute_global_address" "sample_global_address" {
name = "sample-global-address"
address_type = "EXTERNAL"
}
resource "google_compute_global_forwarding_rule" "sample_forwarding_rule" {
name = "sample-forwarding-rule"
target = google_compute_target_https_proxy.sample_target_https_proxy.self_link
port_range = "443"
ip_address = google_compute_global_address.sample_global_address.address
load_balancing_scheme = "EXTERNAL_MANAGED"
}
GCPコンソールからIAPの様子を確認
Terraformにてリソース作成後、コンソールを確認すると作成したbackend service
に紐づくIAPが有効になっていることがわかります。
対象のCloudRunにロールを付与
次に、IAPを経由した、CloudRunへの通信を行う場合、service-[PROJECT-NUMBER]@gcp-sa-iap.iam.gserviceaccount.com
というサービスアカウントに対して、roles/run.invoker
というロールを付与する必要があるので、コンソールから権限を付与してみます。すると、以下のようにアカウントが有効でないというエラーとなりました。
回避方法
回避方法は単純で、GCPのコンソール画面でどれか適当なbackend service
に紐づくIAPを選択し、有効化設定を一時的にOFFにしてONにするだけです。
手順1
IAPを無効化
手順2
IAPを有効化
結果
上記手順を行った結果、service-[PROJECT-NUMBER]@gcp-sa-iap.iam.gserviceaccount.com
に権限付与ができるようになりました。
また、このときCloudRunのAuthenticationをAllow unauthenticated invocations
にしておくとIAPを一時OFFとしたときに誰でもアクセスできるようになってしまうため、 Require authentication
としておくことをおすすめします。
まとめ
本記事では、Terraformにてbackend service
を作ったときに、service-[PROJECT-NUMBER]@gcp-sa-iap.iam.gserviceaccount.com
が作られないという事例と、その回避方法を紹介しました。これ以外の発生条件や根本的な原因はわかりませんが、最初に設定しておけば害は無いと思うので深追いはせずに回避方法だけ紹介させていただきました。