こんにちは、Infrastructure Teamの宮本(@m1yam0t0)と申します。
本記事では、キャディの権限昇格システムの取り組みを紹介します。
目次
はじめに
みなさんは、パブリッククラウドの権限はどのように管理されていますか?
IAMでメンバーに必要な権限を付与していますでしょうか?TerraformでIaC管理されていますでしょうか?
キャディでは、最小権限の原則に従って、開発者には閲覧系の必要最低限の権限のみを付与しています。*1
開発・運用で追加の権限が必要になった場合は、Just-In-Time(JIT) Accessの仕組みで一定期間だけ権限昇格できるようになっています。
開発者が権限を申請し、承認者が承認してはじめて権限が付与されます。
最小権限の原則を徹底することで、昨今利用が広がっているAIエージェントを活用した場合にも、本番環境の権限を持っていないため、誤って操作してしまうリスクを低減できます。
本記事ではこのJIT Access Systemを内製システムからGoogle Cloud Priviledged Access Manager(PAM)に移行したお話を紹介いたします。
内製システムから Google Cloud PAM への移行
キャディでは、2022年より内製のJIT Access Systemを運用しておりました。
しかし、この内製のJIT Access Systemについて、認可制御に課題があったため、IAM Condition を組み合わせて権限が付与できるように改修を検討していました。
そんな中、Google Cloud PAM のアップデートで、権限のスコープが設定可能になったことを知り、検証をしてみたところ、内製のシステムを改修しづつけるより、効率良く目的を達成できることがわかりました。
IAM release notes | Identity and Access Management (IAM) | Google Cloud Documentation
上記を踏まえて、以下の理由から、キャディのJIT Access SystemをGoogle Cloud PAMへ移行する価値があると判断し、移行を実施いたしました。
- 権限のスコープを細かく設定でき、取得する権限を必要最小限に抑えられる
- Cloud Loggingに監査ログが残るため、通知や監査に活用できる
- Google Cloudマネージドのサービスであるためメンテナンス不要
PAM の利用資格の設定
Google Cloud PAMでは、取得したい権限のセットを利用資格として定義し、必要な権限に対応する利用資格を選択して申請します。
Terraform Provider が公式で提供されているため、IaCで管理できます。
利用資格はユースケースごとに複数作成するため、
以下のようなTerraform moduleを定義し、変数を入力することで容易に設定できるようにします。
resource "google_privileged_access_manager_entitlement" "entitlement" { provider = google-beta entitlement_id = var.entitlement_id location = var.location parent = var.parent max_request_duration = var.max_request_duration eligible_users { principals = var.eligible_users } privileged_access { gcp_iam_access { resource_type = var.resource_type resource = var.resource dynamic "role_bindings" { for_each = toset(var.roles) content { role = role_bindings.value } } } } approval_workflow { manual_approvals { require_approver_justification = var.require_approver_justification steps { approvers { principals = var.approvers } approvals_needed = var.approvals_needed approver_email_recipients = var.approver_email_recipients } } } additional_notification_targets { admin_email_recipients = var.notification_emails } requester_justification_config { unstructured {} } }
実際に利用する箇所では以下のようにTerraform moduleを呼び出して定義しています。
申請・承認するユーザを設定できるため、チームによって申請可能な利用資格を設定できます。
module "pam_org_gcs_bucket_read_access" { source = "../../modules/pam" # 利用資格名 entitlement_id = "gcs-bucket-read-access" # Organization, Folder, Project 単位で指定可能 parent = "organizations/${local.organization_id}" location = "global" resource_type = "cloudresourcemanager.googleapis.com/Organization" resource = "//cloudresourcemanager.googleapis.com/organizations/${local.organization_id}" # 取得したい role を定義 roles = [ "roles/storage.bucketViewer", "roles/storage.objectViewer", ] # 申請可能なユーザ eligible_users = [ "group:users@caddi.com", ] # 承認可能なユーザ approvers = [ "group:approvers@caddi.com", ] # 最大の申請期間 max_request_duration = "14400s" # 必要な承認の数 approvals_needed = 1 }
PAM の運用で工夫していること
Slack 通知機能の実装
PAMの通知機能はメール通知のみでSlackへの通知には標準では対応していません。
しかし、既存のJIT Access SystemではSlack通知するようにしていたため、利用者体験が変わらないようにする必要がありました。
そこで、PAMの監査ログの内容をパースしてSlack通知するAPIを実装しました。
以下のような仕組みで動作しています。
- Pub/Subを経由して、実装したSlack通知APIに送信
- Cloud Loggingに保存されているPAMの監査ログをLog routerでPub/Subに転送
- Pub/Subの Push Subscription を使ってCloud Runで動作しているSlack通知APIにHTTP POST
実際の構成図は以下です。

上記のSlack通知APIを利用して、既存システムの使用感はそのままに、SlackでPAMの申請・承認を通知できるようにしました。

Slack通知の内容についても、利便性を上げるために様々な改善をしています。
- 承認結果のメッセージを申請したメッセージのスレッドに紐づけて投稿
- 申請内容に不備がある場合は、申請内容の修正を促すように警告文を自動で投稿
- 申請のステータスによって、SlackのAttachmentの色を変更
Devin による利用資格設定の自動化
PAMの利用資格の中に取得したい権限が存在しない場合、利用資格を修正する必要があります。
PAMの移行当初は取得できる権限が不足しており、利用者から多く依頼を受けていました。
その度にTerraformの定義を修正しレビューするのは大変です。
そこで、Devinを使って、Terraformの修正からPRの作成を自動でしてもらうようにしました。
Devin Playbook で利用資格を修正するPR作成作業を定型化しています。
利用者がSlack Workflowで追加してほしい権限を入力するとDevinが呼び出され自動でPRを作成します。
あとは、チームメンバーがPRをレビュー、マージして反映するだけです。

まとめ
権限の最小化を徹底するために導入していたJIT Access Systemを、内製システムからGoogle Cloud PAMに移行しました。
PAMに移行したことで最小粒度の認可制御が可能になり、より安全にGoogle Cloud を運用できるようになりました。
また、AIエージェントの活用により運用の改善を効率良く実施できました。本当に便利なものですね。
みなさんがGoogle Cloud PAMを導入するときの参考になれば幸いです。
*1:Terraformで管理