ACE Exam Preparation

Domain 4
アクセスとセキュリティの構成

Identity and Access Management (IAM), Service Accounts, Security Command Center, Cloud Armor, and more.

試験比重: 約20%
01

Chapter 1: セキュリティの基本概念と設計原則

Google Cloud セキュリティの 3 つの基本原則と責任共有モデル

1.1Google Cloud セキュリティの 3 つの基本原則

原則①: 最小特権の原則(Principle of Least Privilege)

必要な権限だけを、必要な人・サービスにだけ、必要な期間だけ付与する。

最小特権の比較: 悪い例(過剰権限)と 良い例(最小権限)
観点悪い例: 過剰な権限良い例: 最小権限
付与する権限とりあえず Editor を全員に付与フロントエンドエンジニアには Cloud Run のデプロイ権限だけを付与
VM 操作誰でも VM を削除できる必要な操作だけ実行できる
DB 操作誰でも DB を変更できるDB 変更は専用 SA / DBA のみ
侵害時の影響範囲被害が組織全体に拡大他リソースへの波及を最小化

原則②: 職務分掌(Separation of Duties)

同一人物がすべての操作を単独で実行できないようにし、コードを書いた人がそのまま本番デプロイできない仕組みを作る。

原則③: 深層防御(Defense in Depth)

複数のセキュリティ層を重ねて、1 つの層が破られても他の層で防御する。

深層防御の層構造 (Defense in Depth)外側Cloud Armor(DDoS / WAF)ネットワークファイアウォール / VPC Service Controls認証IAM / Identity-Aware ProxyデータCloud KMS (暗号化) / Secret Manager監視Security Command Center / Cloud Logging外側ほど広範囲・内側ほど機密性が高い — 各層が独立して防御
1.2Google の共有責任モデル(Shared Responsibility Model)
Google の共有責任モデル誰が何を守るか?Google の責任• 物理インフラのセキュリティ(データセンター)• ハードウェア / ソフトウェアの脆弱性対応• ネットワークの基盤セキュリティ• マネージドサービスのセキュリティ (GKE Autopilot 等)顧客 (あなた) の責任• IAM 設定 (誰がアクセスできるか)• データの暗号化設定• アプリケーションのセキュリティ• ファイアウォールルールの設定• シークレット・認証情報の管理責任の境界はサービスによって異なるIaaS (Compute Engine)顧客の責任範囲が広いPaaS (Cloud Run)Google の責任範囲が広いSaaS (Google Workspace)ほぼ Google が管理左から右に向かって、顧客責任は縮小し Google 責任は拡大する
02

Chapter 2: IAM の基本アーキテクチャ

主体・ロール・リソースの関係と命名規則

2.1IAM の 3 つの要素

IAM(Identity and Access Management)は, Google Cloud のすべてのアクセス制御の基盤です。

IAM の 3 要素
#要素英名 / 別名意味
主体Principal / Who誰がアクセスするか?
ロールRole / Can do what何ができるか?
リソースResource / On whichどのリソースに対して?

IAM ポリシー = 主体 + ロール + リソース の組み合わせ

2.2主体(Principal)の種類
主体の種類説明
Google アカウント個人ユーザーuser:alice@example.com
サービスアカウントアプリ・プログラムのアカウントserviceAccount:my-app@project.iam.gserviceaccount.com
Google グループユーザーのグループ(推奨)group:dev-team@example.com
Google Workspace ドメインドメイン全体のユーザーdomain:example.com
Cloud Identity ドメインCloud Identity のユーザー全員domain:example.com
allUsersインターネット上の誰でも公開バケットなど
allAuthenticatedUsersGoogle アカウントを持つ誰でもほぼ使用しない
⚠️ 試験頻出

allUsersallAuthenticatedUsers公開設定になるため、機密リソースには絶対に使用しないこと!

2.3権限(Permission)の命名規則
権限の命名規則: service.resource.verb

例:
  compute.instances.create    → VM インスタンスの作成
  storage.objects.get         → Storage オブジェクトの取得
  bigquery.tables.create      → BigQuery テーブルの作成
  iam.serviceAccounts.actAs   → サービスアカウントとして動作

【service の例】
  compute    → Compute Engine
  storage    → Cloud Storage
  bigquery   → BigQuery
  iam        → IAM
  container  → GKE
  run        → Cloud Run
  cloudsql   → Cloud SQL
2.4IAM ポリシーの構造
{
  "bindings": [
    {
      "role": "roles/storage.objectViewer",
      "members": [
        "user:alice@example.com",
        "group:dev-team@example.com",
        "serviceAccount:my-app@project.iam.gserviceaccount.com"
      ]
    },
    {
      "role": "roles/compute.instanceAdmin.v1",
      "members": [
        "user:bob@example.com"
      ],
      "condition": {
        "title": "Production Hours Only",
        "expression": "request.time.getHours('Asia/Tokyo') >= 9 && request.time.getHours('Asia/Tokyo') < 18"
      }
    }
  ],
  "version": 3
}
03

Chapter 3: ロールの 3 種類:基本 / 事前定義 / カスタム

基本ロール(非推奨)・事前定義ロール・カスタムロールの使い分け

3.1基本ロール(Basic Roles / Primitive Roles)
【3 つの基本ロール】

roles/viewer(閲覧者)
  └── すべてのリソースを閲覧のみ(変更不可)

roles/editor(編集者)
  └── ほぼすべてのリソースを作成・更新・削除
      ※ IAM の変更・請求設定は不可

roles/owner(オーナー)
  └── すべての権限(IAM 変更・請求設定も含む)

⚠️ 基本ロールを使ってはいけない理由

【なぜ本番環境で基本ロールを使ってはいけないのか?】

roles/editor を付与した場合:
  ✅ やりたいこと: Cloud Run へのデプロイ
  ❌ 意図しない権限:
      ・Cloud SQL の DB を削除できる
      ・Cloud Storage バケットを削除できる
      ・Cloud Spanner のデータを変更できる
      ・Compute Engine の VM を削除できる
      ・Secret Manager のシークレットを読める

→ 必要以上の権限が付与されてしまう
→ アカウントが侵害された場合の被害が甚大

【例外的に使用可能なケース】
  ├── 開発環境での個人プロジェクト(学習目的)
  ├── 小規模チームの初期フェーズ(一時的)
  └── 組織ポリシーで後から制限することを前提に
3.2事前定義ロール(Predefined Roles)

Google が各サービスに対してキュレーションした細かいロールです。

Compute Engine

ロール権限の概要
roles/compute.adminCompute Engine の完全管理
roles/compute.instanceAdmin.v1VM インスタンスの作成・管理(ネットワーク変更不可)
roles/compute.networkAdminネットワークリソースの管理
roles/compute.osLoginOS Login での SSH 接続
roles/compute.osAdminLoginOS Login での SSH 接続(sudo 権限付き)
roles/compute.viewer閲覧のみ

Cloud Storage

ロール権限の概要
roles/storage.adminバケット・オブジェクトの完全管理
roles/storage.objectAdminオブジェクトの完全管理(バケット設定変更不可)
roles/storage.objectCreatorオブジェクトのアップロードのみ
roles/storage.objectViewerオブジェクトの閲覧のみ

IAM & Service Accounts

ロール権限の概要
roles/iam.securityAdminIAM ポリシーの表示・設定
roles/iam.roleAdminカスタムロールの作成・管理
roles/iam.serviceAccountAdminサービスアカウントの作成・管理
roles/iam.serviceAccountUserSA を VM 等にアタッチする権限
roles/iam.serviceAccountTokenCreatorSA の短期トークンを生成(権限借用)
roles/iam.workloadIdentityUserWorkload Identity を通じた SA へのアクセス

GKE

ロール権限の概要
roles/container.adminGKE クラスタの完全管理
roles/container.developerGKE のワークロード管理(クラスタ設定変更不可)
roles/container.clusterViewerクラスタ情報の閲覧のみ

Cloud Run

ロール権限の概要
roles/run.adminCloud Run の完全管理
roles/run.developerデプロイ・設定変更
roles/run.invokerCloud Run サービスへのリクエスト送信

BigQuery

ロール権限の概要
roles/bigquery.adminBigQuery の完全管理
roles/bigquery.dataEditorデータセット・テーブルの編集
roles/bigquery.dataViewerデータの閲覧のみ
roles/bigquery.jobUserクエリの実行(データへのアクセス権は別途必要)
3.3カスタムロール(Custom Roles)
【カスタムロールを作成すべきケース】

事前定義ロールでは:
  ├── 権限が多すぎる(オーバースコープ)
  │   例: roles/storage.admin はバケット削除もできてしまう
  │       「オブジェクトのアップロードと読み取りだけ」のロールが欲しい
  │
  └── 複数のサービスにまたがる特定の組み合わせが必要
      例: Cloud Run のデプロイ権限 + Artifact Registry の読み取り権限

【カスタムロールの注意点】
  ├── 管理コストが増える(権限の追加・削除の追跡が必要)
  ├── Google が新しいサービスを追加しても自動更新されない
  └── 使いすぎると管理が複雑になる → 最小限にとどめる

カスタムロールの作成:

# YAML ファイルでカスタムロールを定義
cat > custom-deployer-role.yaml <<EOF
title: "Cloud Run Deployer"
description: "Cloud Run へのデプロイと Artifact Registry の読み取りのみ"
stage: "GA"
includedPermissions:
  - run.services.create
  - run.services.update
  - run.services.get
  - run.services.list
  - artifactregistry.repositories.get
  - artifactregistry.tags.get
  - artifactregistry.tags.list
  - storage.objects.get
  - storage.objects.list
EOF

# プロジェクトレベルでカスタムロールを作成
gcloud iam roles create cloudRunDeployer \
  --project=PROJECT_ID \
  --file=custom-deployer-role.yaml

# カスタムロールの一覧確認
gcloud iam roles list --project=PROJECT_ID --filter="name~customRoles"

# カスタムロールの詳細確認
gcloud iam roles describe cloudRunDeployer \
  --project=PROJECT_ID

# カスタムロールの更新(権限を追加)
gcloud iam roles update cloudRunDeployer \
  --project=PROJECT_ID \
  --add-permissions=run.routes.get
3.4ロール選択の意思決定フロー
権限を付与したい
    ↓
事前定義ロールで要件を満たせるか?
    ├── YES → 事前定義ロールを使用(推奨)
    │
    └── NO  → 事前定義ロールが広すぎる or 複数ロールの組み合わせが必要
              ↓
          カスタムロールを作成(最小限の権限で)

※ 基本ロール(Viewer/Editor/Owner)は最終手段
  → 本番環境では原則使用しない
✅ ベストプラクティス: ロール管理
#ベストプラクティス理由
1本番環境での基本ロール(Editor/Owner)使用を禁止過剰権限によるリスク
2ユーザーではなくグループにロールを付与メンバー変更時の管理コスト削減
3リソースレベルではなくプロジェクト/フォルダレベルで付与一元管理・継承の活用
4定期的に Policy Recommender で不要な権限を削除クリープ(権限の肥大化)防止
5カスタムロールは組織レベルで管理再利用・一元管理
04

Chapter 4: IAM ポリシーの設定と管理

CLI・API を用いたアクセス権限の付与と Policy Recommender

4.1IAM ポリシーの設定コマンド
# ===== プロジェクトレベルの IAM 操作 =====

# 現在の IAM ポリシーを確認
gcloud projects get-iam-policy PROJECT_ID

# ユーザーにロールを付与
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="user:alice@example.com" \
  --role="roles/run.developer"

# グループにロールを付与(推奨)
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="group:backend-team@example.com" \
  --role="roles/compute.instanceAdmin.v1"

# ロールを削除
gcloud projects remove-iam-policy-binding PROJECT_ID \
  --member="user:alice@example.com" \
  --role="roles/run.developer"

# ===== リソースレベルの IAM 操作 =====

# Cloud Storage バケットへの権限付与
gcloud storage buckets add-iam-policy-binding gs://my-bucket \
  --member="serviceAccount:my-app@PROJECT.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer"

# Cloud Run サービスへの Invoker 権限付与
gcloud run services add-iam-policy-binding my-service \
  --region=asia-northeast1 \
  --member="serviceAccount:caller-sa@PROJECT.iam.gserviceaccount.com" \
  --role="roles/run.invoker"

# BigQuery データセットへの権限付与
bq add-iam-policy-binding \
  --project=PROJECT_ID \
  --dataset=my_dataset \
  --member="group:data-team@example.com" \
  --role="roles/bigquery.dataViewer"
4.2IAM ポリシーの一括更新(Policy ファイルを使った管理)
# 現在のポリシーをファイルに書き出す
gcloud projects get-iam-policy PROJECT_ID \
  --format=json > current-policy.json

# ポリシーファイルを編集して一括更新
# (current-policy.json を編集後)
gcloud projects set-iam-policy PROJECT_ID current-policy.json
⚠️ 注意

`set-iam-policy` は完全上書きです!現在のポリシーを取得してから編集して適用してください。

4.3Policy Recommender(IAM 推奨事項)

Policy Recommender は、実際の使用状況を分析して、過剰な権限を検出し、より適切なロールを推奨する AI 搭載ツールです。

【Policy Recommender の仕組み】

90 日間のアクティビティを分析
    ↓
「このユーザーは Editor 権限を持っているが、
 実際に使ったのは Cloud Run の操作だけ」を検出
    ↓
推奨事項:
  「roles/editor → roles/run.developer に変更することを推奨
   これにより 150 の不要な権限が削除されます」
# プロジェクトの IAM 推奨事項を確認
gcloud recommender recommendations list \
  --project=PROJECT_ID \
  --location=global \
  --recommender=google.iam.policy.Recommender

# 推奨事項を適用(権限を縮小)
gcloud recommender recommendations apply RECOMMENDATION_ID \
  --project=PROJECT_ID \
  --location=global \
  --recommender=google.iam.policy.Recommender \
  --etag=ETAG

05 条件付きロールバインディング(IAM Conditions)

5.1 IAM Conditions とは?

IAM Conditions は、ロールバインディングに「条件」を追加して、特定の状況でのみ権限を有効にする機能です。

【通常のロールバインディング】
  alice に roles/storage.objectAdmin を付与
  → いつでも、どこからでもアクセス可能

【条件付きロールバインディング】
  alice に roles/storage.objectAdmin を付与
  ただし、以下の条件を満たす場合のみ:
    ├── 特定の時間帯のみ(例: 平日 9:00-18:00)
    ├── 特定のリソースのみ(例: 本番バケット以外)
    └── 特定のリクエスト元のみ
5.2 条件式の書き方(CEL: Common Expression Language)
【よく使う条件の種類】

① 時間ベースの条件
request.time.getHours('Asia/Tokyo') >= 9 &&
request.time.getHours('Asia/Tokyo') < 18

② 特定リソースへのアクセス制限
resource.name.startsWith("projects/my-project/datasets/staging")

③ リソースタイプによる制限
resource.type == "storage.googleapis.com/Object"

④ タグベースのアクセス制御
resource.matchTagId("tagValues/123456789")

実践的な使用例

# 例1: 業務時間内(JST 9:00-18:00)のみ権限を有効化
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="user:contractor@partner.com" \
  --role="roles/compute.instanceAdmin.v1" \
  --condition='
    title=BusinessHoursOnly,
    description=Only during business hours JST,
    expression=request.time.getHours("Asia/Tokyo") >= 9 && request.time.getHours("Asia/Tokyo") < 18'

# 例2: 有効期限付きの権限付与(一時的なアクセス)
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="user:temp-worker@example.com" \
  --role="roles/viewer" \
  --condition='
    title=TemporaryAccess,
    description=Valid until 2024-03-31,
    expression=request.time < timestamp("2024-03-31T23:59:59Z")'

# 例3: 特定の Cloud Storage パスのみアクセス許可
gcloud storage buckets add-iam-policy-binding gs://my-bucket \
  --member="serviceAccount:external-app@PROJECT.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer" \
  --condition='
    title=DevOnlyAccess,
    description=Access to dev prefix only,
    expression=resource.name.startsWith("projects/_/buckets/my-bucket/objects/dev/")'
5.3 グループ vs 個人へのロール付与
【個人(ユーザー)に直接ロールを付与する問題】

社員 A、B、C が同じ権限を必要としている場合:
  ユーザーごとに add-iam-policy-binding を 3 回実行
    ↓
社員 D が追加されたら また 1 回実行
社員 A が退職したら remove-iam-policy-binding を実行
    ↓
管理が煩雑・設定漏れのリスク

【グループにロールを付与する利点(推奨)】

Google グループ: backend-team@example.com に権限付与
    ↓
グループにメンバーを追加するだけで権限が自動付与
グループからメンバーを削除するだけで権限が自動剥奪
IAM ポリシーを変更する必要なし!

設定例:
  gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="group:backend-team@example.com" \
    --role="roles/run.developer"

✅ ベストプラクティス: IAM ポリシー管理

#ベストプラクティス理由
1個人ではなくグループにロールを付与メンバー変更時の管理を自動化
2最もスコープの小さいレベルで権限を付与影響範囲の最小化
3定期的な権限レビュー(90 日ごと)不要な権限の蓄積(クリープ)を防止
4IAM Conditions で一時的な権限を付与永続権限のリスクを排除
5`set-iam-policy` より `add/remove-iam-policy-binding` を使用他の権限を誤って上書きするリスクを防止

🔗 参考: https://docs.cloud.google.com/iam/docs/resource-hierarchy-access-control

06 サービスアカウントの基本概念と種類

6.1 サービスアカウントとは?
【人間のアカウント vs サービスアカウント】

人間のアカウント(User Account):
  └── alice@example.com でログインするのは「人間」

サービスアカウント(Service Account):
  └── my-app@project.iam.gserviceaccount.com
      これは「アプリケーション・プログラム」のアカウント

【サービスアカウントの二重の役割】

役割①: 主体(Principal)としてのサービスアカウント
  → 他のリソースにアクセスする「誰か」として機能
  例: VM 上のアプリが Cloud Storage を読み取る
      (VM に SA をアタッチ → SA の権限でアクセス)

役割②: リソース(Resource)としてのサービスアカウント
  → 「誰かが SA を使う権限を管理する対象」
  例: alice が特定の SA を使う権限を持つかどうか
      (SA へのアクセス自体を IAM で制御)
6.2 サービスアカウントの種類
種類作成者用途
ユーザー管理 SAユーザーが作成アプリ・CI/CD・GKE Pod など
デフォルト SAGoogle が自動作成App Engine、Compute Engine のデフォルト
Google 管理 SAGoogle が内部で使用Google サービスの内部通信

⚠️ デフォルト SA の危険性: Compute Engine のデフォルト SA は、組織の作成時期によっては roles/editor 相当の権限を自動付与される可能性があります。組織ポリシー(iam.automaticIamGrantsForDefaultServiceAccounts)を確認し、2024-05-03 以降に作成された組織ではこの制約がデフォルトで有効なため自動付与は行われませんが、旧来の組織では明示的に確認が必要です。いずれの場合も、専用の最小権限 SA を作成してアタッチしてください。

6.3 サービスアカウントの作成と管理
# サービスアカウントの作成
gcloud iam service-accounts create my-app-sa \
  --display-name="My Application Service Account" \
  --description="SA for the production web application"

# SA の一覧確認
gcloud iam service-accounts list

# SA の詳細確認
gcloud iam service-accounts describe \
  my-app-sa@PROJECT_ID.iam.gserviceaccount.com

# SA に IAM ロールを付与(SA が Cloud Storage を読み取る権限)
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:my-app-sa@PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer"

# SA を VM にアタッチ(VM 作成時)
gcloud compute instances create my-vm \
  --service-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com \
  --scopes=cloud-platform \
  --zone=asia-northeast1-a

# 既存 VM の SA を変更
gcloud compute instances set-service-account my-vm \
  --service-account=new-sa@PROJECT_ID.iam.gserviceaccount.com \
  --scopes=cloud-platform \
  --zone=asia-northeast1-a

# SA の無効化(削除せずに一時停止)
gcloud iam service-accounts disable \
  my-app-sa@PROJECT_ID.iam.gserviceaccount.com

# SA の削除
gcloud iam service-accounts delete \
  my-app-sa@PROJECT_ID.iam.gserviceaccount.com
6.4 iam.serviceAccounts.actAs 権限の重要性
【actAs 権限とは?】

「サービスアカウントを VM にアタッチする」操作は
roles/iam.serviceAccountUser(含む actAs 権限)が必要

なぜ重要か?
  privileged-sa には Cloud SQL Admin 権限がある
  → この SA を誰でも VM にアタッチできると
    誰でも privileged-sa の権限を利用できてしまう!

→ actAs 権限を持つ人だけが、その SA を使えるリソースを作成できる

gcloud iam service-accounts add-iam-policy-binding \
  privileged-sa@PROJECT.iam.gserviceaccount.com \
  --member="user:alice@example.com" \
  --role="roles/iam.serviceAccountUser"

07 サービスアカウントキーのリスクと代替手法

7.1 SA キー(JSON キー)の問題点
【サービスアカウントキーの生成から漏洩まで】

Step 1: エンジニアが SA キーを生成
  gcloud iam service-accounts keys create key.json \
    --iam-account=my-sa@PROJECT.iam.gserviceaccount.com

Step 2: key.json を CI/CD に設定 or ローカルに保存

Step 3: 誤って GitHub にコミット or ラップトップを紛失

Step 4: 攻撃者がキーを発見

Step 5: 攻撃者が GCP API を呼び出す
  gcloud auth activate-service-account --key-file=stolen-key.json

Step 6: 莫大な被害が発生!

【SA キーの管理コスト】
  ├── 定期的なローテーションが必要(90日ごと推奨)
  ├── 有効期限の管理
  ├── 誰がどのキーを持っているかの追跡
  └── 組織全体で数百〜数千のキーを管理する地獄

⚠️ ACE 試験最重要: SA JSON キーの使用はセキュリティ上の重大なアンチパターン。代替手法を必ず覚えること。

7.2 SA キーを使わない認証方法の選択
【シナリオ別の推奨認証方法】

シナリオ A: GCE/GKE/Cloud Run 上のアプリ
  → VM または Pod に SA をアタッチ
  → メタデータサーバーから自動的にトークンを取得
  → キー不要!

シナリオ B: 開発者のローカル PC
  → gcloud auth application-default login
  → ADC(Application Default Credentials)を使用
  → キー不要!

シナリオ C: GitHub Actions / GitLab CI / Jenkins
  → Workload Identity Federation を設定
  → CI/CD が動的にトークンを交換
  → キー不要!

シナリオ D: AWS / Azure / オンプレミスのシステム
  → Workload Identity Federation を設定
  → 外部 IdP のトークンを GCP トークンに交換
  → キー不要!

シナリオ E: 権限が必要な一時的な管理作業
  → SA Impersonation(権限借用)を使用
  → 短期トークンのみを生成
  → キー不要!

⚠️ SA JSON キーを使うべきシナリオ: ほぼなし
   どうしても必要な場合は組織ポリシーで管理し、
   有効期限を設定して定期ローテーションする

08 Workload Identity Federation

8.1 Workload Identity Federation とは?

外部システム(AWS、GitHub Actions など)から SA キーなしで Google Cloud API にアクセスするための仕組みです。

【Workload Identity Federation の仕組み】

従来(SA キー使用):
  GitHub Actions → key.json を秘密として保存 → GCP API 呼び出し

Workload Identity Federation(推奨):
  GitHub Actions
      ↓ OIDC トークン(GitHub が発行)を提示
  Google Cloud Security Token Service (STS)
      ↓ OIDC トークンを検証
      ↓ 短期有効な Google Cloud アクセストークンを発行
  GCP API を呼び出す
      ↓ 完了後トークンは自動失効

【メリット】
  ✓ SA キーをどこにも保存しない
  ✓ トークンは短期間で自動失効
  ✓ 監査ログで誰が何時アクセスしたか追跡可能
8.2 GitHub Actions との Workload Identity Federation 設定
# Step 1: Workload Identity Pool の作成
gcloud iam workload-identity-pools create github-pool \
  --location=global \
  --description="GitHub Actions Workload Identity Pool" \
  --display-name="GitHub Actions Pool"

# Step 2: GitHub の OIDC プロバイダーを登録
gcloud iam workload-identity-pools providers create-oidc github-provider \
  --location=global \
  --workload-identity-pool=github-pool \
  --display-name="GitHub OIDC Provider" \
  --issuer-uri="https://token.actions.githubusercontent.com" \
  --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.actor=assertion.actor,attribute.aud=assertion.aud" \
  --attribute-condition="assertion.repository_owner == 'my-org'"  # 組織を限定

# Step 3: SA を作成(CI/CD 用の最小権限 SA)
gcloud iam service-accounts create github-deploy-sa \
  --display-name="GitHub Actions Deploy SA"

gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:github-deploy-sa@PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/run.developer"  # 必要な権限のみ

# Step 4: Workload Identity Pool に SA への権限借用を許可
WORKLOAD_IDENTITY_POOL_ID=$(gcloud iam workload-identity-pools describe github-pool \
  --location=global \
  --format="value(name)")

gcloud iam service-accounts add-iam-policy-binding \
  github-deploy-sa@PROJECT_ID.iam.gserviceaccount.com \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/my-org/my-repo"

GitHub Actions ワークフローの設定

# .github/workflows/deploy.yml
name: Deploy to Cloud Run

on:
  push:
    branches: [main]

permissions:
  contents: read
  id-token: write  # OIDC トークンの生成を許可

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Workload Identity Federation で認証(SA キー不要!)
      - id: auth
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/providers/github-provider'
          service_account: 'github-deploy-sa@PROJECT_ID.iam.gserviceaccount.com'

      # gcloud が自動的に上記で取得したトークンを使用
      - name: Deploy to Cloud Run
        run: |
          gcloud run deploy my-service \
            --image=gcr.io/PROJECT/my-app:${{ github.sha }} \
            --region=asia-northeast1
8.3 GKE での Workload Identity

GKE 環境では、Pod が Google Cloud API にアクセスする際に Workload Identity を使用します。

# Step 1: GKE クラスタで Workload Identity を有効化
gcloud container clusters update my-cluster \
  --workload-pool=PROJECT_ID.svc.id.goog \
  --region=asia-northeast1

# Step 2: Google Cloud SA を作成
gcloud iam service-accounts create gke-app-sa \
  --display-name="GKE Application SA"

# Step 3: SA に必要な権限を付与
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:gke-app-sa@PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"  # Secret Manager へのアクセス

# Step 4: Kubernetes SA と Google Cloud SA を紐付け
gcloud iam service-accounts add-iam-policy-binding \
  gke-app-sa@PROJECT_ID.iam.gserviceaccount.com \
  --role=roles/iam.workloadIdentityUser \
  --member="serviceAccount:PROJECT_ID.svc.id.goog[my-namespace/my-ksa]"
# Kubernetes Service Account の設定
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-ksa
  namespace: my-namespace
  annotations:
    # Google Cloud SA に紐付け
    iam.gke.io/gcp-service-account: gke-app-sa@PROJECT_ID.iam.gserviceaccount.com

🔗 参考: https://docs.cloud.google.com/kubernetes-engine/docs/concepts/autopilot-security

09 Application Default Credentials (ADC)

9.1 ADC とは?

ADC は、コードを変更せずに認証情報を切り替えられる仕組みです。

【ADC の検索順序(コードが認証情報を探す順番)】

1. GOOGLE_APPLICATION_CREDENTIALS 環境変数
   └── 指定されたキーファイルを使用

2. gcloud auth application-default login で設定した認証情報
   └── ローカル開発環境での標準

3. GCE / GKE / Cloud Run などの実行環境
   └── メタデータサーバーからトークンを自動取得(キー不要)

4. Cloud Shell
   └── 自動的に認証済み

【コードは認証情報を意識しない】

# コードでは認証情報を指定しない
from google.cloud import storage
client = storage.Client()  # ADC が自動的に認証情報を解決
9.2 ローカル開発での ADC 設定
# 方法1: ユーザーアカウントで認証(最も一般的)
gcloud auth application-default login
# ブラウザが開いて Google アカウントでログイン
# 認証情報が ~/.config/gcloud/application_default_credentials.json に保存

# 方法2: SA を権限借用して ADC を設定
gcloud auth application-default login \
  --impersonate-service-account=my-sa@PROJECT.iam.gserviceaccount.com
# SA の権限でローカル開発が可能

# 方法3: 環境変数で SA キーを指定(非推奨)
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
# ※ 緊急時以外は使用しない

# ADC の設定を確認
gcloud auth application-default print-access-token

# ADC の設定を削除
gcloud auth application-default revoke

10 権限借用(Impersonation)と PAM

10.1 SA Impersonation(権限借用)
【権限借用の仕組み】

alice(通常の権限を持つエンジニア)
    ↓ roles/iam.serviceAccountTokenCreator を持つ
privileged-sa(管理者権限を持つ SA)
    ↓ 短期トークンを生成(1時間以内に自動失効)
管理タスクを実行
    ↓ 完了

【通常の権限付与との違い】

通常の権限付与:
  alice に直接 roles/storage.admin を付与
  → alice は永続的に全バケットを管理できる
  → alice のアカウントが侵害されると大問題

権限借用:
  alice は自分の権限ではなく SA を借用して作業
  → 短期トークンで操作(1時間で失効)
  → 「alice が privileged-sa を使って何時にどの操作をしたか」
    が監査ログに詳細記録される
  → alice 自身の権限は小さいまま

設定手順:

# Step 1: privileged-sa の作成
gcloud iam service-accounts create privileged-sa \
  --display-name="Privileged Operations SA"

# Step 2: privileged-sa に管理権限を付与
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:privileged-sa@PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/storage.admin"

# Step 3: alice に SA の TokenCreator 権限を付与
gcloud iam service-accounts add-iam-policy-binding \
  privileged-sa@PROJECT_ID.iam.gserviceaccount.com \
  --member="user:alice@example.com" \
  --role="roles/iam.serviceAccountTokenCreator"

# Step 4: alice が権限借用を使って操作
gcloud storage buckets list \
  --impersonate-service-account=privileged-sa@PROJECT_ID.iam.gserviceaccount.com

# または短期トークンを生成して使用
gcloud auth print-access-token \
  --impersonate-service-account=privileged-sa@PROJECT_ID.iam.gserviceaccount.com
10.2 Privileged Access Manager (PAM)

PAM は承認ワークフロー付きで一時的な特権アクセスを管理するエンタープライズ機能です。

【PAM のワークフロー】

Step 1: alice が特権アクセスをリクエスト
  「prod の Cloud SQL を修正するために DB Admin が必要(理由: インシデント対応)」

Step 2: 承認者(上長・セキュリティチーム)がリクエストを確認
  → Slack / Email で通知
  → 理由・期間を確認して承認 or 却下

Step 3: 承認されたら自動的にロールを付与
  → 指定期間(例: 2時間)だけ有効

Step 4: 期間終了後、自動的にロールを剥奪
  → 誰の操作も不要

Step 5: 全操作が監査ログに詳細記録
# PAM の設定(エンタイトルメントの作成)
gcloud pam entitlements create prod-db-admin-access \
  --location=global \
  --project=PROJECT_ID \
  --privileged-access='iamAccess={iamPolicies=[{resource=//cloudresourcemanager.googleapis.com/projects/PROJECT_ID,roleBindings=[{role=roles/cloudsql.admin}]}]}' \
  --max-request-duration=7200s \
  --approval-workflow='manualApprovals={steps=[{approvalsNeeded=1,approvers={principals=[user:manager@example.com]}}]}'

✅ ベストプラクティス: SA と認証管理

#ベストプラクティス理由
1SA JSON キーの生成を組織ポリシーで禁止漏洩リスクの根本排除
2GCE/GKE は SA を VM/Pod にアタッチ(キー不要)メタデータサーバーで自動認証
3CI/CD は Workload Identity Federation を設定キー不要・自動失効
4ローカル開発は ADC(gcloud auth application-default login)キー不要・ユーザー権限のまま
5特権操作は SA Impersonation または PAM監査ログ + 自動失効
61 SA = 1 アプリケーション / 1 目的最小権限・追跡可能性の確保

🔗 参考: https://cloud.google.com/blog/products/identity-security/iam-best-practice-guides-available-now

11 Secret Manager(シークレット管理)

11.1 Secret Manager とは?
【なぜ Secret Manager が必要か?】

❌ 絶対にやってはいけないこと:
  ├── コードにパスワードをハードコード
  │   DB_PASSWORD = "my-secret-password"
  ├── 環境変数に平文でシークレットを設定
  │   ENV DB_PASSWORD="my-secret-password"
  └── 設定ファイルをそのまま Git にコミット
      database.conf に password=... が含まれている

✅ Secret Manager を使う理由:
  ├── シークレットを安全に暗号化して保存
  ├── アクセス制御(IAM で誰が読めるかを制御)
  ├── バージョン管理(前のバージョンにロールバック可能)
  ├── 自動ローテーション(パスワードを定期更新)
  └── 監査ログ(誰がいつシークレットを読んだか記録)
11.2 Secret Manager の基本操作
# ===== シークレットの作成 =====

# テキストでシークレットを作成
echo -n "my-database-password" | \
  gcloud secrets create db-password \
    --replication-policy=automatic \
    --data-file=-

# ファイルからシークレットを作成
gcloud secrets create api-key \
  --replication-policy=automatic \
  --data-file=./api-key.txt

# ===== シークレットのバージョン管理 =====

# 新しいバージョンを追加(ローテーション)
echo -n "new-password-v2" | \
  gcloud secrets versions add db-password \
    --data-file=-

# バージョン一覧の確認
gcloud secrets versions list db-password

# ===== シークレットへのアクセス =====

# 最新バージョンにアクセス
gcloud secrets versions access latest --secret=db-password

# 特定バージョンにアクセス
gcloud secrets versions access 2 --secret=db-password

# ===== シークレットの管理 =====

# シークレット一覧
gcloud secrets list

# シークレットの詳細
gcloud secrets describe db-password

# 古いバージョンを無効化
gcloud secrets versions disable 1 --secret=db-password

# バージョンを削除(永久削除・復元不可)
gcloud secrets versions destroy 1 --secret=db-password

# シークレット自体を削除
gcloud secrets delete db-password
11.3 アプリケーションからのシークレットアクセス

Python からのアクセス

from google.cloud import secretmanager

def access_secret(project_id: str, secret_id: str, version_id: str = "latest") -> str:
    """Secret Manager からシークレットを取得"""
    client = secretmanager.SecretManagerServiceClient()
    
    # シークレットのリソース名を構築
    name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
    
    # シークレットにアクセス
    response = client.access_secret_version(request={"name": name})
    
    return response.payload.data.decode("UTF-8")

# 使用例
db_password = access_secret("my-project", "db-password")
# → "my-database-password"

Cloud Run での環境変数注入

# Cloud Run デプロイ時に Secret Manager のシークレットを環境変数として注入
gcloud run deploy my-service \
  --image=gcr.io/PROJECT/my-app:latest \
  --region=asia-northeast1 \
  --set-secrets="DB_PASSWORD=db-password:latest,API_KEY=api-key:latest"
  # 環境変数名=シークレット名:バージョン

Kubernetes(GKE)でのシークレットの使用

# Secret Store CSI Driver を使用して Pod に直接マウント
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: my-app-secrets
spec:
  provider: gcp
  parameters:
    secrets: |
      - resourceName: "projects/PROJECT/secrets/db-password/versions/latest"
        fileName: "db-password"
---
apiVersion: v1
kind: Pod
spec:
  volumes:
  - name: secrets-vol
    csi:
      driver: secrets-store.csi.k8s.io
      readOnly: true
      volumeAttributes:
        secretProviderClass: my-app-secrets
  containers:
  - name: app
    volumeMounts:
    - name: secrets-vol
      mountPath: /run/secrets
      readOnly: true
11.4 Secret Manager の IAM 設定
# SA にシークレットへのアクセス権を付与
gcloud secrets add-iam-policy-binding db-password \
  --member="serviceAccount:my-app-sa@PROJECT.iam.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

# 開発チームにシークレットの管理権限を付与
gcloud secrets add-iam-policy-binding db-password \
  --member="group:backend-team@example.com" \
  --role="roles/secretmanager.secretVersionManager"
ロール権限
roles/secretmanager.adminシークレットの完全管理
roles/secretmanager.secretAccessorシークレットの値を読み取る
roles/secretmanager.secretVersionManagerバージョンの作成・無効化(値の読み取りは不可)
roles/secretmanager.viewerシークレットのメタデータのみ閲覧

✅ ベストプラクティス: Secret Manager

#ベストプラクティス
1コードへのハードコードを根絶(コードレビューで CI/CD が検出)
2最小権限: アプリは secretAccessor のみ(管理権限は不要)
3Secret ローテーション: 90 日ごとにパスワードを自動更新
4アクセスログを Cloud Logging で監視(誰がいつ読んだか)
5リージョンを指定して規制コンプライアンスに対応

🔗 参考: https://cloud.google.com/secret-manager/docs/overview

12 Cloud KMS(鍵管理サービス)

12.1 Cloud KMS とは?
【Cloud KMS でできること】

暗号化キーの管理:
  ├── 暗号化キーを Cloud KMS で一元管理
  ├── キーのローテーション(定期的に新しいキーに切り替え)
  ├── キーへのアクセスを IAM で制御
  └── FIPS 140-2 準拠のハードウェアで保護

データの暗号化・復号化:
  └── Cloud KMS キーを使ってデータを暗号化・復号化
      (CMEK: Customer Managed Encryption Keys)

【デフォルト暗号化 vs CMEK】

デフォルト:
  Google が管理するキーでデータを暗号化
  → 自動・コストなし
  → キーの管理は Google が担当

CMEK(顧客管理暗号化キー):
  自分で作成・管理するキーでデータを暗号化
  → コストあり
  → キーの削除でデータへのアクセスを完全遮断可能
  → コンプライアンス要件(自社でキーを管理する義務)に対応
12.2 Cloud KMS の基本操作
# ===== キーリングとキーの作成 =====

# キーリングを作成(キーをグループ化するコンテナ)
gcloud kms keyrings create my-keyring \
  --location=asia-northeast1

# 対称暗号化キーを作成(データの暗号化・復号化)
gcloud kms keys create my-symmetric-key \
  --keyring=my-keyring \
  --location=asia-northeast1 \
  --purpose=encryption \
  --rotation-period=90d \
  --next-rotation-time=2024-04-01T00:00:00Z

# 非対称署名キーを作成(コード署名・JWT 署名など)
gcloud kms keys create my-asymmetric-key \
  --keyring=my-keyring \
  --location=asia-northeast1 \
  --purpose=asymmetric-signing \
  --default-algorithm=ec-sign-p256-sha256

# ===== 暗号化・復号化 =====

# ファイルを暗号化
gcloud kms encrypt \
  --keyring=my-keyring \
  --key=my-symmetric-key \
  --location=asia-northeast1 \
  --plaintext-file=sensitive-data.txt \
  --ciphertext-file=sensitive-data.enc

# ファイルを復号化
gcloud kms decrypt \
  --keyring=my-keyring \
  --key=my-symmetric-key \
  --location=asia-northeast1 \
  --ciphertext-file=sensitive-data.enc \
  --plaintext-file=decrypted-data.txt

# ===== キーバージョン管理 =====

# キーの全バージョン一覧
gcloud kms keys versions list \
  --key=my-symmetric-key \
  --keyring=my-keyring \
  --location=asia-northeast1

# 古いキーバージョンを無効化(既存データへのアクセスは可能)
gcloud kms keys versions disable 1 \
  --key=my-symmetric-key \
  --keyring=my-keyring \
  --location=asia-northeast1
12.3 CMEK による Cloud Storage の暗号化
# Cloud Storage バケットに CMEK を設定
gcloud storage buckets update gs://my-sensitive-bucket \
  --default-kms-key=projects/PROJECT/locations/asia-northeast1/keyRings/my-keyring/cryptoKeys/my-symmetric-key

# SA に Cloud Storage バケットがキーを使う権限を付与
gcloud kms keys add-iam-policy-binding my-symmetric-key \
  --keyring=my-keyring \
  --location=asia-northeast1 \
  --member="serviceAccount:service-PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com" \
  --role="roles/cloudkms.cryptoKeyEncrypterDecrypter"
KMS ロール権限
roles/cloudkms.adminキーの完全管理
roles/cloudkms.cryptoKeyEncrypterDecrypter暗号化と復号化の両方
roles/cloudkms.cryptoKeyEncrypter暗号化のみ
roles/cloudkms.cryptoKeyDecrypter復号化のみ
roles/cloudkms.viewerキーのメタデータ閲覧のみ

🔗 参考: https://cloud.google.com/kms/docs/overview

13 VPC Service Controls

13.1 VPC Service Controls とは?
【VPC Service Controls の目的】

通常の IAM:
  「誰が何のリソースにアクセスできるか」を制御

VPC Service Controls:
  「どこから」アクセスできるかを制御
  (IAM と組み合わせてより強固なセキュリティを実現)

【防御できる脅威】

脅威1: データの持ち出し(Data Exfiltration)
  攻撃者が会社の BigQuery データを
  自分の Google Cloud プロジェクトにコピーしようとする
  → VPC Service Controls でブロック!

脅威2: 認証情報の盗難後のアクセス
  盗まれた SA キーで外部から Cloud Storage にアクセスしようとする
  → VPC Service Controls で許可された場所からのみアクセス!

脅威3: フィッシング後の不正アクセス
  社員が騙されてフィッシングサイトで認証情報を入力
  → 特定の IP / VPC からのみアクセスを許可しているためブロック!
13.2 VPC Service Controls の設計
【サービス境界(Service Perimeter)の構造】

サービス境界(Service Perimeter):
  ├── 保護対象プロジェクト: project-A, project-B
  ├── 保護対象 API: BigQuery, Cloud Storage, Cloud SQL
  │
  ├── アクセスポリシー(誰がアクセスできるか):
  │   ├── VPC Network: my-corp-vpc(社内ネットワークから)
  │   ├── IP アドレス範囲: 203.0.113.0/24(会社の外部 IP)
  │   └── SA: trusted-sa@project.iam.gserviceaccount.com
  │
  └── アクセスレベル(Access Level):
      └── 上記の組み合わせで定義

境界外からのアクセス → PERMISSION DENIED
境界内からのアクセス → IAM で判断
# アクセスポリシーの作成
gcloud access-context-manager policies create \
  --organization=ORG_ID \
  --title="My Corp Access Policy"

# アクセスレベルの作成(会社の VPC + IP 範囲を許可)
gcloud access-context-manager levels create corp-network \
  --policy=POLICY_ID \
  --title="Corporate Network Access" \
  --basic-level-spec=access-level-spec.yaml

# サービス境界の作成
gcloud access-context-manager perimeters create my-perimeter \
  --policy=POLICY_ID \
  --title="Data Protection Perimeter" \
  --resources=projects/PROJECT_NUMBER \
  --restricted-services=bigquery.googleapis.com,storage.googleapis.com \
  --access-levels=accessPolicies/POLICY_ID/accessLevels/corp-network

🔗 参考: https://cloud.google.com/vpc-service-controls/docs/overview

14 Identity-Aware Proxy (IAP)

14.1 IAP とは?
【IAP がない場合(従来の方法)】

ユーザー → インターネット → VPN → 社内システム
または
ユーザー → インターネット → Bastion Host → 社内システム

問題点:
  ├── VPN のセットアップが面倒
  ├── Bastion Host の管理コスト
  └── VPN が侵害されると内部に全アクセス

【IAP がある場合(ゼロトラストアクセス)】

ユーザー → インターネット → IAP → Google 内部ネットワーク → アプリ
              ↑
         認証・認可をここで実施
         ・Google アカウントで認証
         ・IAM で認可(どのユーザーがアクセス可能か)
         ・デバイスのセキュリティ状態を確認
         ・VPN 不要!
14.2 IAP の設定
# Cloud Run サービスに IAP を有効化
# (先にロードバランサを設定し、IAP はバックエンドサービスに適用)

# バックエンドサービスに IAP を有効化
gcloud compute backend-services update my-backend-service \
  --iap=enabled \
  --oauth2-client-id=CLIENT_ID \
  --oauth2-client-secret=CLIENT_SECRET \
  --global

# ユーザーにアクセスを許可
gcloud iap web add-iam-policy-binding \
  --resource-type=backend-services \
  --service=my-backend-service \
  --member="user:alice@example.com" \
  --role="roles/iap.httpsResourceAccessor"

# グループにアクセスを許可(推奨)
gcloud iap web add-iam-policy-binding \
  --resource-type=backend-services \
  --service=my-backend-service \
  --member="group:internal-users@example.com" \
  --role="roles/iap.httpsResourceAccessor"
14.3 IAP による SSH / TCP トンネリング

VPN なしで VM や GKE ノードに安全に接続できます。

# IAP トンネル経由で VM に SSH 接続
gcloud compute ssh VM_NAME \
  --zone=asia-northeast1-a \
  --tunnel-through-iap
# → 外部 IP なし・ファイアウォールで SSH を開放していない VM にも接続可能!

# IAP トンネル経由でローカルポートフォワーディング
# 例: Cloud SQL に直接接続(Auth Proxy の代替)
gcloud compute start-iap-tunnel VM_NAME 3306 \
  --local-host-port=localhost:3307 \
  --zone=asia-northeast1-a
# → localhost:3307 → IAP → VM の 3306 にトンネル

✅ ベストプラクティス: IAP

#ベストプラクティス
1VPN の代わりに IAP でゼロトラストアクセスを実現
2VM の外部 IP を削除し、IAP トンネル経由でのみ SSH を許可
3グループで IAP アクセスを管理(個人への付与は避ける)
4IAP + OS Login の組み合わせで多層防御

🔗 参考: https://cloud.google.com/iap/docs/concepts-overview

15 Cloud Armor(DDoS 防御 / WAF)

15.1 Cloud Armor の役割
【Cloud Armor が保護するレイヤ】

インターネット → Cloud Armor → Cloud Load Balancer → バックエンド
     ↑
  DDoS 攻撃・悪意のあるリクエストをここでブロック

【Cloud Armor でできること】

① L3/L4 DDoS 防御(自動)
   → ネットワーク層の大規模 DDoS を自動的に軽減

② L7 WAF(Web Application Firewall)
   → SQL インジェクション、XSS などの攻撃を検出・ブロック

③ IP ベースのアクセス制御
   → 特定の IP アドレスをブロック or 許可リスト

④ 地理情報ベースのアクセス制御
   → 特定の国からのアクセスをブロック

⑤ レート制限
   → 1つの IP からの大量リクエストを制限
15.2 Cloud Armor のセキュリティポリシー設定
# セキュリティポリシーを作成
gcloud compute security-policies create my-waf-policy \
  --description="WAF and DDoS protection for production"

# ===== WAF ルール(OWASP ルールセット)=====

# SQL インジェクション対策ルールを追加
gcloud compute security-policies rules create 1000 \
  --security-policy=my-waf-policy \
  --expression="evaluatePreconfiguredExpr('sqli-v33-stable')" \
  --action=deny-403 \
  --description="Block SQL injection attempts"

# XSS(クロスサイトスクリプティング)対策
gcloud compute security-policies rules create 1001 \
  --security-policy=my-waf-policy \
  --expression="evaluatePreconfiguredExpr('xss-v33-stable')" \
  --action=deny-403 \
  --description="Block XSS attempts"

# ===== IP ベースのルール =====

# 特定 IP をブロック
gcloud compute security-policies rules create 2000 \
  --security-policy=my-waf-policy \
  --src-ip-ranges=203.0.113.100/32 \
  --action=deny-403 \
  --description="Block known malicious IP"

# 特定の国からのアクセスをブロック
gcloud compute security-policies rules create 3000 \
  --security-policy=my-waf-policy \
  --expression="origin.region_code == 'XX'" \
  --action=deny-403 \
  --description="Block traffic from country XX"

# ===== レート制限 =====

# 1 IP あたり 100 リクエスト/60 秒に制限
gcloud compute security-policies rules create 4000 \
  --security-policy=my-waf-policy \
  --expression="true" \
  --action=rate-based-ban \
  --rate-limit-threshold-count=100 \
  --rate-limit-threshold-interval-sec=60 \
  --ban-duration-sec=600 \
  --conform-action=allow \
  --exceed-action=deny-429 \
  --description="Rate limiting per IP"

# ===== ポリシーを LB バックエンドサービスに適用 =====
gcloud compute backend-services update my-backend-service \
  --security-policy=my-waf-policy \
  --global
15.3 Cloud Armor のアダプティブ保護(Adaptive Protection)
【Adaptive Protection とは?】

Google の ML モデルがトラフィックを分析:
  ├── 通常のトラフィックパターンを学習
  ├── 異常なトラフィック(DDoS の可能性)を検出
  ├── ブロックルールを自動提案
  └── ワンクリックで適用可能

設定方法:
  gcloud compute security-policies update my-waf-policy \
    --enable-layer7-ddos-defense

→ 大規模 DDoS 攻撃時に自動的に保護ルールを適用

✅ ベストプラクティス: Cloud Armor

#ベストプラクティス
1すべての本番 ALB に Cloud Armor を設定
2OWASP Top 10 対策ルールを有効化(WAF ルールセット)
3レート制限で DDoS によるコスト暴走を防止
4Adaptive Protection を有効化して ML ベースの自動保護
5プリコンフィグ済みルールはまず `preview` モードで確認

🔗 参考: https://cloud.google.com/armor/docs/overview

16 Security Command Center (SCC)

16.1 Security Command Center とは?
【SCC の目的と位置づけ】

Security Command Center = Google Cloud のセキュリティ管理センター

機能:
  ├── 脆弱性の自動検出(VM の設定ミス、公開バケットなど)
  ├── 脅威の検出(不審な操作、マルウェアなど)
  ├── コンプライアンス状況の可視化(CIS Benchmark など)
  └── セキュリティスコアの提供

【SCC のサービス階層】

Standard(無料):
  ├── Security Health Analytics(設定ミスの検出)
  ├── Web Security Scanner(基本)
  └── Cloud Asset Inventory との統合

Premium(有料):
  ├── Event Threat Detection(リアルタイム脅威検出)
  ├── Container Threat Detection(GKE の脅威)
  ├── Virtual Machine Threat Detection(VM のマルウェア)
  └── Web Security Scanner(高度)
16.2 Security Health Analytics(設定ミスの検出)

SCC は以下のような設定ミスを自動的に検出してアラートを出します。

検出カテゴリ具体的な検出内容
IAM の問題プロジェクトオーナーが複数いる、allUsers への権限付与
ネットワーク設定0.0.0.0/0 からの SSH/RDP 許可、パブリックアクセス
Cloud Storageパブリックバケット、暗号化なし
Compute Engineシールドド VM 無効、OS Login 無効、外部 IP
GKE認証の弱い設定、特権コンテナ、古いバージョン
ログ関連監査ログ無効、ログ取り込み設定なし
SQL公開 IP、SSL 無効、バックアップなし
16.3 SCC の所見(Findings)の確認
# SCC の所見一覧を確認
gcloud scc findings list ORGANIZATION_ID \
  --source=ALL \
  --filter="state=ACTIVE AND severity=HIGH" \
  --format="table(name,category,severity,state)"

# 特定のプロジェクトの所見
gcloud scc findings list ORGANIZATION_ID \
  --source=ALL \
  --filter="resourceName:projects/my-project AND state=ACTIVE"

# 所見を解消済みとしてマーク
gcloud scc findings update FINDING_NAME \
  --source=SOURCE_ID \
  --organization=ORG_ID \
  --state=INACTIVE
16.4 Binary Authorization(コンテナの完全性保証)
【Binary Authorization の目的】

問題:
  「誰でもどんなコンテナイメージでも GKE にデプロイできる」
  → サプライチェーン攻撃に弱い
  → テストしていないイメージが本番に入るリスク

解決策: Binary Authorization

CI/CD パイプライン:
  コードビルド → テスト合格 → 承認済み署名をイメージに付与

GKE デプロイ時:
  Binary Authorization がポリシーを確認
    ├── 有効な署名あり → デプロイ許可 ✅
    └── 署名なし / 無効な署名 → デプロイ拒否 ❌ + アラート

【防げる攻撃】
  ├── 承認されていないイメージの誤デプロイ
  ├── サプライチェーン攻撃(npm パッケージへの悪意のあるコード)
  └── 開発者による手動デプロイ(CI/CD をバイパス)
# Binary Authorization を GKE クラスタで有効化
gcloud container clusters update my-cluster \
  --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
  --region=asia-northeast1

# 証明者(Attestor)の作成
# 証明者 = 「このイメージを承認できる人/サービス」の定義
gcloud container binauthz attestors create my-attestor \
  --attestation-authority-note=projects/PROJECT/notes/my-note \
  --attestation-authority-note-project=PROJECT

# ポリシーの設定(すべてのイメージに署名を要求)
cat > policy.yaml <<EOF
defaultAdmissionRule:
  evaluationMode: REQUIRE_ATTESTATION
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
  requireAttestationsBy:
    - projects/PROJECT/attestors/my-attestor
globalPolicyEvaluationMode: ENABLE
EOF

gcloud container binauthz policy import policy.yaml
16.5 ファイアウォールルールのセキュリティ設計

ファイアウォール設計の原則

【デフォルト拒否(Default Deny)の原則】

ネットワークのデフォルト状態:
  すべてのトラフィックを拒否
    ↓ 明示的に許可したもののみ通過

GCP のデフォルトファイアウォール:
  ├── INGRESS: すべて拒否(デフォルト)
  └── EGRESS: すべて許可(デフォルト)
      ↑ 本番環境では Egress も制限することを検討

安全なファイアウォール設計パターン

# ===== 推奨パターン: タグベースのルール =====

# Web サーバーへの HTTP/HTTPS のみ許可
gcloud compute firewall-rules create allow-http-https-to-web \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=1000 \
  --action=ALLOW \
  --rules=tcp:80,tcp:443 \
  --target-tags=web-server \        # web-server タグを持つ VM のみ
  --source-ranges=0.0.0.0/0 \
  --description="Allow HTTP/HTTPS traffic to web servers"

# App サーバーへはロードバランサからのみ許可
gcloud compute firewall-rules create allow-app-from-lb \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=1000 \
  --action=ALLOW \
  --rules=tcp:8080 \
  --target-tags=app-server \
  --source-tags=web-server          # web-server タグからのみ

# DB サーバーへはアプリサーバーからのみ許可
gcloud compute firewall-rules create allow-db-from-app \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=1000 \
  --action=ALLOW \
  --rules=tcp:5432 \
  --target-tags=db-server \
  --source-tags=app-server          # app-server タグからのみ

# SSH は IAP からのみ許可(外部からの直接 SSH を完全ブロック)
gcloud compute firewall-rules create allow-ssh-iap \
  --network=prod-vpc \
  --direction=INGRESS \
  --priority=1000 \
  --action=ALLOW \
  --rules=tcp:22 \
  --target-tags=ssh-allowed \
  --source-ranges=35.235.240.0/20   # IAP の IP レンジ

❌ やってはいけないファイアウォール設定

# ❌ 危険: SSH を全世界に公開
gcloud compute firewall-rules create bad-ssh-rule \
  --action=ALLOW \
  --rules=tcp:22 \
  --source-ranges=0.0.0.0/0   # すべての IP から SSH 接続可能!

# ❌ 危険: タグなし(全 VM に適用)
gcloud compute firewall-rules create bad-rule \
  --action=ALLOW \
  --rules=tcp:3389 \           # RDP を全 VM に公開
  --source-ranges=0.0.0.0/0

# ✅ 修正: IAP からの SSH のみ許可、特定タグの VM のみ
gcloud compute firewall-rules create good-ssh-rule \
  --action=ALLOW \
  --rules=tcp:22 \
  --source-ranges=35.235.240.0/20 \  # IAP の IP レンジ
  --target-tags=bastion-only          # 限定された VM のみ
16.6 OS Login と多層防御(再確認)

Domain 4 として改めて OS Login の重要性を整理します。

【OS Login の多層防御効果】

層1: IAM(誰が SSH できるか)
  roles/compute.osLogin        → SSH 接続(sudo なし)
  roles/compute.osAdminLogin   → SSH 接続(sudo あり)
  → IAM で制御されるため、退職者は即時アクセス不可

層2: OS Login 自体の設定
  enable-oslogin=TRUE          → OS Login 有効化
  enable-oslogin-2fa=TRUE      → 2 要素認証必須

層3: ファイアウォールルール
  SSH は IAP からのみ許可(35.235.240.0/20)
  → 外部 IP からの直接アクセスを完全ブロック

層4: 組織ポリシー(強制適用)
  constraints/compute.requireOsLogin
  → 全 VM で OS Login を強制(設定し忘れ防止)

→ この 4 層すべてを通過しないと VM にアクセスできない!

17 Domain 4 試験対策まとめ

17.1 試験頻出パターン
【パターン①: IAM ロールの選択問題】
「フロントエンドエンジニアは Cloud Run へのデプロイと
 Artifact Registry からのイメージプルができる必要がある。
 最小権限のロールはどれか?」

考え方:
  Step 1: 必要な操作を特定
    ├── Cloud Run のデプロイ → roles/run.developer
    └── Artifact Registry の読み取り → roles/artifactregistry.reader

  Step 2: 基本ロールは選ばない
    ❌ roles/editor(過剰権限)
    ✅ roles/run.developer + roles/artifactregistry.reader

【よくある誤答パターン】
  ❌ roles/owner(問題外の過剰権限)
  ❌ roles/editor(多くの不要な権限が含まれる)
  ✅ 事前定義ロールの組み合わせ または カスタムロール

【パターン②: SA キーの代替手法の問題】
「GitHub Actions から GCP のリソースを操作したい。
 最もセキュアな方法はどれか?」

正解: Workload Identity Federation
  → GitHub OIDC トークンを GCP トークンに交換
  → SA キーを GitHub に保存しない

【パターン③: シークレット管理の問題】
「Cloud Run アプリがデータベースのパスワードを必要とする。
 最もセキュアな管理方法はどれか?」

正解:
  Secret Manager にパスワードを保存
  Cloud Run の --set-secrets フラグで環境変数として注入
  SA に roles/secretmanager.secretAccessor を付与

【パターン④: ネットワークセキュリティの問題】
「本番環境の VM への SSH アクセスをセキュアにしたい。
 外部 IP を持たない VM にも接続できるようにしたい。」

正解: IAP トンネル + OS Login
17.2 セキュリティサービスの役割マップ
【攻撃経路別のセキュリティサービス】

① 認証・アクセス制御
   IAM: 誰が何をできるか
   OS Login: VM への SSH アクセス
   IAP: VPN 不要のゼロトラストアクセス
   Binary Authorization: 承認済みコンテナのみデプロイ

② シークレット・データ保護
   Secret Manager: パスワード・APIキーの安全な管理
   Cloud KMS: 暗号化キーの管理・CMEK

③ ネットワーク防御
   Cloud Armor: DDoS・WAF(外部からの攻撃)
   VPC Firewall: ネットワーク層のアクセス制御
   VPC Service Controls: データ持ち出し防止

④ 可視化・検出
   Security Command Center: 設定ミス・脅威の検出
   Cloud Audit Logs: 誰が何をしたかの記録
   Cloud Asset Inventory: リソース・IAM の全体把握
17.3 Domain 4 全体のベストプラクティス一覧
カテゴリベストプラクティス
IAM 一般最小権限の原則を徹底(事前定義ロール優先)
IAM 一般グループにロールを付与(個人への直接付与は避ける)
IAM 一般定期的な権限レビュー(Policy Recommender 活用)
SA 管理SA JSON キーの生成を組織ポリシーで禁止
SA 管理CI/CD は Workload Identity Federation を使用
SA 管理ローカル開発は ADC(gcloud auth application-default login)
SA 管理特権操作は SA Impersonation または PAM
シークレットSecret Manager でシークレットを一元管理
シークレットコード・設定ファイルへのハードコードを根絶
暗号化規制データには CMEK(Cloud KMS)を適用
ネットワークVM の外部 IP を削除し IAP 経由でアクセス
ネットワークOS Login + 2FA を組織ポリシーで強制
ネットワークすべての本番 ALB に Cloud Armor を設定
コンテナBinary Authorization で承認済みイメージのみデプロイ
可視化SCC で設定ミスを定期確認・修正
可視化データアクセス監査ログを有効化(機密データ)
📝 Domain 4 学習の最終アドバイス

必ず押さえるべき 5 つの核心:

  1. SA JSON キーは使わない → Workload Identity / ADC / Impersonation
  2. 基本ロール(Editor/Owner)は本番禁止 → 事前定義ロールを使う
  3. Secret Manager でシークレットを管理(ハードコード・平文禁止)
  4. IAP + OS Login で VM への SSH を多層防御(外部 IP 不要)
  5. Cloud Armor ですべての本番 ALB を DDoS/WAF から保護

18 包括的調査および実践的アーキテクチャガイド

18.1 クラウドインフラストラクチャにおけるセキュリティの重要性

現代のクラウドインフラストラクチャ設計において、強固なセキュリティ基盤の確立と厳格なアクセス制御の実装は、システムの可用性とデータの機密性を担保するための最重要課題です。ゼロトラストアーキテクチャの原則に基づき、最小特権の原則を実際のシステムに適用する実践的な能力が問われます。

18.2 IAM権限とロールの構造的分類

IAMにおける最小のアクセス制御単位は「権限(Permissions)」であり、通常 service.resource.verb の形式(例:compute.instances.start)で表現されます。これらを論理的に束ねた「ロール(Roles)」をプリンシパルに割り当てます。

【ロールの種類と特徴】

基本ロール (Basic Roles):
  「オーナー」「編集者」「閲覧者」。広範なアクセス権を提供。
  本番環境での使用はセキュリティ上の観点から強く非推奨。

事前定義ロール (Predefined Roles):
  Googleが保守。特定のサービスやジョブ機能に特化した細粒度の権限を提供。
  本番環境における標準的かつ最も推奨される選択肢。

カスタムロール (Custom Roles):
  組織独自の要件に適合させるため、任意の権限を組み合わせて定義。
  編集権限を持つプリンシパルに対する厳格な制限が必要(特権昇格リスク)。
18.3 IAMポリシーの動的管理とAPIの失敗に対する指数バックオフ戦略
【Read-Modify-Write パターン】

大規模な変更をREST APIやクライアントライブラリを通じて実行する場合:
1. Read: getIamPolicy() で現在の許可ポリシーと ETag を取得
2. Modify: JSONオブジェクトに対してプリンシパルの追加・ロール変更を適用
3. Write: setIamPolicy() で送信し、サーバー側で ETag を比較

【Thundering Herd 問題の回避】
IAM APIリクエストが失敗した場合、「ジッター(揺らぎ)を伴う切り捨て指数バックオフ」を適用。
待機時間 = min((2^n + random-fraction), maximum-backoff)
※ 409 (Conflict) エラーの場合は、単なる再試行ではなく、getIamPolicy() からやり直す。
18.4 サービスアカウントキーの脆弱性と最新の組織ポリシー
2024年のセキュリティ動向レポートによると、認証情報の脆弱性がクラウド侵害の約76%を占めます。
Google Cloudは2024年5月以降、デフォルトで iam.disableServiceAccountKeyCreation の強力な組織ポリシーを適用しています。

キーを使用せざるを得ない環境での運用ルール:
・一時ディレクトリや公開された共有フォルダに絶対に放置しない。
・ユーザー間で電子メールやチャットツールを通じて直接受け渡ししない。
・GitHubやGitLabなどのソースコードリポジトリにキーを含めてコミットしない。
・アプリケーションの実行バイナリの内部にキーをハードコードして埋め込まない。
・定期的なローテーションポリシーを確立し自動化する。
18.5 Cloud Audit Logsによる監視体制とコンプライアンスの確保
【監査ログの4つのカテゴリ】

管理アクティビティ監査ログ (Admin Activity):
  リソースの構成変更を記録。強制的に有効(無料)、400日間保存。

データアクセス監査ログ (Data Access):
  ユーザーデータに対する作成・変更・読み取りを記録。
  デフォルト無効。有効化時は膨大なボリュームに注意。
  「免除されたプリンシパル」を設定してノイズを削減することが重要。

システムイベント監査ログ (System Event):
  Google Cloudシステム側が自律的に実行したイベント。常に有効(無料)。

ポリシー拒否監査ログ (Policy Denied):
  セキュリティポリシー違反や拒否されたアクセス試行を記録。デフォルト有効。
19

参考資料(References)

公式ドキュメントおよび信頼性の高い学習リソース

19.1 公式ドキュメント・学習リソース一覧
本ドメインの解説にあたって参照したソースおよび、さらに深く学習するためのリソースです。
公式試験情報ページ
Google Cloud IAM の概要
IAM ロールと権限の詳細
IAM の安全な利用方法
サービスアカウント運用のベストプラクティス
外部 ID との連携による鍵なし認証
GKE アプリケーションのセキュアな認証
シークレット管理サービス
鍵管理システム (CMEK 等)
データの境界保護と持ち出し防止
ゼロトラストアクセスの実現
DDoS 防御および WAF
脅威検出と脆弱性管理
API 操作の監査ログ記録
デプロイ時ポリシー強制
ジャストインタイムの特権アクセス
その他、詳細な技術解説ブログ・コミュニティリソース:
dev.to による IAM の役割解説
StrongDM によるロール比較
CloudOptimo によるリソース階層の解説
OneUptime による短期トークンの実装解説
Binadox による FinOps/Security 解説