Chuyển đến nội dung chính

レッスン 19: 高度なセキュリティと Vault の統合

セキュリティ強化 Keycloak、コンテンツ セキュリティ ポリシー ヘッダー、ブルート フォース検出構成、パスワード ポリシー (各ポリシーの詳細)、セッション管理 (セッション制限、アイドル/最大タイムアウト)、CORS 構成、クリックジャッキング保護、HTTPS/TLS ベスト プラクティス、証明書管理、Vault 統合 (HashiCorp Vault、Kubernetes Secrets、ファイルベース)、ローテーション資格情報、管理コンソールのアクセス制限。

🔒 DevSecOps — レッスン 19 レッスン 19: 高度なセキュリティとボールト 統合

基本から上級までの Keycloak

パート 5: テーマ、イベント、セキュリティ、および Vault

xdev.asia

1. セキュリティ強化チェックリスト

Keycloakを実稼働環境に導入する前に、次の強化策を完全に実装する必要があります。

#カテゴリレベル状態
1HTTPS/TLS の強制致命的☐
2デフォルトの管理者の資格情報を変更する致命的☐
3ブルートフォース検出高い☐
4パスワードポリシー高い☐
5セッションタイムアウト高い☐
6CSPヘッダー高い☐
7クリックジャッキング保護高い☐
8CORS 構成中くらい☐
9シークレットの Vault 統合高い☐
10管理コンソールのアクセス制限高い☐
11未使用の機能/エンドポイントを無効にする中くらい☐
12保存時のデータベースの暗号化高い☐
13トークンセキュリティ (有効期限が短い)高い☐
14監査ログが有効になっている高い☐

2. コンテンツ セキュリティ ポリシー (CSP) ヘッダー

CSP ヘッダーは、ページへの読み込みを許可するリソースを制御することにより、XSS 攻撃から保護します。

2.1 KeycloakでCSPを構成する

KeycloakはCSPを構成しますレルム設定 → セキュリティ防御:

# Headers tab → Content-Security-Policy
frame-src 'self'; frame-ancestors 'self'; object-src 'none';

# Nâng cao: restrict thêm script-src, style-src
frame-src 'self'; frame-ancestors 'self'; object-src 'none'; \
script-src 'self' 'unsafe-inline'; \
style-src 'self' 'unsafe-inline';

2.2 REST APIによる設定

# Cập nhật Security Headers cho realm
curl -X PUT "http://localhost:8080/admin/realms/my-realm" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "browserSecurityHeaders": {
        "contentSecurityPolicy": "frame-src '\''self'\''; frame-ancestors '\''self'\''; object-src '\''none'\'';",
        "contentSecurityPolicyReportOnly": "",
        "xContentTypeOptions": "nosniff",
        "xRobotsTag": "none",
        "xFrameOptions": "SAMEORIGIN",
        "strictTransportSecurity": "max-age=31536000; includeSubDomains",
        "xXSSProtection": "1; mode=block",
        "referrerPolicy": "no-referrer"
    }
  }'

2.3 重要なセキュリティヘッダー

ヘッダ推奨値目的
X フレーム オプション同じ原産地クリックジャッキング対策
X-コンテンツタイプ-オプション鼻を鳴らすMIME タイプ スニッフィングを防止する
X-XSS 保護1;モード=ブロックブラウザの XSS フィルターをオンにする
厳格な輸送セキュリティ最大年齢=31536000;サブドメインを含むHTTPS (HSTS) を強制する
リファラーポリシー非参照者リファラーヘッダーを送信しない
コンテンツセキュリティポリシーフレームソース、オブジェクトソースを制限するXSS とデータ インジェクションを防止する

3. ブルートフォース検出

Keycloakには、ログイン試行に対するブルートフォース防止メカニズムが組み込まれています。

3.1 ブルートフォース構成

入力レルム設定 → セキュリティ防御 → ブルートフォース検出:

# Bật/tắt
Enabled: ON

# Lockout settings
Permanent Lockout: OFF                  # Có khóa vĩnh viễn không
Max Login Failures: 5                   # Số lần thất bại tối đa trước khi lock
Wait Increment (seconds): 60            # Thời gian chờ tăng dần mỗi lần fail tiếp
Max Wait (seconds): 900                 # Thời gian chờ tối đa (15 phút)
Quick Login Check (milliseconds): 1000  # Khoảng thời gian giữa 2 lần login nhanh
Minimum Quick Login Wait: 60            # Chờ tối thiểu khi quick login detected
Failure Reset Time (seconds): 43200     # Reset failure counter sau 12 giờ

3.2 REST APIによる設定

curl -X PUT "http://localhost:8080/admin/realms/my-realm" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "bruteForceProtected": true,
    "permanentLockout": false,
    "maxFailureWaitSeconds": 900,
    "minimumQuickLoginWaitSeconds": 60,
    "waitIncrementSeconds": 60,
    "quickLoginCheckMilliSeconds": 1000,
    "maxDeltaTimeSeconds": 43200,
    "failureFactor": 5
  }'

3.3 ブルートフォース検出の仕組み

Lần fail thứ 1: Không lockout
Lần fail thứ 2: Không lockout
Lần fail thứ 3: Không lockout
Lần fail thứ 4: Không lockout
Lần fail thứ 5: Lockout 60 giây (waitIncrementSeconds)
Lần fail thứ 6: Lockout 120 giây (60 * 2)
Lần fail thứ 7: Lockout 240 giây (60 * 4)
...tiếp tục tăng...
Max lockout: 900 giây (15 phút)

Sau 12 giờ không fail: Reset counter về 0

3.4 ロックの解除 ユーザーがロックされています

# Kiểm tra trạng thái brute-force cho user
curl -s "http://localhost:8080/admin/realms/my-realm/attack-detection/brute-force/users/$USER_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN" | jq .

# Response mẫu:
# {
#   "numFailures": 6,
#   "disabled": true,
#   "lastIPFailure": "192.168.1.100",
#   "lastFailure": 1710489045000
# }

# Unlock user cụ thể
curl -X DELETE "http://localhost:8080/admin/realms/my-realm/attack-detection/brute-force/users/$USER_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Unlock tất cả users
curl -X DELETE "http://localhost:8080/admin/realms/my-realm/attack-detection/brute-force/users" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

4. パスワードポリシー

Keycloakは、強力なパスワードを確保するために多くのパスワード・ポリシーをサポートしています。

4.1 パスワードポリシーの構成

入力認証 → ポリシー → パスワードポリシーそしてポリシーを追加します。

ポリシー説明するサンプル値
長さ。長さ最小長さ12
最大長さ最大長さ128
数字数字の最小数1
小文字最小文字数1
大文字大文字の最小数1
特別な文字特殊文字の最小数1
ユーザー名ではありませんパスワードはユーザー名と同じであってはなりません(値なし)
メールではありませんパスワードはメールアドレスと一致してはなりません(値なし)
パスワード履歴過去 N 個のパスワードを再利用しないでください5
ハッシュアルゴリズムパスワードハッシュアルゴリズムpbkdf2-sha512
ハッシュ反復ハッシュの反復数210000
強制期限切れパスワード変更N日後にMKの変更を強制される90
regulx式カスタム正規表現パターン^(?!.*(.)\1{2}).*$

4.2 REST APIによる設定

# Set password policies cho realm
curl -X PUT "http://localhost:8080/admin/realms/my-realm" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "passwordPolicy": "length(12) and digits(1) and lowerCase(1) and upperCase(1) and specialChars(1) and notUsername and notEmail and passwordHistory(5) and hashAlgorithm(pbkdf2-sha512) and hashIterations(210000) and forceExpiredPasswordChange(90) and maxLength(128)"
  }'

4.3 ハッシュアルゴリズムの推奨事項

アルゴリズム反復 (推奨)注記
pbkdf2-sha256600,000OWASP 2023 の推奨事項
pbkdf2-sha512210,000OWASP 2023 の推奨事項
アルゴン2該当なし (Keycloak 24+)メモリに負荷がかかるため、新規導入に推奨
# Sử dụng Argon2 (Keycloak 24+)
# passwordPolicy: hashAlgorithm(argon2)
curl -X PUT "http://localhost:8080/admin/realms/my-realm" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "passwordPolicy": "length(12) and digits(1) and lowerCase(1) and upperCase(1) and specialChars(1) and hashAlgorithm(argon2)"
  }'

5. セッション管理

厳密なセッション管理はセキュリティにとって重要です。

5.1 セッションのタイムアウト

での構成レルム設定 → セッション:

設定説明する推奨
SSO セッションのアイドル状態SSO セッションの最大アイドル時間30分
SSO セッション最大値SSO セッションの最大時間 (アクティビティに関係なく)10時
SSO セッション アイドル状態 リメンバーミー「Remember Me」が有効な場合のアイドル タイムアウト7日間
SSO セッション Max Remember Me「Remember Me」が有効な場合の最大有効期間30日
クライアントセッションアイドル状態クライアント固有のセッションのアイドル タイムアウト15分
クライアントセッション最大値クライアント固有のセッションの最大存続期間8時
オフラインセッションアイドル状態オフライントークンのアイドルタイムアウト30日
オフラインセッション最大値オフラインセッションの最大制限ライフタイム60日

5.2 セッションの詳細な設定

# Cấu hình session timeouts
curl -X PUT "http://localhost:8080/admin/realms/my-realm" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ssoSessionIdleTimeout": 1800,
    "ssoSessionMaxLifespan": 36000,
    "ssoSessionIdleTimeoutRememberMe": 604800,
    "ssoSessionMaxLifespanRememberMe": 2592000,
    "clientSessionIdleTimeout": 900,
    "clientSessionMaxLifespan": 28800,
    "offlineSessionIdleTimeout": 2592000,
    "offlineSessionMaxLifespan": 5184000,
    "offlineSessionMaxLifespanEnabled": true
  }'

5.3 セッション制限

ユーザーごとの同時セッション数を制限します。

# Authentication → Flows → Browser Flow
# Thêm step "User Session Limits"

Session Limits Configuration:
- Max concurrent sessions per user: 3
- Behavior on breach: "Terminate oldest session"

# Hoặc cấu hình qua Authentication Flow:
# 1. Copy "Browser" flow
# 2. Thêm execution "User Session Count Limiter"  
# 3. Cấu hình max sessions

5.4 セッションの監査と取り消し

# List sessions của user
curl -s "http://localhost:8080/admin/realms/my-realm/users/$USER_ID/sessions" \
  -H "Authorization: Bearer $ACCESS_TOKEN" | jq .

# Response mẫu:
# [
#   {
#     "id": "session-id",
#     "username": "john",
#     "userId": "user-uuid",
#     "ipAddress": "192.168.1.100",
#     "start": 1710489045,
#     "lastAccess": 1710492645,
#     "clients": { "client-uuid": "my-app" }
#   }
# ]

# Revoke session cụ thể
curl -X DELETE "http://localhost:8080/admin/realms/my-realm/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Logout tất cả sessions của user
curl -X POST "http://localhost:8080/admin/realms/my-realm/users/$USER_ID/logout" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Logout tất cả sessions trong realm
curl -X POST "http://localhost:8080/admin/realms/my-realm/logout-all" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

6. CORS の設定

CORS (Cross-Origin Resource Sharing) が構成されているクライアントごとキークロークで。

6.1 クライアントの CORS の構成

# Client Settings → Web Origins

# Cho phép specific origins
https://myapp.com
https://admin.myapp.com

# Cho phép tất cả redirect URIs (sử dụng "+")
+

# KHÔNG sử dụng "*" trong production
# "*" cho phép tất cả origins — nguy hiểm!
# Cấu hình CORS qua REST API
curl -X PUT "http://localhost:8080/admin/realms/my-realm/clients/$CLIENT_UUID" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "webOrigins": [
        "https://myapp.com",
        "https://admin.myapp.com"
    ]
  }'

6.2 CORS のベスト プラクティス

  • 常に特定の起源を指定する— ワイルドカードは使用しないでください*
  • 使用+— 有効なリダイレクト URI から起点を自動的に導出する
  • 個別のクライアント— 各フロントエンド アプリには、独自の CORS 構成を持つ独自のクライアントが必要です
  • 慎重にテストしてください— ブラウザーの DevTools で CORS 応答ヘッダーを確認する

7. クリックジャッキング保護

クリックジャッキング攻撃は、Keycloak ログインページを iframe に埋め込んで認証情報を盗みます。

7.1 X フレーム オプションの構成

# Realm Settings → Security Defenses → Headers

X-Frame-Options: SAMEORIGIN
# - DENY: Không cho phép iframe dưới bất kỳ điều kiện nào
# - SAMEORIGIN: Chỉ cho phép iframe từ cùng origin
# - ALLOW-FROM uri: (deprecated, dùng CSP frame-ancestors thay thế)

7.2 CSP フレーム祖先 (推奨)

# Content-Security-Policy header
frame-ancestors 'self';

# Cho phép specific parent origins
frame-ancestors 'self' https://portal.mycompany.com;

8. HTTPS/TLS の強制

8.1 ホスト名とTLSの構成

# Production: Strict HTTPS
bin/kc.sh start \
  --hostname=auth.mycompany.com \
  --hostname-strict=true \
  --https-certificate-file=/etc/certs/tls.crt \
  --https-certificate-key-file=/etc/certs/tls.key \
  --https-port=8443 \
  --http-enabled=false

8.2 リバース プロキシを使用した TLS (一般的)

# Khi sử dụng reverse proxy (Nginx, HAProxy) terminate TLS
bin/kc.sh start \
  --hostname=auth.mycompany.com \
  --hostname-strict=true \
  --proxy-headers=xforwarded \
  --http-enabled=true \
  --http-port=8080
# Nginx reverse proxy configuration
server {
    listen 443 ssl http2;
    server_name auth.mycompany.com;

    ssl_certificate /etc/ssl/certs/auth.mycompany.com.crt;
    ssl_certificate_key /etc/ssl/private/auth.mycompany.com.key;

    # Strong TLS configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location / {
        proxy_pass http://keycloak:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port $server_port;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Timeouts
        proxy_read_timeout 90s;
        proxy_send_timeout 90s;
    }
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name auth.mycompany.com;
    return 301 https://$host$request_uri;
}

8.3 相互TLS (mTLS)

# Bật mTLS cho client authentication
bin/kc.sh start \
  --https-certificate-file=/etc/certs/tls.crt \
  --https-certificate-key-file=/etc/certs/tls.key \
  --https-trust-store-file=/etc/certs/truststore.jks \
  --https-trust-store-password=changeit \
  --https-client-auth=request

# --https-client-auth options:
# none: không yêu cầu client cert
# request: yêu cầu nhưng không bắt buộc
# required: bắt buộc client cert

8.4 証明書の管理

# Sử dụng cert-manager trong Kubernetes
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: keycloak-tls
  namespace: keycloak
spec:
  secretName: keycloak-tls-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - auth.mycompany.com
  renewBefore: 720h  # Renew 30 ngày trước khi hết hạn
# Kubernetes Deployment sử dụng TLS secret
apiVersion: apps/v1
kind: Deployment
metadata:
  name: keycloak
spec:
  template:
    spec:
      containers:
        - name: keycloak
          image: quay.io/keycloak/keycloak:26.1
          args:
            - start
            - --hostname=auth.mycompany.com
            - --https-certificate-file=/etc/certs/tls.crt
            - --https-certificate-key-file=/etc/certs/tls.key
          volumeMounts:
            - name: tls-certs
              mountPath: /etc/certs
              readOnly: true
      volumes:
        - name: tls-certs
          secret:
            secretName: keycloak-tls-secret

9. ボールトの統合

Keycloakは、データベース内のプレーンテキストではなく、外部ボールトへのシークレット(LDAPバインド・パスワード、SMTPパスワード、クライアント・シークレット)の保存をサポートしています。

9.1 HashiCorp Vault の統合

# Cấu hình Keycloak sử dụng HashiCorp Vault
bin/kc.sh start \
  --vault=hashicorp \
  --vault-hashicorp-paths=/secret/data/keycloak \
  --vault-hashicorp-address=https://vault.mycompany.com:8200 \
  --vault-hashicorp-auth-method=token \
  --vault-hashicorp-token=$VAULT_TOKEN

# Hoặc sử dụng AppRole authentication
bin/kc.sh start \
  --vault=hashicorp \
  --vault-hashicorp-paths=/secret/data/keycloak \
  --vault-hashicorp-address=https://vault.mycompany.com:8200 \
  --vault-hashicorp-auth-method=approle \
  --vault-hashicorp-approle-role-id=$ROLE_ID \
  --vault-hashicorp-approle-secret-id=$SECRET_ID

9.2 HashiCorp Vault へのシークレットの保存

# Cấu hình Vault KV secrets engine
vault secrets enable -path=secret kv-v2

# Lưu LDAP bind password
vault kv put secret/keycloak/my-realm \
  ldap_bind_credential="LdapS3cur3P@ss!" \
  smtp_password="SmtpP@ssw0rd!" \
  my-client-secret="Cl13ntS3cr3t!"

# Cấu trúc path trong Vault:
# secret/data/keycloak/{realm-name}/{key}

9.3 KeycloakでのVaultリファレンスの使用

Keycloak では、次の構文を使用します${vault.key}平文の代わりに:

# LDAP User Federation
Bind Credential: ${vault.ldap_bind_credential}

# SMTP Settings
Password: ${vault.smtp_password}

# Client Secret
Client Secret: ${vault.my-client-secret}

9.4 Kubernetes/OpenShift Secrets Vault

# Sử dụng Kubernetes Secrets làm vault
bin/kc.sh start \
  --vault=file \
  --vault-dir=/mnt/secrets
# Kubernetes Secret
apiVersion: v1
kind: Secret
metadata:
  name: keycloak-vault
  namespace: keycloak
type: Opaque
stringData:
  # Format: {realm-name}_{key}
  my-realm_ldap_bind_credential: "LdapS3cur3P@ss!"
  my-realm_smtp_password: "SmtpP@ssw0rd!"
  my-realm_my-client-secret: "Cl13ntS3cr3t!"
# Mount Secret vào Keycloak Pod
apiVersion: apps/v1
kind: Deployment
metadata:
  name: keycloak
spec:
  template:
    spec:
      containers:
        - name: keycloak
          args:
            - start
            - --vault=file
            - --vault-dir=/mnt/secrets
          volumeMounts:
            - name: vault-secrets
              mountPath: /mnt/secrets
              readOnly: true
      volumes:
        - name: vault-secrets
          secret:
            secretName: keycloak-vault

9.5 ファイルベースのボールト (開発)

# Tạo vault files cho development
mkdir -p /opt/keycloak/vault/my-realm

# Mỗi file chứa một secret (filename = key)
echo -n "LdapS3cur3P@ss!" > /opt/keycloak/vault/my-realm/ldap_bind_credential
echo -n "SmtpP@ssw0rd!" > /opt/keycloak/vault/my-realm/smtp_password

# Cấu hình Keycloak
bin/kc.sh start-dev \
  --vault=file \
  --vault-dir=/opt/keycloak/vault

9.6 認証情報のローテーション

# HashiCorp Vault: Rotate LDAP password
# 1. Update secret trong Vault
vault kv put secret/keycloak/my-realm \
  ldap_bind_credential="NewLdapP@ss2026!"

# 2. Keycloak sẽ tự động lấy secret mới
# (Vault SPI cache TTL = 0 by default, mỗi lần cần sẽ fetch lại)

# Kubernetes Secrets: Update secret
kubectl create secret generic keycloak-vault \
  --from-literal=my-realm_ldap_bind_credential="NewLdapP@ss2026!" \
  --dry-run=client -o yaml | kubectl apply -f -

# Rolling restart Keycloak để pickup new secrets
kubectl rollout restart deployment/keycloak -n keycloak

10. 管理コンソールのアクセス制限

10.1 専用の管理者レルム

使用マスターレルム管理者の場合のみ、ユーザー/クライアント ビジネスを作成しないでください。

Best Practice:
- Master realm: Chỉ chứa admin users
- Business realms: Chứa application users/clients
- Không cho phép self-registration trên master realm
- MFA bắt buộc cho admin accounts

10.2 管理コンソールの IP ホワイトリスト

# Nginx: Restrict Admin Console access
location /admin/ {
    # Chỉ cho phép IP nội bộ
    allow 10.0.0.0/8;
    allow 172.16.0.0/12;
    allow 192.168.0.0/16;
    deny all;

    proxy_pass http://keycloak:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

# Block admin REST API từ external
location /admin/realms/ {
    allow 10.0.0.0/8;
    deny all;

    proxy_pass http://keycloak:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

10.3 Kubernetesネットワークポリシー

# NetworkPolicy: Restrict Admin API access
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: keycloak-admin-restrict
  namespace: keycloak
spec:
  podSelector:
    matchLabels:
      app: keycloak
  policyTypes:
    - Ingress
  ingress:
    # Allow user-facing traffic from ingress controller
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
      ports:
        - port: 8080
    # Allow admin traffic only from management namespace
    - from:
        - namespaceSelector:
            matchLabels:
              name: management
      ports:
        - port: 8080

11. トークンのセキュリティ

11.1 有効期間の短いトークン

# Cấu hình token lifespans
curl -X PUT "http://localhost:8080/admin/realms/my-realm" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "accessTokenLifespan": 300,
    "accessTokenLifespanForImplicitFlow": 900,
    "actionTokenGeneratedByUserLifespan": 300,
    "actionTokenGeneratedByAdminLifespan": 43200
  }'

# Per-client token lifespan override
curl -X PUT "http://localhost:8080/admin/realms/my-realm/clients/$CLIENT_UUID" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "attributes": {
        "access.token.lifespan": "180",
        "client.session.idle.timeout": "600",
        "client.session.max.lifespan": "3600"
    }
  }'

11.2 トークンのイントロスペクション

# Introspect token (kiểm tra validity)
curl -X POST "http://localhost:8080/realms/my-realm/protocol/openid-connect/token/introspect" \
  -d "client_id=my-resource-server" \
  -d "client_secret=$CLIENT_SECRET" \
  -d "token=$ACCESS_TOKEN"

# Response
# {
#   "active": true,
#   "sub": "user-uuid",
#   "aud": "my-app",
#   "exp": 1710492645,
#   "iat": 1710489045,
#   "realm_access": { "roles": ["user"] },
#   "scope": "openid profile email"
# }

11.3 トークンの取り消し

# Revoke refresh token
curl -X POST "http://localhost:8080/realms/my-realm/protocol/openid-connect/revoke" \
  -d "client_id=my-app" \
  -d "client_secret=$CLIENT_SECRET" \
  -d "token=$REFRESH_TOKEN" \
  -d "token_type_hint=refresh_token"

# Revoke access token
curl -X POST "http://localhost:8080/realms/my-realm/protocol/openid-connect/revoke" \
  -d "client_id=my-app" \
  -d "client_secret=$CLIENT_SECRET" \
  -d "token=$ACCESS_TOKEN" \
  -d "token_type_hint=access_token"

12. 実稼働環境への導入 — 強化された

# docker-compose.production.yml - Hardened Keycloak
services:
  keycloak:
    image: quay.io/keycloak/keycloak:26.1
    command:
      - start
      - --hostname=auth.mycompany.com
      - --hostname-strict=true
      - --proxy-headers=xforwarded
      - --http-enabled=true
      - --metrics-enabled=true
      - --health-enabled=true
      - --vault=file
      - --vault-dir=/mnt/secrets
      - --log=console
      - --log-console-output=json
    environment:
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD_FILE: /run/secrets/db_password
      KC_CACHE: ispn
      KC_CACHE_STACK: kubernetes
    volumes:
      - ./secrets:/mnt/secrets:ro
    secrets:
      - db_password
    deploy:
      replicas: 2
      resources:
        limits:
          memory: 1G
          cpus: '1.0'
        reservations:
          memory: 512M
          cpus: '0.5'
    healthcheck:
      test: ["CMD-SHELL", "exec 3<>/dev/tcp/localhost/9000 && echo -e 'GET /health/ready HTTP/1.1\r\nHost: localhost\r\n\r\n' >&3 && cat <&3 | grep -q '\"status\":\"UP\"'"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

secrets:
  db_password:
    file: ./secrets/db_password

13. ベストプラクティスの概要

  • どこでもHTTPS— TLS を使用せずに Keycloak 本番環境をデプロイしないでください。 HSTS ヘッダーを使用します。
  • Vault の秘密— 平文の認証情報を DB に保存しないでください。 HashiCorp Vault または Kubernetes Secret を使用します。
  • 強力なパスワードポリシー— 最小 12 文字。反復回数が多い場合は Argon2 または PBKDF2-SHA512 を使用します。
  • セッション制限— 同時セッションの数を制限します。それに応じてアイドル/最大タイムアウトを設定します。
  • 管理者アクセスが制限されています— 管理コンソールの IP ホワイトリスト。管理者アカウントには MFA が必要です。
  • 有効期間の短いトークン— アクセス トークンは 5 分間、リフレッシュ トークンのローテーションは有効です。
  • ブルートフォース保護— 有効にし、それに応じて設定します。ログイン失敗率を監視します。
  • 定期的なセキュリティ監査— Keycloak構成を定期的に確認します。最新バージョンにアップデートしてください。
  • 別個の管理レルム— マスターレルムは管理者のみに使用します。管理者ユーザーとビジネス ユーザーを混在させないでください。
  • 監視と警告— イベント ログ (レッスン 18) をセキュリティ監視と組み合わせて、検出と対応を行います。