まえがき
会社組織としてGoogle Cloudを管理していると、文書上のポリシーだけではなく実際に行ってはならないことを技術的に制限したくなることが多々ある。
ただし、例外的に静的ホストをしたいコンテンツ等が存在し、わざわざロードバランサやCompute EngineでApacheやnginxを利用してホストするなどアホらしいことはしたくない。
その中で、Google Cloudで利用出来る組織ポリシーの中にあるCloud Storageの外部公開の制限について検証をした。
今回の検証について
Classmethod社のブログにて、既に Cloud Storageの公開アクセスの防止を適用する組織ポリシーを検証してみた という記事が公開されている。
記事の内容自体は上記の記事とほぼ同じだが、全く同じことをやった1年ほど前の記憶と実際の挙動について違いがあったので覚え書き。
組織ポリシーの設定
基本的に、組織向けにセットアップされたGoogle Cloudでは 組織 > フォルダ (ネスト可能) > プロジェクト の親子関係があり、最上位のポリシーがフォルダやプロジェクトに継承される。
その中で、 constraints/storage.publicAccessPrevention
の設定値が組織内に存在するCloud Storageのバケットを公開・非公開を強制する。 (デフォルトは公開可能)
タグとタグの値
Google Cloudにはタグとそのタグに紐付く値という概念があり(リソースに付与するラベルとは明確に異なる)、そのタグ・値を事前に定義しておく。
この場合、後述する組織ポリシーの条件式で参照可能で、該当のリソースにタグを付与することで条件に合致させ行動を許可・拒否することが可能になる。
実際の設定
組織 (またはフォルダなど、行動を制限したい最上位。基本的に組織で良いと思う)にプロジェクトを切り替え、 IAM & Admin → Tags から作成を行う。
タグ名 | 値 |
---|---|
allow-storage-public |
allow |
今回は簡易的にこんな感じでタグを作成した。
その次は、ポリシーの設定を行う。
IAM & Admin → Organization Policies から Enforce Public Access Prevention を選択し、設定を以下のように変更する。
- Policy source を Override parent’s policy へ変更する
- Rules のデフォルトになる値を Enforced に変更する
- Add a rule からルールを追加し、 Enforcement を Off し Edit condition から条件を設定する (以下画像参考)
とりあえずここまで設定すると、組織全体でCloud Storageの外部公開が 禁止 になる。
挙動の確認
Cloud Storage から適当にバケットを作成し、 Permission から allUsers
を “Storage Legacy Object Reader” 付与すると IAM ポリシーの更新に失敗する。これは想定通り。
次に、 Tags から先程作成したタグを追加する。(または別のバケットを作成してタグを追加する。)
設定後に、再び allUsers
に対して “Storage Legacy Object Reader” を付与すると 失敗する。(なんでだよ)
原因と解消
実は記事冒頭のClassmethod社の記事には一か所大切な部分が抜けており、UIからポチポチ作成するとバケットの設定が以下のようになる。
これは、バケット自体の設定で公開を許容しない設定になっているためであり、組織ポリシーの影響を 受けない。
そのため、 gcloud
コマンドでバケットの作成時もしくは設定の変更を行う。ドキュメントの Use public access prevention で触れられているが、 --no-public-access-prevention
フラグを指定する必要がある。
作成時
$ gcloud storage buckets create gs://BUCKET_NAME \
--location=us \
--no-public-access-prevention
更新時
$ gcloud storage buckets update gs://BUCKET_NAME \
--no-public-access-prevention
この設定を行うことでバケット自体の設定が変更され、先程の項目の値が変わり allUsers
に対して権限を付与することが可能になる。
オチ。Terraform だと
Terraformのドキュメント によると、任意オプションである public_access_prevention
は inherited
または enforced
を受け付け、デフォルトでは inherited
(つまり、組織の設定を継承するためタグの有無によって挙動が変わる) になっている。
そりゃTerraformで書いてたら気づかんわ。