😺

CloudRunで動作するサービスをIAP(Identity Aware Proxy)で保護する構成をTerraformで実装する

2024/01/09に公開

記事の内容

CloudRun上で動作するサービスをIAP(Identity Aware Proxy)で保護する構成をTerraformで実装します。

IAPについて

Identity Aware ProxyはGCPのLoadbalancerなどと共に動作するProxyで、GCPサービスを簡単に保護することができます。

IAPを利用するとGCP上で登録したGoogleアカウントでログインしているブラウザからのみCloudRun上で動作するサービスにアクセスできる構成を簡単に作ることができるため、社内管理画面などをインターネットアクセスから保護したい場合に便利です。

記事の長さ

3分で読めます

CloudRunを実装する

まずは、保護対象であるCloudRunサービスを作成します。

cloudrun.tf

resource "google_cloud_run_v2_service" "this" {
  project  = var.project_id
  name     = "iap-cloudrun"
  location = "asia-northeast1"
  ingress  = "INGRESS_TRAFFIC_ALL"

  template {
    containers {
      image = "gcr.io/cloudrun/hello"
    }
  }
}

data "google_iam_policy" "noauth" {
  binding {
    role    = "roles/run.invoker"
    members = ["allUsers"]
  }
}

resource "google_cloud_run_v2_service_iam_policy" "policy" {
  project     = var.project_id
  location    = "asia-northeast1"
  name        = google_cloud_run_v2_service.this.name
  policy_data = data.google_iam_policy.noauth.policy_data
}

上記Terraformファイルをapplyすると、CloudRun上でテストサイトが起動します。

$ terraform apply

Grafana

Loadbalancerを設定する

IAPはLoadbalancerとともに動作するため、CloudRunへのアクセスをLoadbalancer経由に変更します。

CloudRunのIngressを変更する

先ほど作成したCLoudRunは、インターネットから直接CloudRunにアクセスすることを前提に作成されていたため、Loadbalancer経由でのアクセスに変更します。(ingressを変更する)

cloudrun.tf

resource "google_cloud_run_v2_service" "this" {
  project  = var.project_id
  name     = "iap-cloudrun"
  location = "asia-northeast1"

  # ここを変更。
  ingress  = "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER"

  template {
    containers {
      image = "gcr.io/cloudrun/hello"
    }
  }
}

data "google_iam_policy" "noauth" {
  binding {
    role    = "roles/run.invoker"
    members = ["allUsers"]
  }
}

resource "google_cloud_run_v2_service_iam_policy" "policy" {
  project     = var.project_id
  location    = "asia-northeast1"
  name        = google_cloud_run_v2_service.this.name
  policy_data = data.google_iam_policy.noauth.policy_data
}


Loadbalancerを作成する

CloudRunがLoadbalancer経由でアクセスを受け付けるようになったので、次はLoadbalancer自体を設定します。

lb.tf

resource "google_compute_region_network_endpoint_group" "this" {
  provider              = google-beta
  project               = var.project_id
  name                  = "cloudrun-neg"
  network_endpoint_type = "SERVERLESS"
  region                = "asia-northeast1"
  cloud_run {
    service = google_cloud_run_v2_service.this.name
  }
}

module "lb-http" {
  source = "GoogleCloudPlatform/lb-http/google//modules/serverless_negs"

  project = var.project_id
  name    = "iap-lb"

  managed_ssl_certificate_domains = [var.domain_name]
  ssl                             = true
  https_redirect                  = true

  backends = {
    default = {
      groups = [
        {
          group = google_compute_region_network_endpoint_group.this.id
        }
      ]

      enable_cdn = false

      log_config = {
        enable = false
      }

      iap_config = {
        enable = false
        oauth2_client_id = null
        oauth2_client_secret = null
      }

    }
  }
}

上記ファイルを作成後、再度Terraform Applyを実行します。

※Httpsアクセスが必要なため、独自ドメインを取得して、Loadbalancerに紐づけています。(DNSへのAレコードの追加は別で対応しています。)

Applyが成功したら、設定したdomain_nameにアクセスしてみてください。
先ほどCloudRunのURLにアクセスした時と同じ画面が表示されます。

IAPを設定する

アプリケーションが動作するCloudRunとLoadbalancerが作成できたので、最後にIAPを導入してCloudrun上で動作するアプリケーションにアクセスできるユーザーを限定します。

Oauth設定をする

まずは、IAP自体を利用できるようにするために、iap_brandを作成します。

iap.tf

resource "google_iap_brand" "project_brand" {
  support_email     = var.support_email
  application_title = "Cloud IAP protected Application"
  project           = var.project_id
}

IAPを実装するために、IAP Brandを作成します。

Support Emailにemailアドレスを設定し、上記Terraformソースを実行してください。

Applyが完了すると、OAuth Consent Screenに作成したアプリケーションが作成されているのを確認できます。

Grafana

OAuth client IDを作成する

次に、Oauth Client IDを作成します。これはTerraformが対応していないため、手動でコンソールから作成します。

Credentialsの画面からCREATE CREDENTIALSボタンをクリックし、OAuth client IDの選択項目を選択します。

Grafana

その後、Web applicationをApplication typeとして選択し、Nameは任意で、Authorized redirect URIsに保護したいドメイン名を入力します。

Grafana

この状態で作成すると、Oauth Clientのclient_idclient_secretが表示されますので、それをメモしておきます。(後ほどTerraformに使います)

アクセスできるユーザーを指定する

次にIAPで制限しているアプリケーションにアクセスできるユーザーを指定します。

iap.tf

resource "google_iap_brand" "project_brand" {
  support_email     = var.support_email
  application_title = "Cloud IAP protected Application"
  project           = var.project_id
}

resource "google_iap_client" "cloudrun_client" {
  display_name = "cloudrun_iap_client"
  brand        = google_iap_brand.project_brand.name
}

# これを追加
resource "google_iap_web_backend_service_iam_binding" "this" {
  project = var.project_id
  web_backend_service = module.lb-http.backend_services.default.name
  role = "roles/iap.httpsResourceAccessor"
  members = [
    "user:${var.access_user_email}",
  ]
}

上記のようにTerraformソースを変更して、access_user_emailにCloudRunにアクセス可能なユーザーのemailを設定してTerraform Applyを実行します。

LoadbalancerにIAPを設定する

IAPの準備とIAPにアクセスできるユーザーを設定したので、LoadbalancerにIAPを追加します。

lb.tf

resource "google_compute_region_network_endpoint_group" "this" {
  provider              = google-beta
  project               = var.project_id
  name                  = "cloudrun-neg"
  network_endpoint_type = "SERVERLESS"
  region                = "asia-northeast1"
  cloud_run {
    service = google_cloud_run_v2_service.this.name
  }
}

module "lb-http" {
  source = "GoogleCloudPlatform/lb-http/google//modules/serverless_negs"

  project = var.project_id
  name    = "iap-lb"

  managed_ssl_certificate_domains = [var.domain_name]
  ssl                             = true
  https_redirect                  = true

  backends = {
    default = {
      groups = [
        {
          group = google_compute_region_network_endpoint_group.this.id
        }
      ]

      enable_cdn = false

      log_config = {
        enable = false
      }

# ここを変更
      iap_config = {
        enable = true
        oauth2_client_id = var.oauth2_client_id
        oauth2_client_secret = var.oauth2_client_secret
      }

    }
  }
}

上記のようにLoadbalancerのTerraform moduleにIAPを設定して、Terraform Applyを実行します。
oauth2_client_idoauth2_client_secretには、手動で作成してメモしておいたOAuth Clientのclient_idとclient_secretを設定します。

これで全ての実装が完了しました。

正常に保護されていることを確認する

最後にCloudRunのサイトが正常にIAPで保護されていることを確認します。
※IAPの反映まで5分ほどかかるので、Terraform Applyから10分ほど待ってから実験してください。

今回作成したアプリケーションのURLにアクセスするとGoogle認証が求められます。そして、今回追加したユーザーでログインすることでCloudRunのアプリケーションを表示できます!

Sample Code

Githubに今回作成したリソースを配置しておきます!

https://github.com/rara-tan/zenn-cloudrun-iap

note

勉強法やキャリア構築法など、エンジニアに役立つ記事をnoteで配信しています。

https://note.com/ring_belle/membership

Discussion