🎭

[Playwright] CI/CDで社内環境に対してGitHub ActionsのIPを許可する in GCP編

に公開
2026/09/29

🌱 はじめに

この記事では、社内で初めて Playwright を CI/CD に組み込んだ時に苦労した点と対策を解説します。

ワークフローの全体像と、各ステップで苦労した点の対応は次のとおりです。

GitHub ActionsのランナーがWorkload Identity連携で認証し、Cloud ArmorにIPの許可ルールを追加してPlaywrightのテストを実行し、最後にルールを削除する流れを表した図

実際に使った yaml
name: Playwright Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  e2e-tests:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: "projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider"
          service_account: "example@project.iam.gserviceaccount.com"

      # GitHub ActionsのIPは可変のため、GitHub Actionsのアクセスを許可するルールをWAFに追加する
      - name: Allow Security-Policy
        run: |
          IP=$(curl -f -s http://whatismyip.akamai.com)
          echo "The IP address is: $IP"
          gcloud compute security-policies rules create NUMBER --action allow --security-policy XXXXX --description "GitHub Actions IP" --src-ip-ranges ${IP}

      - uses: actions/setup-node@v4
        with:
          node-version: 18
          cache: npm
          cache-dependency-path: package-lock.json
      - name: Install dependencies
        run: npm ci

      - name: Install Playwright Browsers
        run: npx playwright install --with-deps

      # WAFのルールが適用に時間が必要なため待機する
      - name: Wait for WAF to apply (up to 3 minutes)
        run: |
          sleep 90
          for i in {1..3}; do
            if curl -f https://example.com; then
              echo "Success"
              break
            fi
            echo "Retrying in 30 seconds..."
            sleep 30
          done

      # テスト実行
      - name: Run Playwright tests
        run: npx playwright test

      # 先ほど追加したWAFの許可ルールを削除する
      - name: Delete Security-Policy
        if: ${{ always() }}
        run: |
          gcloud compute security-policies rules delete NUMBER --security-policy XXXXX --quiet

🌱 1. google-github-actions/auth のエラーが解消できない

このエラーを解消するのに大変時間を要しました。

上記のエラーを解消する時に試したことを列挙します。
お困りの方の参考になれば幸いです。

1. id-tokenの書き込み権限を許可する

当時 id-tokenの書き込み権限を許可しても上記のエラーは解消しませんでした。
(id-token: write は OIDC 認証に必須の設定です。ただし、fork からの PR ではこれだけでは足りませんでした)

jobs:
  e2e-tests:
    runs-on: ubuntu-latest
+    # Add "id-token" with the intended permissions.
+    permissions:
+      id-token: write
+      contents: read
    steps:

2. google-github-actions/authの書き方が正しいか

下記項目について確認しました。

  • google-github-actions/authの ver
  • workload_identity_providerの値
  • service_accountの値
- uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: "projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider"
    service_account: "example@project.iam.gserviceaccount.com"

3. 対象リポジトリのSettingsが適切か

下記項目にチェックが付いているのかを確認しました。

  • Fork pull request workflows > Run workflows from fork pull requests
  • Workflow permissions > Read and write permissions

gihub-setting

4. service_accountを CLI から作成する

当初は GUI からservice_accountを作成しておりましたが、CLIで実行すると必要な設定ができるみたいです。
Workload Identity Federation とサービスアカウントの設定手順は、下記の README(Setup)が参考になります。

※インフラ担当の方に依頼したので詳細はよく分かりません。

5. google-github-actions/authの前にactions/checkoutを追加する

下記サイトを参考にactions/checkoutを追加しましたが、解消には繋がりませんでした。

+ - uses: actions/checkout@v4
  - uses: google-github-actions/auth@v2
    with:
      workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
      service_account: 'example@project.iam.gserviceaccount.com'

6. Fork 先から実行するのではなく、Fork 元から実行する

この対応でgoogle-github-actions/authのエラーが解消されました。

fork からの pull_request イベントでは、GITHUB_TOKEN が読み取り専用になり、id-token: write も付与されません。
そのため、ACTIONS_ID_TOKEN_REQUEST_TOKEN などが注入されず、OIDC による認証ができなかったのが原因です。
(pull_request_target を使って回避する方法は、fork のコードに権限を渡すことになりセキュリティ上危険なので避けてください)

🌱 2. WAF が有効になるのに時間がかかる

当たり前の話かもしれませんが、WAF は即座に反映されません。
そのため、WAF 設定が有効になるのを待つ必要があります。

方法はいくつかあると思いますが、自分は下記コードを yaml に追加しました。
※ 大体 1-3 分の間で有効になることを観測しております。

# WAFのルールが適用に時間が必要なため待機する
- name: Wait for WAF to apply (up to 3 minutes)
  run: |
    sleep 90
    for i in {1..3}; do
      if curl -f https://example.com; then
        echo "Success"
        break
      fi
      echo "Retrying in 30 seconds..."
      sleep 30
    done

🌱 3. Job ごとで GitHub Actions の IP が変わる

当初は各 Job を管理しやすいように細かく分けましたが、Job ごとに IP が変わってしまいました。
そのため、allow-security-policyで許可した IP 以外でPlaywrightが実行されて403 Forbiddenが表示されて困りました。
しかし、下記サイトを読み各 Job を 1 つにまとめ403 Forbiddenを解消しました。

Job を分けた場合と、1つにまとめた場合の違いは次のとおりです。

Jobを3つに分けるとランナーのIPが変わって403になり、1つのJobにまとめると同じIPで実行されて成功することを比べた図

下記のようにyamlを変更しました。

jobs:
-  allow-security-policy:                                  
-    runs-on: ubuntu-latest
-    steps:
-    # --- 以下略 ---
-
-  run-playwright-tests
-    runs-on: ubuntu-latest
-    steps:
-    # --- 以下略 ---
-
-  delete-security-policy
-    runs-on: ubuntu-latest
-    steps:
-    # --- 以下略 ---
+  e2e-tests:
+    runs-on: ubuntu-latest
+    steps:
+    # --- 以下略 ---

🌱 4. 海外アクセスブロックよりも優先度を高くする

既存の WAF に、国外からのアクセスを拒否するルールがありました。
GitHub Actions のランナーは海外の IP から接続するため、上記のルールよりも優先度を高くする必要があります。
Cloud Armor では priority の数値が小さいほど優先されるため、国外拒否ルールより小さい値(NUMBER)を指定します。

🌱 5. Playwright のために追加した WAF のルールは必ず削除する

試行錯誤中は、処理が最後まで進まないケースがあります。
その際、前回の WAF のルールが残ったままになり、次回実行時に下記のエラーが発生しておりました。
※ そのたびにインフラ担当の方に削除連絡をしておりました。

if: ${{ always() }}を追加し、テストの失敗/キャンセル/処理の失敗でも削除処理を実行する必要があります。
(ランナーの強制終了などでは実行されない場合もあるため、ルールが残ったときは手動で削除します)

    # 先ほど追加したWAFの許可ルールを削除する
    - name: Delete Security-Policy
+      if: ${{ always() }}
      run: |
        gcloud compute security-policies rules delete NUMBER --security-policy XXXXX --quiet

🌱 6. 連続で CI/CD はできない

WAF の優先度を固定の数値にしているため、priorityの重複エラーが発生します。
再度確認したい場合は、前回の処理が終わるのを待つ or キャンセルする必要があります。

さらに、並行して実行すると、後から始まった実行は作成に失敗しますが、always() の削除処理は実行されるため、先に実行中のルールを消してしまいます。
ワークフローに concurrency を設定して直列化する、作成に成功したときだけ削除する(if: ${{ always() && steps.<作成ステップのid>.outcome == 'success' }})などの対策を検討してください。

GitHubで編集を提案

Discussion