
この記事は「Timee Advent Calendar 2025」シリーズ3の21日目の記事です。
今回はDREグループで導入したGoogle Cloudの PAM(Privileged Access Manager) についてご紹介します。
AIエージェントにGoogle Cloudの「権限」を預ける怖さ
最近DREグループ内では、開発効率を上げるためにローカル実行型の AIコーディングエージェント(Claude Code / Cursorなど) を積極的に活用していこうという動きがあります。
ローカル実行型のAIコーディングエージェントは、実行ユーザーのローカル認証情報を使って自律的にコマンドを実行します。つまり、ユーザーが持っている権限の範囲で、AIコーディングエージェントがGoogle Cloudのリソースにアクセスできてしまう状態になります。
人間が毎回チェックすれば良いという話もありますが、AIが生成した複雑なコマンドを完璧にノータイムでチェックし続けるのは、精神的にもかなりの負担です。
「普段は閲覧のみ、必要なときだけ必要な権限を」へ
タイミーのインフラ変更は Terraform + CI/CD が基本であるため、通常時は閲覧以外の権限は不要なはずです。しかし、現実には以下のような「編集権限が必要な瞬間」も存在します。
- 障害対応時の緊急オペレーション
- Terraform化されていないリソースの調査や一時的な変更
「AIを安全に使いたい」けれど、「いざという時は動きたい(=権限が必要)」。このニーズを解決するために導入したのが、Google Cloudの PAM(Privileged Access Manager) です。
Google CloudのPAM(Privileged Access Manager)とは
PAMは、一言で言うと「権限の時限付き貸し出し機能」を実現する仕組みです。
特定の権限を、「必要な時だけ」「承認を得て」「指定した時間だけ」ユーザーに付与することができます。
PAMを導入して良かったこと
- 編集権限の完全廃止: 普段は閲覧権限のみにしておける。AIエージェントが万が一暴走しても、そもそも権限がないので被害が出ない。
- 監査ログの強化: 「誰が」「いつ」「何の目的で」権限を昇格させたかが明確にログに残る。
- スムーズな承認フロー: チーム内での承認プロセスをGoogle Cloudの標準機能として組み込める。
導入後のフローと使用感

導入後は、権限が必要になったらGoogle Cloudコンソールの「特権アクセス管理」画面から申請を出します。
- 申請: 理由を書いてリクエストを送信。
- 承認: チームメンバーに通知が届き、コンソール上で承認ボタンを押す。
- 作業: 承認された瞬間から権限が有効化される。
- 自動終了: 設定時間が過ぎれば、自動で権限が剥奪される。
このフローのおかげで、普段の作業でAIエージェントがうっかり破壊的な指示を出したとしても、物理的に権限がないのでエラーで止まってくれます。この「ガードレールがある安心感」は、開発スピードを落とさないためにも非常に重要だと感じています。
PAMで解決したこと
PAMの導入により、DREグループでは以下の状態を作ることができました。
- AIエージェントを安心して活用できる: 通常時は閲覧権限のみ、誤爆のリスクがなくて安心
- 運用の機動力は犠牲にしない: 緊急時はPAMで即座に権限を昇格できて安心
- うっかりを仕組みで防ぐ: 人間もAIもミスをする前提で、システム側で安全性を担保できて安心
まとめ
AIコーディングエージェントは非常に強力な武器ですが、編集権限を持った状態では安心して利用できません。
DREグループではPAMの利用により「緊急対応の迅速さ」と「最小権限」を両立することができ、AIと人間が安心して開発が可能な環境に近づくことができました。
「AIをフル活用したいけれど、編集権限を持っているのが不安」という方は、ぜひGoogle CloudのPAMを活用して、安全なAI開発環境を構築してみてはいかがでしょうか。
明日のアドベントカレンダーもお楽しみに!
もし本記事やDREの取り組みにご興味があればぜひお話ししましょう!
付録:Terraformでの設定例
Terraformでの記述例を紹介します。 この例ではDREグループのメンバーが、必要に応じて「承認」を経てWriter権限をリクエストできるように構成しています。
# 1. PAMサービスエージェントへのIAMロール付与 resource "google_organization_iam_member" "pam_service_agent" { org_id = var.organization_id role = "roles/privilegedaccessmanager.serviceAgent" member = "serviceAccount:service-org-${var.organization_id}@gcp-sa-pam.iam.gserviceaccount.com" } # 2. 特権アクセスの設定(Entitlement) resource "google_privileged_access_manager_entitlement" "dre_admin" { entitlement_id = "dre-admin-entitlement" location = "global" max_request_duration = "3600s" # 最大1時間 parent = "organizations/${var.organization_id}" # 権限をリクエストできる対象(DREグループのアドレス) eligible_users { principals = [ "group:team-dre@example.com", ] } # 一時的に付与する権限 privileged_access { gcp_iam_access { role_bindings { role = "roles/writer" } resource = "//cloudresourcemanager.googleapis.com/organizations/${var.organization_id}" resource_type = "cloudresourcemanager.googleapis.com/Organization" } } # 承認ワークフローの設定 approval_workflow { manual_approvals { require_approver_justification = true steps { approvals_needed = 1 approver_email_recipients = [ "user:data-dre-manager@example.com", # 承認者 ] } } } # リクエスト時の理由入力を必須にする requester_justification_config { unstructured {} } depends_on = [google_organization_iam_member.pam_service_agent] }
実際に設定する際は、ユーザが作業に必要な最小の権限を付与するのが望ましいので、たとえばroles/bigquery.adminのようなサービスごとに権限を付与する特権アクセス設定を作成しましょう。