GCPに構築したシステムを安全に運用するための一時権限付与の仕組みについて

データシステム担当の黒瀬です。

こちらは、TVer Advent Calendar 2022の9日目の記事です。

この記事では、TVerで運用しているデータシステムの基本的な権限管理ポリシーについてご紹介します。

大まかな内容

  • GCP上に構築しているデータシステムをメンテナンスする際の権限を、従来は管理者が手動管理していたが、この運用にはリスクがありました。
  • そこで、権限を付与するためのサービスアカウントを経由する仕組みおよびその趣旨を明確にするルールを導入しました。
  • 結果、管理者に依存せずにメンテナンスができる運用が可能になりました。

背景

TVerでは、主にBigQueryに視聴ログなどのデータを集約し、その上で集計や分析をするという方針をとっています。

ログを収集するシステムはAWSGCPなど要件に合わせて各所に構築されていますが、これらからBigQueryへデータを収集・集約するためのETLについては、BigQueryとの親和性を考慮し、専らGCP上で構築しています。

課題

こうしたETLについては、デプロイもほとんどが自動化されているのですが、それでも手動でシステムに手を入れるメンテナンスが必要なことがあります。

例えば、ETLの連携先の変更・追加や、CI/CDそのものの設定変更といった場合です。

通例、開発者は開発時に利用した強い権限をそのまま引き継いでいたため、管理者としてメンテナンスも実施します。その際は元々権限を持っているため、システムに手を入れられますが、他のメンバーへ実作業を依頼することも多々あります。

こうしたケースでは、その管理者がその都度作業者へ権限を付与してから作業する、という方法をとっていました。

しかし、これには次の課題がありました。

  • 課題1. 管理者が普段の作業で意図せずETLのリソースを変更したりやデータを削除してしまうリスクがあるという点
  • 課題2. 管理者が休暇をとっている際にメンテナンスができなくなってしまう点
  • 課題3. 作業後に管理者への権限無効化依頼を徹底しないと、権限を付与したままになってしまう点
  • 課題4. 各権限の趣旨が後からたどれない点

そこで、下記を要件とする仕組みを検討することになりました。

  • 要件1. 管理者自身も権限付与のための権限を普段持っていなくても済むこと
  • 要件2. 管理者に逐一権限付与を依頼しなくても自分のタイミングで権限を付与できること
  • 要件3. 不要になった権限は自動で無効化されること
  • 要件4. 各権限が何のためのものなのかが分かること

方針

これらの要件に対して、次のGCPの機能を利用することにしました。

service account impersonation

これは、あるサービスアカウントとしてふるまう(impersonate)ことで、そのサービスアカウントの権限でGCPのリソースを操作するという機能です。

cloud.google.com

例えば、Cloud SQL Admin roleを持つサービスアカウントを用意しておき、あるユーザアカウントがそのサービスアカウントとしてふるまうことで、実行元のユーザアカウント自体には権限がなくても、Cloud SQL Admin roleを持っているかのようにふるまうことができます。

また、その際はgcloud CLIに用意されている --impersonate-service-account フラグを利用します。

cloud.google.com

つまり、ETLのメンテナンスに必要な権限をもつサービスアカウント(以下、準特権アカウント)を用意し、そのサービスアカウントとしてふるまえるユーザアカウントを事前に設定しておいた上で、gcloudコマンドを利用することで、上述の要件1および2を次のように満たすことが可能です。

  • 要件1に対して: 管理者は権限付与の窓口を準特権アカウントに移管することで、ETLのメンテナンス用の権限を持っておく必要がなくなる
  • 要件2に対して: gcloudで各担当者がいつでも準特権アカウントとしてふるまうことで、管理者のスケジュールとは独立してメンテナンスを実施できる

conditional role bindings

文字通り、条件付きで権限付与できる機能です。

cloud.google.com

具体的には、あるタグが付与されているリソースにのみ権限を与える・ある文字列にマッチするリソース名を持つリソースにのみ権限を与える・時間制限をつける、といったことが可能です。

また、その権限付与単位でタイトルや説明文を付記することができます。

他にも下記にあるように多様な制御が可能になっています。

cloud.google.com

つまり、ETLのメンテナンスに必要な権限はその都度期限およびその趣旨を付記することで、上記の要件3および4を次のように解決することが可能です。

  • 要件3に対して: 当該権限の有効期限が過ぎれば自動で無効化される
  • 要件4に対して: 当該権限が何の趣旨なのかをIAMの一覧画面で確認できる

アプローチ

これらの機能を利用し、下記の要領で権限管理の仕組みを作成しました。

  1. ETLを構築しているGCPプロジェクトに対してIAMの操作権限(Project IAM Admin)を持つ準特権アカウントを、それ専用のGCPプロジェクト上に作成します*1

  2. その準特権アカウントに対して、ETLのメンテナンスに関わるメンバーがService Account Token Creatorを持つように権限付与します。

準特権アカウントを経由した権限付与

そして、ETLのメンテナンス時には、担当者はgcloudコマンドで自分に期限付き権限を付与します。

例えば、

  • 準特権アカウント名: sa@another-prj.iam.gserviceaccount.com
  • ユーザアカウント名: superguy@example.com
  • 権限付与先GCPプロジェクト: etl-prj-prd
  • 有効期限: UTCの2022-12-01 23:59:59
  • 権限のロール名: BigQuery Data Owner
  • この権限の趣旨のメンテナンス手順のissueへのリンク: https://example.com/some-task-board/1234

の場合、次のコマンドを実行します。

$ gcloud projects add-iam-policy-binding etl-prj-prd \
    --member="user:superguy@example.com" \
    --role="roles/bigquery.dataOwner" \
    --condition='expression=request.time < timestamp("2022-12-01T23:59:59Z"),title=https://example.com/some-task-board/1234' \
    --impersonate-service-account sa@another-prj.iam.gserviceaccount.com

実際のメンテナンスでは、複数のロールを必要とすることが多いため、これとは別途作成したラッパスクリプトも利用して作業をしています。

効果

これらの施策によって下記の通り各課題が解決できました。

  • 課題1に対して: 管理者に逐一権限付与を依頼しなくても自分のタイミングで権限を付与できるようになりました。
  • 課題2に対して: 管理者自身も権限付与のための権限を普段持っていなくても済むようになりました。
  • 課題3に対して: 不要になった権限は自動で無効化されるようになりました。
  • 課題4に対して: 各権限が何のためのものなのかが分かるようになりました。

まとめ

  • 従来のメンテナンスでは、管理者へ都度権限を付与の依頼をする必要があり、権限の管理が煩雑になっていました。
  • そこで、GCPのservice account impersonationおよびconditional role bindingsを利用することにしました。
  • データシステムの担当者が自分のタイミングで必要な権限を最小範囲で付与しつつ、その目的を明確化することができました。

今後

今回ご紹介した施策はまだまだ改善の余地があります。今後は例えば下記のような施策に取り組んでいきたいと考えています。

  • gcloudコマンドではなく別のUIで権限付与できるようにすること
  • 手動のメンテナンスが必要な箇所を減らすべく自動化の対応範囲を広げること

*1:同じGCPプロジェクトにあると、準特権アカウントとしてふるまえる人をいつでも増やせてしまうためです。この時、その準特権アカウントが所属するGCPプロジェクトには、各自のユーザアカウントからは変更を加えたりできないように権限をしぼっておきます。