😴

外部IPなしのCloud WorkstationsにCloud Run + IAPでブラウザから直接アクセスする

に公開

kura@ちゅらデータのエンジニア(45)です。
はっぴばーすでーとぅみーー、はっぴばーすでーとぅみーー

アラフィフの仲間入り、・・・そんな年齢になりました!

前回に引き続きCloud Workstationsネタです。IAP(Identity-Aware Proxy)認証を使い、VPNもローカルプロキシも不要で、ブラウザから外部IPなしの Cloud Workstationsに直接アクセスする方法を解説します。

はじめに

前回の記事では gcloud run services proxy を使ったローカルプロキシ経由のアクセス方法を紹介しました。最近iPadを買いまして、それで開発をやってみたいんですよ、なので今回はIAP認証をCloud Runでやって、ブラウザから直接アクセスできる構成にします。

前回との違い

項目 前回 今回
認証 gcloud run services proxy(IAM認証) IAP(Googleログイン)
アクセス方法 localhost:8080 経由 ブラウザで直接URL

アーキテクチャ

IAP認証で、許可されたGoogleアカウントだけがCloud Run URLにアクセスできます。

IAP認証の仕組み

従来のIAM認証との比較

IAP設定のポイント

IAP on Cloud RunはTerraformがネイティブ対応していないようなので、null_resourcegcloud コマンドを実行します。

# IAP有効化(サービス更新時に自動再適用)
resource "null_resource" "enable_iap" {
  triggers = {
    service_name     = google_cloud_run_v2_service.proxy.name
    service_revision = google_cloud_run_v2_service.proxy.latest_ready_revision
  }

  provisioner "local-exec" {
    command = <<-EOT
      gcloud beta run services update ${var.service_name} \
        --region=${var.region} \
        --project=${var.project_id} \
        --iap
    EOT
  }

  depends_on = [google_cloud_run_v2_service.proxy]
}

重要: service_revision をトリガーに含めると、terraform apply でサービスが更新されるたびにIAP設定が自動で再適用されます。デプロイ後にIAP設定が消える問題を防げます。

IAMアクセス権の付与

# Cloud Run invoker権限
resource "google_cloud_run_v2_service_iam_member" "iap_users" {
  for_each = toset(var.iap_users)
  role     = "roles/run.invoker"
  member   = each.value
}

# IAPアクセス権限
resource "null_resource" "iap_access" {
  for_each = toset(var.iap_users)

  provisioner "local-exec" {
    command = <<-EOT
      gcloud beta iap web add-iam-policy-binding \
        --region=${var.region} \
        --resource-type=cloud-run \
        --service=${var.service_name} \
        --project=${var.project_id} \
        --member="${each.value}" \
        --role="roles/iap.httpsResourceAccessor"
    EOT
  }
}

terraform.tfvars で許可ユーザーを指定:

iap_users = ["user:alice@example.com", "user:bob@example.com"]

セッションベースのルーティング

VS Code IDEは静的リソース(CSS, JS)を /vscode/... のようなパスで取得します。正しいWorkstationにルーティングするため、セッションに「最後にアクセスしたWorkstation名」を記憶します:

# セッション管理
_sessions = {}  # {session_id: {"expires": timestamp, "last_workstation": str}}

@web.middleware
async def session_middleware(request, handler):
    """セッション管理ミドルウェア"""
    session_id = request.cookies.get('session')
    if not session_id or session_id not in _sessions:
        session_id = secrets.token_urlsafe(32)
        _sessions[session_id] = {"expires": time.time() + SESSION_DURATION}
        response = await handler(request)
        response.set_cookie('session', session_id, httponly=True, max_age=SESSION_DURATION)
        return response
    return await handler(request)

ハマったポイント

1. IAP設定がterraform applyで消える

問題: サービス更新後にIAP設定が無効化されてForbiddenエラー

原因: null_resource のトリガーにサービスリビジョンがなかった

解決: service_revision をトリガーに追加

triggers = {
  service_name     = google_cloud_run_v2_service.proxy.name
  service_revision = google_cloud_run_v2_service.proxy.latest_ready_revision  # これが重要
}

まとめ

IAP認証をCloud Runに統合して、ブラウザからCloudRunにアクセスしてWorkStationsを利用できるようにしました。これでiPadから使える。

※Cloud RunのIAP認証は2025年12月時点でプレビュー機能です。

Discussion