セキュリティのないツールを保護する
PrometheusのダッシュボードやプライベートWiki、カスタムの管理スクリプトを立ち上げたものの、セキュリティ機能が全く備わっていないことに気づく。そんな経験は誰にでもあるでしょう。これらをローカルネットワーク上で公開したままにするのはギャンブルですし、パスワードなしで公開ウェブにさらすのは、データ漏洩を招くようなものです。
壊れやすいBasic認証を無理やり構築する代わりに、OAuth2 Proxyを使うべきです。これはプロフェッショナル級のゲートキーパーとして機能します。サービスの前面に配置され、ユーザーが1バイトのデータでも閲覧する前に、Google、GitHub、またはOpenID Connect経由でのログインを強制します。
クイックスタート:5分でアプリを保護する
実際に動作を確認する最も早い方法は、Docker Composeを使うことです。この例では、GitHubをアイデンティティプロバイダーとして使用し、シンプルな「Whoami」サービスを保護します。
1. GitHub OAuthアプリの作成
GitHubの Settings > Developer settings > OAuth Apps > New OAuth App へ進みます。「Homepage URL」を http://localhost:4180 に、「Authorization callback URL」を http://localhost:4180/oauth2/callback に設定します。作成後、Client IDとClient Secretを取得してください。
2. Docker Composeファイル
次に、docker-compose.yml ファイルを作成します。OAUTH2_PROXY_COOKIE_SECRET には、正確に32バイトの文字列が必要です。私は通常、ブラウザ上で完結して動作する toolcraft.app のジェネレーターを使用しています。このシークレットが正確に32文字でないと、プロキシは起動に失敗します。
version: '3'
services:
oauth2-proxy:
image: quay.io/oauth2-proxy/oauth2-proxy:latest
ports:
- "4180:4180"
environment:
OAUTH2_PROXY_PROVIDER: github
OAUTH2_PROXY_CLIENT_ID: "あなたのクライアントID"
OAUTH2_PROXY_CLIENT_SECRET: "あなたのクライアントシークレット"
OAUTH2_PROXY_COOKIE_SECRET: "あなたの32バイトシークレット"
OAUTH2_PROXY_UPSTREAM: "http://webapp:80"
OAUTH2_PROXY_HTTP_ADDRESS: "0.0.0.0:4180"
OAUTH2_PROXY_EMAIL_DOMAINS: "*"
webapp:
image: traefik/whoami
container_name: webapp
docker-compose up -d で起動します。次に http://localhost:4180 にアクセスしてください。GitHubのログイン画面が表示され、アクセスがブロックされるはずです。ログインに成功して初めて、「Whoami」ページが表示されます。
仕組みの解説
OAuth2 Proxyはリバースプロキシとして動作します。リクエストが届くと、特定のセッションクッキーを探します。クッキーがない、または期限切れの場合、プロキシはユーザーをプロバイダー(Googleなど)にリダイレクトします。ユーザーがログインすると、プロバイダーは認証コードと共にユーザーを戻します。プロキシはそのコードをトークンと交換し、ブラウザに安全なクッキーを保存して、最終的にアプリへの通信を許可します。
主な設定の詳細
- Upstreams: アプリの内部URLです。プロキシがユーザーの身元を確認した後にのみ、通信がこの宛先に届きます。
- Email Domains: これが主要な防御策になります。
*を使う代わりに、yourcompany.comのように設定します。これにより、誰かがGitHubアカウントを持っていても、会社のメールアドレスでない限りアクセスできないように制限できます。 - Cookie Secret: 改ざんを防ぐためにセッションクッキーに署名します。このキーが漏洩すると、攻撃者がログインセッションを偽造できる可能性があります。
Google認証への切り替え
多くの企業環境ではGoogleが標準です。Googleを使用するには、Google Cloud Consoleの「OAuth クライアント ID」で認証情報を作成します。「ウェブ アプリケーション」を選択し、リダイレクトURIを https://your-domain.com/oauth2/callback に設定します。設定ファイルで、プロバイダーを google に変更し、IDを更新するだけです。
高度な設定:Nginxとの統合
本番環境では、OAuth2 Proxyを直接公開することは稀です。Nginxをメインのエントリポイントとして使用し、auth_request モジュールを介してプロキシと通信させるのが最善です。これにより、1つのOAuth2 Proxyインスタンスで数十の異なるサブドメインを保護できます。
以下は、アクセスを許可する前にプロキシを確認するようNginxに指示する方法です:
server {
listen 80;
server_name private-app.example.com;
location /oauth2/ {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Auth-Request-Redirect $request_uri;
}
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# 検証済みのユーザー情報をアプリに渡す
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
proxy_pass http://internal-service:8080;
}
}
このアプローチは非常にクリーンです。内部サービスはOAuthやトークンについて何も知る必要がありません。単に X-User ヘッダーを読み取るだけでよく、そのヘッダーはプロキシが重い処理を終えた後にNginxによって提供されます。
実戦で役立つ本番環境のヒント
ローカルテストから本番環境に移行すると、いくつかの障害に直面することがよくあります。これらのデプロイを管理する中で学んだことを紹介します。
1. 「巨大なクッキー」問題の解決
OAuth2 Proxyはデフォルトでセッションデータをクッキーに保存します。ユーザーが多くのグループに所属している場合、トークンのサイズがブラウザの4KB制限を簡単に超えてしまい、ランダムな「400 Bad Request」エラーが発生することがあります。これを解決するには、セッションストレージに Redis を使用するように切り替えます。これにより、クッキーは小さなセッションIDになり、重いデータはサーバー側に保持されます。
2. きめ細かなアクセス制御
ドメインによる制限だけでは不十分な場合が多いです。GitHubを使用している場合は、--github-org="your-org" フラグを使用して、特定の組織メンバーのみにアクセスを制限します。Google Workspaceユーザーの場合は、--google-admin-group フラグを使用して、[email protected] のような特定の部署にアプリを制限できます。
3. 「ログインループ」の罠
本番環境では常に --cookie-secure=true を設定してください。これにより、クッキーはHTTPS経由でのみ送信されるようになります。ただし、HTTPやlocalhostでテストしている場合、この設定はログインループを引き起こします。ブラウザが安全でないクッキーを黙って拒否するためです。ローカル開発ではオフにし、本番環境では必ずオンにしてください。
4. 不一致のデバッグ
「Redirect URI Mismatch」エラーが発生した場合は、末尾のスラッシュを再確認してください。OAuthプロバイダーは非常に厳格です。http://app.com/oauth2 と http://app.com/oauth2/ は、彼らにとって異なるURLです。迷ったときはコンテナのログを確認してください。通常、プロバイダーが期待していた正確なURLが示されています。
OAuth2 Proxyを導入することで、本来セキュリティ機能を持たないツールに堅牢なセキュリティレイヤーを追加できました。これは、デプロイする社内ツールごとにローカルユーザーやハードコードされたパスワードを管理するよりも、はるかに拡張性の高いソリューションです。

