はじめに
GMOコネクトの永田です。
「セキュリティガイドラインに沿った設定、全部確認できてる?」
こう聞かれて、ドキッとした経験はありませんか?
ガイドライン・チェックリスト・マニュアルに沿ってブラウザをポチポチ操作して確認するのは、正直かなり面倒です(私は結構あります😇)。しかも、リグレッション試験や複数環境での確認となると、同じ手順を何度も繰り返すことに...
「この手動確認、どこまで自動化できる?」
最近の技術進歩により、Playwright codegenとLLMを組み合わせることで、かなり現実的に自動化できそうだったので試してみました!
本記事では、GitLabのセキュリティガイドライン準拠チェックを題材に、以下を実践します:
- Playwright codegenで手動操作を記録し、E2Eテストコードの叩き台を自動生成
- GitHub Copilot AgentでAssert内容を調整し、実用的なテストコードに仕上げる
最初にまとめ
Playwright codegenとLLMを組み合わせることで、ガイドラインに沿ったブラウザ操作の確認を効率的に自動化できました。
実現できたこと:
- 手動のブラウザ操作を記録してE2Eテストコードの叩き台を自動生成
- GitHub Copilot AgentでAssert内容やコードの品質を改善
- GitLabのセキュリティガイドライン準拠チェックを自動実行
重要なポイント:
- ガイドラインに「確認手順」と「確認観点」が整理されていることが前提
- codegenで生成されたコードは、Locatorの選択やAssert内容の調整が必要
- リグレッション試験など、同一手順を繰り返し実行する場面で特に効果的
活用シーン:
リグレッション試験、複数環境での動作確認、複数ブラウザでの互換性確認など、手動で同一手順を繰り返し実施しているケースに最適です。
試した対象システム(=GitLab)について
今回はGitLabで試しました。
理由としては、以下です。
- docker composeでローカル検証環境がさくっと作れる
- とても重要: ガイドラインで手順と観点がちゃんと整理されている
お手元の環境で再現しやすいよう、要点のみ以下にまとめます。
docker composeでのGitLab起動〜ログイン確認
docker compose yamlの作成〜起動
最低限の内容でgitlabを起動するyamlを作成します。
本記事ではGitLab CE 18.7で検証しています。
services:
web:
image: 'gitlab/gitlab-ce:latest'
restart: always
hostname: '127.0.0.1'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://127.0.0.1:9010'
gitlab_rails['gitlab_shell_ssh_port'] = 2022
ports:
- '9010:9010'
- '2022:22'
volumes:
- './volume/config:/etc/gitlab'
- './volume/logs:/var/log/gitlab'
- './volume/data:/var/opt/gitlab'
その後、docker compose up で起動します。
初回起動時、Gitlabで色々と初期化処理をするため、Gitlabログを見て初期化が終わっていそうなのを確認してください。(そこそこ時間がかかります)
GitLabへAdmin権限でログイン
ブラウザで http://127.0.0.1:9010/ を開き、ID/Passwordを入力しトップページが表示されれば準備完了です。
- ID:
root - Password:
volume/config/initial_root_passwordからコピー
初期パスワードはdocker composeのボリュームに設定した ./volume/config:/etc/gitlab 配下に生成されます。なお、該当ファイルにも記載があるとおり24時間で消えるのでご注意ください。
# NOTE: This file is automatically deleted after 24 hours on the next reconfigure run.
利用したGitLabセキュリティガイドライン
GitLabはセキュア設定(hardening)が丁寧にまとめられています。
具体的には以下の観点がちゃんと書かれています。( とても重要 )
- 確認手順
- 確認観点
今回はこのうち優先度が高いと思われる3件をピックアップし、さらに1件で具体的に試します。
NotebookLMに上記のURLをソースに入れ、以下のpromptでピックアップと内容の整理をしてもらいます。
(NotebookLMはソースの情報を厳密に参照するため、誤情報が少ないです)
GitLab Self-Managedに対して、以下を表形式でまとめる。
特に優先度の高い3点をピックアップ。
### 表の内容
- 概要
- 確認手順
- 確認観点
- 重要と判断した理由
### 優先度の考え方
- 確認手順、確認観点が明確なものは、優先度が高い
- 設定によりセキュリティ向上の意義が大きいものは、優先度が高い
まとめてくれました! ざっとみた感じ、良さそうですね。
GitLab Self-Managed セキュリティ設定(優先度・高)
| 項目 | 概要 | 確認手順 | 確認観点 | 重要と判断した理由 |
|---|---|---|---|---|
| 1. 多要素認証と管理者モードの強制 | 全ユーザーへの2要素認証(2FA)適用および、管理者操作時の追加認証(Admin Mode)を有効化する。 |
Admin > Settings > General > Sign-in restrictions に移動する。 |
・Two-factor authentication (2FA) にチェックが入っているか。・ Two-factor grace period(猶予期間)が48時間(デフォルト)より短く設定されているか。・ Enable admin mode が有効化されているか。 |
パスワード漏洩時の不正アクセスを防ぐ基本対策であると同時に、Admin Modeにより管理者が重要な操作を行う際に再認証(2FA含む)を求めることで、セッションハイジャック等の攻撃から特権操作を保護できるため。 |
| 2. ユーザー登録の制限 | 誰でもアカウントを作成できる状態を防ぎ、メール確認やドメイン制限を厳格化する。 |
Admin > Settings > General > Sign-up restrictions に移動する。 |
・Sign-up enabled のチェックが外されているか(招待制にする場合)。・ Email confirmation settings が Hard に設定されているか。・ Allowed domains for sign-ups に組織のドメインのみが指定されているか。 |
Self-Managed版がインターネットからアクセス可能な場合、登録制限がないと第三者が自由にアカウントを作成し、内部情報へアクセスを試みるリスクがあるため、侵入経路を塞ぐ上で最も効果的な設定の一つです。 |
| 3. 公開範囲(Visibility)のデフォルト制限 | 新規作成されるプロジェクトやグループが、意図せず「公開(Public)」になることを防ぐ。 |
Admin > Settings > General > Visibility and access control に移動する。 |
・Default project visibility が Private に設定されているか。・ Default group visibility が Private に設定されているか。 |
ユーザーの操作ミス(ヒューマンエラー)による情報漏洩を防ぐ「安全なデフォルト(Secure by Default)」を実現するためです。後から変更可能ですが、初期設定を非公開にしておくことで偶発的なデータ流出を確実に防止できます。 |
この後、実際に操作するので、手動で設定画面を見ておいてください。
では早速試していきます!
Playwright codegenで、手動操作の記録とLLMでの修正
では、手動操作した内容をどこまで自動でテストコード化できるか?を試していきます。
E2Eテストの自動化でネックになるのは、やはり自動テストコードの作成工数です。
「手動でぱぱっとブラウザ操作して目視で確認する方が手軽だよ」という話は昔からよく聞きますが、手動操作の結果が自動テストコードの叩き台に使える となるとどうでしょうか?
ちょっと自動テストの導入ハードルが下がりますよね😊
ということで試します。
Playwright codegenでテストコードの記録
Playwrightやcodegen自体の説明や詳細なセットアップ手順は以下の記事などを参照してください。
以下、手順の要点のみ書いておきます。(Nodejsはv22を利用)
$ npm init playwright@latest # Playwrightのインストールと初期化。今回は全てデフォルト値
$ npx playwright codegen http://127.0.0.1:9010 # codegenでローカルGitLabへアクセス
このような画面がでればcodegenの起動完了です。
では、2. ユーザー登録の制限 の確認手順の沿って、普通のブラウザと同じように操作していきます。
※ 1. 多要素認証と管理者モードの強制 の設定を入れると画面遷移が変わったり、MFAにより自動ログインが困難になる(回避手段は別途あり)ため、2のほうで試します。
「Admin > Settings > General > Sign-up restrictions に移動する。」まで操作した結果がこちらです。(Passwordはマスクしています)
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://127.0.0.1:9010/users/sign_in');
await page.getByTestId('username-field').click();
await page.getByTestId('username-field').fill('root');
await page.getByTestId('password-field').click();
await page.getByTestId('password-field').fill('********');
await page.getByTestId('sign-in-button').click();
await page.getByTestId('topbar-admin-link').click();
await page.getByRole('button', { name: 'Settings' }).hover();
await page.getByRole('link', { name: 'General' }).click();
await page.getByRole('button', { name: 'Expand Sign-up restrictions' }).click();
なお、Settings > General はマウスオーバーで表示されるメニューのため、注意が必要です。
この場合Settingsを右クリックして表示されるPlaywrightのaction Hover を明示的に選択しないと、Playwright Inspectorに記録されません。
次に確認観点(=Assert)をいれていきます。それぞれ以下の方針です。
- 共通
- Playwright Inspectorでは現在の状態が記録されるため、必要に応じ事前に理想的な設定状態へ更新しておいてくのもありです
- Playwright InspectorはLocatorの特定(操作対象のオブジェクトの特定)のみに割り切る、という使い方もあり
- チェックボックス、ラジオボタン
- codegenのassert value を利用
- テキストボックス(InputText)
- codegenのassert value を利用
- テキストボックスの数値(InputText)
- codegenのassert value を利用
- 「以下」「未満」のような指定まではcodegenではできないので、条件判定は後でソース修正
Inspectorに追加されたコードは以下です。
- コメントは説明のために手で追記しています
- この後のLLMでのテストケースの自動修正を試すため、検証用にあえてNG状態(理想的ではない設定状態)で記録しているため、コメントとAssertがずれています
// ・Sign-up enabled のチェックが外されているか(招待制にする場合)。
await expect(page.getByRole('checkbox', { name: 'Sign-up enabled Any user that' })).toBeChecked();
// ・Email confirmation settings が Hard に設定されているか。
await expect(page.getByRole('radio', { name: 'Hard Send a confirmation' })).not.toBeChecked();
// ・Allowed domains for sign-ups に組織のドメインのみが指定されているか。
await expect(page.getByRole('group', { name: 'Allowed domains for sign-ups' }).getByPlaceholder('domain.com')).toBeEmpty();
GitHub Copilot Agentでテストコードの修正
Inspectorの内容を tests/test-signup.spec.ts などのファイルとして保存して修正します。(GitHub Copilot AgentでClaude Haiku 4.5利用)
利用したpromptの例は以下です、
tests/test-signup.spec.ts は、gitlab_hardening.md の **2. ユーザー登録の制限** のテストコード。
tests/test-signup.spec.ts に対し、以下の修正を実施。
- Playwrightのテストコードから冗長な記載を削除
- fillの前のclick, press Eisuなど
- Markdownの表の「項目」「概要」「確認手順」と「確認観点」を、テストコードにコメントとして追記
- AssertをMarkdownの記載に合わせて修正
- 「組織のドメイン」は、「gmo-connect.jp」とする
- Assertは expect.soft のSoft Assertionとする
expect.soft はAssert内容次第ですが、今回は全ての設定が独立しているので1件NGでテストを中断せず、他のAssertも実行して全ての確認結果を得られるようにしたいので入れています。(最終的には、NGがあればテストは失敗となります)
softにするかは、Assertの内容によって調整してください。
Assertもいい感じに直してくれていますね😊
出来ました! 出来上がったテストコードの全体はこちらです。
import { test, expect } from '@playwright/test';
test('ユーザー登録の制限', async ({ page }) => {
// 項目: 2. ユーザー登録の制限
// 概要: 誰でもアカウントを作成できる状態を防ぎ、メール確認やドメイン制限を厳格化する。
// 確認手順: Admin > Settings > General > Sign-up restrictions に移動する。
// 確認観点:
// - Sign-up enabled のチェックが外されているか(招待制にする場合)。
// - Email confirmation settings が Hard に設定されているか。
// - Allowed domains for sign-ups に組織のドメインのみが指定されているか。
await page.goto('http://127.0.0.1:9010/users/sign_in');
await page.getByTestId('username-field').fill('root');
await page.getByTestId('password-field').fill('*******');
await page.getByTestId('sign-in-button').click();
await page.getByTestId('topbar-admin-link').click();
await page.getByRole('button', { name: 'Settings' }).hover();
await page.getByRole('link', { name: 'General' }).click();
await page.getByRole('button', { name: 'Expand Sign-up restrictions' }).click();
// 確認: Sign-up enabled が無効化されている
await expect.soft(page.getByRole('checkbox', { name: 'Sign-up enabled Any user that' })).not.toBeChecked();
// 確認: Email confirmation settings が Hard に設定されている
await expect.soft(page.getByRole('radio', { name: 'Hard Send a confirmation' })).toBeChecked();
// 確認: Allowed domains for sign-ups に gmo-connect.jp が設定されている
await expect.soft(page.getByRole('group', { name: 'Allowed domains for sign-ups' }).getByPlaceholder('domain.com')).toHaveValue('gmo-connect.jp');
});
注意: 上記はサンプルコードです。実際の運用では、パスワードや認証情報をソースコードに直接埋め込まず、環境変数やシークレット管理ツールを利用してください。
Playwrightテストコードの実行例
早速実行してみます。(VSCode Extension経由でも良いです)
設定次第ですがデフォルトだと複数ブラウザで実行するので、今回は検証用にchromiumのみとします。
$ npx playwright test test-signup.spec.ts --project=chromium
無事にpassすると npx playwright show-report で実行結果がみれます。
逆に3件ともNGになる設定で試してみましょう。
NGだと自動でエラーレポートがブラウザに表示されます。
Expected: not checked
Received: checked
のように期待値と異なっていることが分かります。
Playwright codegenを使ってみての所感
自分でPlaywrightのソースコードをほぼ記載することなく、E2Eテストコードがさくっと実装できちゃうのはかなり便利ですね!
特に既存のテスト項目やガイドラインなどで、確認手順・確認観点がちゃんと整理・メンテナンスされているが(とても重要(3回目ぐらい))、リグレッション試験・複数試験環境・複数ブラウザなどによって、手動で同一手順を実施しているようなAsIsの自動化には、かなり威力を発揮しそうです。
(ToBeでももちろんできますが、バグか仕様か手順誤りかとかの切り分け作業が入ります)
ただし、codegenで生成されたコードには以下のような制約があるため、生成後の確認や調整は必要です:
- Locatorの選択: UI変更に脆弱なセレクタが生成される場合がある
- 冗長なコード: 不必要なclickやpressなどが含まれることがある、認証などの処理の共通化がない
- Assertの調整: 確認観点に合わせたAssert内容の修正が必要
ここまででもかなりE2Eテストコード作成が楽になっていますが、「codegenでブラウザ操作するのも面倒!」というのもあるので、今後は「GitHub Copilot + Playwright MCPで、自然言語での操作+確認の自動化と、その結果のPlaywrightコード化」を試してみたいと思います。
(最近の生成AIの進化によって、実現性がかなり現実的になっていると思われます)
まとめ
Playwright codegenとLLMを組み合わせることで、ガイドラインに沿ったブラウザ操作の確認を効率的に自動化できました。
実現できたこと:
- 手動のブラウザ操作を記録してE2Eテストコードの叩き台を自動生成
- GitHub Copilot AgentでAssert内容やコードの品質を改善
- GitLabのセキュリティガイドライン準拠チェックを自動実行
重要なポイント:
- ガイドラインに「確認手順」と「確認観点」が整理されていることが前提
- codegenで生成されたコードは、Locatorの選択やAssert内容の調整が必要
- リグレッション試験など、同一手順を繰り返し実行する場面で特に効果的
活用シーン:
リグレッション試験、複数環境での動作確認、複数ブラウザでの互換性確認など、手動で同一手順を繰り返し実施しているケースに最適です。
最後に、GMOコネクトではサービス開発支援や技術支援をはじめ、幅広い支援を行っておりますので、何かありましたらお気軽にお問合せください。





