メインコンテンツまでスキップ

システムセキュリティ設定

idp-serverのシステムレベルセキュリティ設定について説明します。

システム設定とは

システム設定(System Configuration) とは、テナント横断で適用されるアプリケーションレベルのセキュリティ設定です。

┌─────────────────────────────────────────────────────────────┐
│ System Configuration │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ SSRF Protection │ │ Trusted Proxies │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ │
└─────────────┼──────────────────────────┼────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ Application │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ HttpRequestExecutor │ │ Request Handler │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ │
└─────────────┼──────────────────────────┼────────────────────┘
│ │
▼ ▼
外部API呼び出し X-Forwarded-For
(検証後) (クライアントIP取得)

目的

  • SSRF保護: サーバーサイドリクエストフォージェリ攻撃の防止
  • プロキシ信頼設定: ロードバランサー/リバースプロキシ経由のクライアント情報の正確な取得
  • 運用柔軟性: 環境に応じた動的な設定変更

テナント設定との違い

設定タイプ適用範囲
テナント設定特定テナントのみ認証ポリシー、クライアント設定
システム設定全テナント共通SSRF保護、信頼するプロキシ

SSRF保護

SSRFとは

SSRF(Server-Side Request Forgery) は、攻撃者がサーバーを踏み台にして内部ネットワークやクラウドメタデータにアクセスする攻撃です。

【攻撃シナリオ - SSRF保護なし】

攻撃者 ──悪意のあるURL──▶ idp-server ──リクエスト──▶ 内部サービス
169.254.169.254
(クラウドメタデータ)

【SSRF保護あり】

攻撃者 ──悪意のあるURL──▶ idp-server ──× ブロック


❌ 拒否

なぜIdPでSSRF保護が必要か

idp-serverは以下のシナリオで外部HTTPリクエストを実行します:

機能外部リクエスト先リスク
フェデレーション外部IdPのuserinfo endpointURLがテナント設定から取得
CIBA通知クライアント通知エンドポイントURLがクライアント設定から取得
Webhookフック外部WebhookエンドポイントURLがフック設定から取得
身元確認連携外部身元確認サービスURLが設定から取得

これらのURLは管理者が設定しますが、設定ミスや悪意ある設定により内部ネットワークへのアクセスが発生する可能性があります。

ブロック対象

SSRF保護が有効な場合、以下のIPレンジへのリクエストがブロックされます:

IPレンジ説明攻撃リスク
10.0.0.0/8クラスAプライベート内部サービスアクセス
172.16.0.0/12クラスBプライベート内部サービスアクセス
192.168.0.0/16クラスCプライベート内部サービスアクセス
127.0.0.0/8ループバックローカルサービスアクセス
169.254.0.0/16リンクローカル / クラウドメタデータAWS/GCP/Azureメタデータ取得
::1/128IPv6ループバックローカルサービスアクセス
fc00::/7IPv6プライベート内部サービスアクセス

設定オプション

{
"ssrf_protection": {
"enabled": true,
"bypass_hosts": ["localhost", "127.0.0.1", "mock-service"],
"allowed_hosts": ["api.example.com", "identity-provider.example.com"]
}
}
フィールド説明デフォルト
enabledSSRF保護の有効/無効false(DBにデータなし時)
bypass_hostsプライベートIP検証をスキップするホスト[]
allowed_hosts許可するホストの明示的リスト(設定時はallowlist方式)[]

検証フロー

外部リクエスト


┌─────────────────┐
│ SSRF保護 有効? │
└────────┬────────┘

No ──┴── Yes
│ │
▼ ▼
✅許可 ┌─────────────────────┐
│ bypass_hostsに含む? │
└──────────┬──────────┘

No ──┴── Yes
│ │
▼ ▼
┌──────────────────┐ ✅許可
│ allowed_hosts │
│ 設定あり? │
└────────┬─────────┘

No ──┴── Yes
│ │
│ ▼
│ ┌──────────────────┐
│ │ allowed_hostsに │
│ │ 含まれる? │
│ └────────┬─────────┘
│ │
│ No ──┴── Yes
│ │ │
│ ▼ │
│ ❌ブロック │
│ │
└───────┬────────┘

┌─────────────────┐
│ プライベートIP? │
└────────┬────────┘

No ──┴── Yes
│ │
▼ ▼
✅許可 ❌ブロック

運用モード

開発環境(bypass_hosts使用)

ローカル開発やモックサービスへのアクセスを許可:

{
"ssrf_protection": {
"enabled": true,
"bypass_hosts": ["localhost", "127.0.0.1", "host.docker.internal", "mock-service"],
"allowed_hosts": []
}
}

本番環境(allowed_hosts使用 - OWASP推奨)

許可するホストを明示的に指定:

{
"ssrf_protection": {
"enabled": true,
"bypass_hosts": [],
"allowed_hosts": [
"api.trusted-partner.com",
"identity.external-idp.com",
"webhook.monitoring-service.com"
]
}
}

信頼するプロキシ設定

なぜプロキシ信頼設定が必要か

idp-serverがロードバランサーやリバースプロキシの背後で動作する場合、クライアントの実際のIPアドレスはX-Forwarded-Forヘッダーから取得する必要があります。

┌──────────────┐      ┌──────────────────┐      ┌─────────────┐
│ クライアント │ │ ロードバランサー │ │ idp-server │
│ 203.0.113.50 │ ───▶ │ 10.0.0.1 │ ───▶ │ │
└──────────────┘ └──────────────────┘ └─────────────┘

│ X-Forwarded-For: 203.0.113.50

実際のクライアントIP

しかし、このヘッダーは偽装可能なため、信頼できるプロキシからのリクエストでのみヘッダーを信頼する必要があります。

設定オプション

{
"trusted_proxies": {
"enabled": true,
"addresses": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],
"trusted_headers": ["X-Forwarded-For", "X-Forwarded-Proto", "X-Real-IP"]
}
}
フィールド説明デフォルト
enabledプロキシ信頼の有効/無効false
addresses信頼するプロキシのIPアドレス/CIDRレンジ[]
trusted_headers信頼するフォワーディングヘッダー["X-Forwarded-For", "X-Forwarded-Proto", "X-Forwarded-Host", "X-Real-IP"]

CIDRレンジ指定

単一IPアドレスまたはCIDR表記でプロキシを指定できます:

{
"addresses": [
"10.0.0.1",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16"
]
}

プリセット設定

プライベートネットワーク全体を信頼する設定(内部ネットワークにプロキシがある場合):

{
"trusted_proxies": {
"enabled": true,
"addresses": [
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"127.0.0.0/8"
]
}
}

デフォルト動作

DBにデータがない場合

idp-serverはOSSとして「すぐに試せる」ことを重視し、初期状態では保護機能は無効です:

設定状態理由
SSRF保護無効ローカル開発でlocalhostへのリクエストをブロックしない
信頼するプロキシ無効プロキシ設定なしでも動作する

本番運用時

本番環境では管理APIを通じて明示的に設定することを推奨します:

# システム設定を更新
curl -X PUT "https://idp.example.com/v1/management/system-configurations" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ssrf_protection": {
"enabled": true,
"bypass_hosts": [],
"allowed_hosts": ["api.trusted-service.com"]
},
"trusted_proxies": {
"enabled": true,
"addresses": ["10.0.0.0/8"]
}
}'

ユースケース

1. AWS環境でのデプロイ

ALB(Application Load Balancer)の背後でidp-serverを運用:

{
"ssrf_protection": {
"enabled": true,
"bypass_hosts": [],
"allowed_hosts": ["cognito-idp.ap-northeast-1.amazonaws.com"]
},
"trusted_proxies": {
"enabled": true,
"addresses": ["10.0.0.0/8"]
}
}

2. Kubernetes環境でのデプロイ

Ingress Controllerの背後でidp-serverを運用:

{
"ssrf_protection": {
"enabled": true,
"bypass_hosts": [],
"allowed_hosts": ["external-idp.example.com", "webhook.example.com"]
},
"trusted_proxies": {
"enabled": true,
"addresses": ["10.0.0.0/8", "172.16.0.0/12"]
}
}

3. 開発環境

ローカル開発やDocker Compose環境:

{
"ssrf_protection": {
"enabled": true,
"bypass_hosts": ["localhost", "127.0.0.1", "host.docker.internal"],
"allowed_hosts": []
},
"trusted_proxies": {
"enabled": false
}
}

関連ドキュメント


参考資料