1. イベントシステムの概要
Keycloakがシステムを提供イベントシステムシステム内のすべてのアクティビティを監視するための包括的な機能。ログイン、登録、管理設定の変更に至るすべてのアクションがイベントとして記録されます。
1.1 2 種類のイベント
| タイプ | 説明する | 例えば |
|---|---|---|
| ログインイベント(ユーザーイベント) | ユーザー関連のアクション | ログイン、登録、ログアウト、TOKEN_EXCHANGE |
| 管理者イベント | 管理コンソール/API を介した構成変更 | ユーザーの作成、レルムの更新、クライアントの削除 |
1.2 ログインイベントの種類
| イベントタイプ | 説明する | それはいつ起こりますか? |
|---|---|---|
ログイン | ログインに成功しました | ユーザーが正しい認証情報を入力する |
ログインエラー | ログインに失敗しました | ユーザー名/パスワードが間違っています |
登録する | 新しいアカウントを登録する | ユーザーがアカウントを正常に作成しました |
登録エラー | 登録に失敗しました | メールが重複しています。検証に失敗しました |
ログアウト | サインアウト | ユーザーのログアウトまたはセッションの期限切れ |
CODE_TO_TOKEN | 認可コード→トークンの交換 | OIDC 認可コードのフロー |
CODE_TO_TOKEN_ERROR | トークン交換に失敗しました | 無効なコード、期限切れのコード |
REFRESH_TOKEN | アクセストークンを更新する | クライアントはリフレッシュトークンを使用します |
REFRESH_TOKEN_ERROR | リフレッシュトークンが失敗しました | トークンが取り消されたか期限切れになった |
CLIENT_LOGIN | クライアント認証 | サービスアカウントのログイン |
INTROSPECT_TOKEN | トークンの導入 | リソースサーバー検証トークン |
UPDATE_PASSWORD | パスワードを変更する | ユーザーがパスワードを変更する |
RESET_PASSWORD | パスワードをリセットする | 電子メールリンク経由でユーザーがリセット |
VERIFY_EMAIL | メール認証 | ユーザーが確認リンクをクリックする |
SEND_RESET_PASSWORD | パスワードリセットメールを送信する | パスワードを忘れた場合のリクエスト |
UPDATE_PROFILE | プロフィールを更新する | ユーザーが個人情報を更新する |
REMOVE_TOTP | TOTPデバイスの削除 | ユーザーが OTP 認証システムを削除する |
UPDATE_TOTP | TOTP 構成 | ユーザーが OTP を設定する |
GRANT_CONSENT | ユーザーが同意する | OAuth2同意画面 |
TOKEN_EXCHANGE | トークン交換 | クライアント間でトークンを交換する |
1.3 管理イベントの操作
| 手術 | 説明する | リソースの種類 |
|---|---|---|
作成する | 新しいリソースを作成する | ユーザー、クライアント、レルム、グループ、ロール... |
アップデート | リソースを更新する | ユーザー、クライアント、REALM_SETTINGS... |
消去 | リソースの削除 | ユーザー、クライアント、セッション... |
アクション | 行動を起こす | RESET_PASSWORD、SEND_VERIFY_EMAIL... |
2. イベントログをオンにする
2.1 管理コンソール経由
- ログイン管理コンソール
- レルムを選択 →レルム設定→タブイベント
- 構成ユーザーイベント設定:
- イベントの保存: の上
- 有効期限: 30 日間 (コンプライアンス要件に応じて)
- 保存されたタイプ: 保存するイベントの種類を選択します (デフォルト: ALL)
- 構成管理者イベントの設定:
- イベントの保存: の上
- 表現を含める: ON (リクエスト/レスポンスボディを保存)
- イベントリスナー: 必要なリスナーを追加します
2.2 REST API経由
# Bật event logging cho realm
curl -X PUT "http://localhost:8080/admin/realms/my-realm" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"eventsEnabled": true,
"eventsExpiration": 2592000,
"eventsListeners": ["jboss-logging"],
"enabledEventTypes": [
"LOGIN", "LOGIN_ERROR",
"REGISTER", "REGISTER_ERROR",
"LOGOUT",
"CODE_TO_TOKEN", "CODE_TO_TOKEN_ERROR",
"REFRESH_TOKEN", "REFRESH_TOKEN_ERROR",
"CLIENT_LOGIN", "CLIENT_LOGIN_ERROR",
"UPDATE_PASSWORD",
"RESET_PASSWORD",
"SEND_RESET_PASSWORD"
],
"adminEventsEnabled": true,
"adminEventsDetailsEnabled": true
}'
3. イベントリスナー
イベント リスナーは、イベントが発生したときに処理します。 Keycloak には次のリスナーが利用可能です。
3.1 jboss-logging リスナー
イベントをKeycloakサーバーログに記録します(デフォルトで有効):
# Log output mẫu
2026-03-15 10:30:45,123 INFO [org.keycloak.events] (executor-thread-1)
type=LOGIN, realmId=my-realm, clientId=my-app, userId=abc-123,
ipAddress=192.168.1.100, auth_method=openid-connect,
auth_type=code, redirect_uri=https://myapp.com/callback,
[email protected]
3.2 電子メールリスナー
重要なイベントがあるときにユーザーに電子メールを送信します (例: 新しいデバイスからのログイン):
# Bật email listener
Realm Settings → Events → Event listeners → Thêm "email"
# Events được gửi email por defecto:
- LOGIN_ERROR (quá nhiều lần → cảnh báo compromised account)
- UPDATE_PASSWORD
- REMOVE_TOTP
- UPDATE_TOTP
4. イベント詳細とイベントストア
4.1 ログインイベントの構造
{
"time": 1710489045000,
"type": "LOGIN",
"realmId": "my-realm",
"clientId": "my-web-app",
"userId": "550e8400-e29b-41d4-a716-446655440000",
"sessionId": "abc-session-id",
"ipAddress": "192.168.1.100",
"details": {
"auth_method": "openid-connect",
"auth_type": "code",
"redirect_uri": "https://myapp.com/callback",
"consent": "no_consent_required",
"code_id": "xyz-code-id",
"username": "[email protected]",
"identity_provider": null
}
}
4.2 管理イベントの構造
{
"time": 1710489100000,
"realmId": "my-realm",
"authDetails": {
"realmId": "master",
"clientId": "security-admin-console",
"userId": "admin-user-id",
"ipAddress": "10.0.0.1"
},
"operationType": "CREATE",
"resourceType": "USER",
"resourcePath": "users/new-user-id",
"representation": "{\"username\":\"newuser\",\"email\":\"[email protected]\",\"enabled\":true}"
}
4.3 イベントストア — データベース
イベントはKeycloakのデータベースに保存されます。
| テーブル | コンテンツ |
|---|---|
EVENT_ENTITY | ログインイベント |
ADMIN_EVENT_ENTITY | 管理者イベント |
注記:デフォルトのイベントストアはKeycloak DBに保存されます。イベントの数が多い場合は、カスタム イベント リスナーを使用してイベントを外部システムに送信し、組み込みストアの有効期限を短く設定する必要があります。
5. イベントのフィルタリングとクエリ
5.1 管理コンソール経由
- 入力イベント→タブユーザーイベントまたは管理者イベント
- イベントを次の条件でフィルタリングします。
- イベントの種類: ログイン、ログインエラー、登録...
- クライアント: 特定のクライアントを選択します
- ユーザー:ユーザーIDで検索
- 日付範囲: 開始日/終了日
- IPアドレス: IPでフィルタリング
5.2 REST API経由 — ログインイベント
# Lấy tất cả login events
curl -s "http://localhost:8080/admin/realms/my-realm/events" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq .
# Filter theo event type
curl -s "http://localhost:8080/admin/realms/my-realm/events?type=LOGIN_ERROR" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq .
# Filter theo user
curl -s "http://localhost:8080/admin/realms/my-realm/events?user=user-uuid" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq .
# Filter theo client và date range
curl -s "http://localhost:8080/admin/realms/my-realm/events?\
client=my-app&\
dateFrom=2026-03-01&\
dateTo=2026-03-31&\
first=0&\
max=100" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq .
# Filter nhiều event types
curl -s "http://localhost:8080/admin/realms/my-realm/events?\
type=LOGIN&type=LOGIN_ERROR&type=REGISTER" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq .
5.3 REST API 経由 — 管理イベント
# Lấy admin events
curl -s "http://localhost:8080/admin/realms/my-realm/admin-events" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq .
# Filter theo operation type
curl -s "http://localhost:8080/admin/realms/my-realm/admin-events?\
operationTypes=CREATE&\
resourceTypes=USER" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq .
# Filter theo resource path
curl -s "http://localhost:8080/admin/realms/my-realm/admin-events?\
resourcePath=users" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq .
6. カスタム イベント リスナー SPI
Keycloak を使用すると、カスタム イベント リスナーを作成できます。サービスプロバイダーインターフェイス (SPI).
6.1 Maven プロジェクトの作成
<!-- pom.xml -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>custom-event-listener</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<keycloak.version>26.1.0</keycloak.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<version>${keycloak.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId>
<version>${keycloak.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>${keycloak.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
6.2 EventListenerProviderの実装
// src/main/java/com/example/CustomEventListenerProvider.java
package com.example;
import org.keycloak.events.Event;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.OperationType;
import org.keycloak.models.KeycloakSession;
import org.jboss.logging.Logger;
import java.util.Map;
public class CustomEventListenerProvider implements EventListenerProvider {
private static final Logger log = Logger.getLogger(CustomEventListenerProvider.class);
private final KeycloakSession session;
public CustomEventListenerProvider(KeycloakSession session) {
this.session = session;
}
@Override
public void onEvent(Event event) {
// Xử lý Login Events
log.infof("Event: type=%s, realmId=%s, clientId=%s, userId=%s, ip=%s",
event.getType(),
event.getRealmId(),
event.getClientId(),
event.getUserId(),
event.getIpAddress());
// Xử lý theo event type
switch (event.getType()) {
case LOGIN:
handleLogin(event);
break;
case LOGIN_ERROR:
handleLoginError(event);
break;
case REGISTER:
handleRegister(event);
break;
default:
break;
}
}
@Override
public void onEvent(AdminEvent event, boolean includeRepresentation) {
// Xử lý Admin Events
log.infof("AdminEvent: operation=%s, resourceType=%s, resourcePath=%s, realmId=%s",
event.getOperationType(),
event.getResourceType(),
event.getResourcePath(),
event.getRealmId());
if (event.getOperationType() == OperationType.DELETE) {
handleAdminDelete(event);
}
}
private void handleLogin(Event event) {
// Ví dụ: Gửi event đến Kafka
String payload = buildEventPayload(event);
// kafkaProducer.send("keycloak-login-events", payload);
log.debugf("Login event sent to message broker: %s", payload);
}
private void handleLoginError(Event event) {
Map<String, String> details = event.getDetails();
String username = details != null ? details.get("username") : "unknown";
String error = event.getError();
log.warnf("Login failure: user=%s, error=%s, ip=%s",
username, error, event.getIpAddress());
// Ví dụ: Increment metric counter cho monitoring
// metricsService.incrementCounter("login_failures",
// "realm", event.getRealmId(),
// "error", error);
}
private void handleRegister(Event event) {
log.infof("New user registered: userId=%s, realm=%s",
event.getUserId(), event.getRealmId());
}
private void handleAdminDelete(AdminEvent event) {
log.warnf("Admin DELETE operation: resource=%s/%s by admin=%s",
event.getResourceType(),
event.getResourcePath(),
event.getAuthDetails().getUserId());
}
private String buildEventPayload(Event event) {
// Tạo JSON payload cho message broker
StringBuilder sb = new StringBuilder();
sb.append("{");
sb.append("\"type\":\"").append(event.getType()).append("\",");
sb.append("\"realmId\":\"").append(event.getRealmId()).append("\",");
sb.append("\"userId\":\"").append(event.getUserId()).append("\",");
sb.append("\"clientId\":\"").append(event.getClientId()).append("\",");
sb.append("\"ipAddress\":\"").append(event.getIpAddress()).append("\",");
sb.append("\"time\":").append(event.getTime());
sb.append("}");
return sb.toString();
}
@Override
public void close() {
// Cleanup resources
}
}
6.3 EventListenerProviderFactoryの実装
// src/main/java/com/example/CustomEventListenerProviderFactory.java
package com.example;
import org.keycloak.Config;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventListenerProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
public class CustomEventListenerProviderFactory implements EventListenerProviderFactory {
public static final String PROVIDER_ID = "custom-event-listener";
@Override
public EventListenerProvider create(KeycloakSession session) {
return new CustomEventListenerProvider(session);
}
@Override
public void init(Config.Scope config) {
// Đọc cấu hình từ keycloak config
// Ví dụ: String kafkaBrokers = config.get("kafka-brokers", "localhost:9092");
}
@Override
public void postInit(KeycloakSessionFactory factory) {
// Post-initialization
}
@Override
public void close() {
// Cleanup
}
@Override
public String getId() {
return PROVIDER_ID;
}
}
6.4 SPIの登録
# src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory
com.example.CustomEventListenerProviderFactory
6.5 導入とアクティベーション
# Build
mvn clean package
# Deploy
cp target/custom-event-listener-1.0.0.jar $KEYCLOAK_HOME/providers/
$KEYCLOAK_HOME/bin/kc.sh build
# Kích hoạt: Admin Console → Realm Settings → Events → Event listeners
# Thêm "custom-event-listener"
7. KeycloakのJSONロギング
集中ログと統合するには、JSON ログを出力するように Keycloak を構成します。
# Bật JSON logging
bin/kc.sh start \
--log=console \
--log-console-output=json
# Hoặc qua environment variables
KC_LOG=console
KC_LOG_CONSOLE_OUTPUT=json
7.1 JSON ログ出力のサンプル
{
"timestamp": "2026-03-15T10:30:45.123Z",
"level": "INFO",
"loggerClassName": "org.keycloak.events",
"loggerName": "org.keycloak.events",
"message": "type=LOGIN, realmId=my-realm, clientId=my-app, userId=abc-123, ipAddress=192.168.1.100",
"threadName": "executor-thread-1",
"threadId": 42,
"hostName": "keycloak-0",
"processName": "keycloak",
"processId": 1
}
7.2 ログレベルの構成
# Cấu hình log levels cho events
bin/kc.sh start \
--log=console \
--log-console-output=json \
--log-level=INFO \
--log-level=org.keycloak.events:DEBUG
# Environment variables
KC_LOG_LEVEL=INFO
KC_LOG_LEVEL=org.keycloak.events:DEBUG
8.ELKスタックの統合
一元的に分析するために、Keycloak ログを ELK スタック (Elasticsearch、Logstash、Kibana) に送信します。
8.1 一般的なアーキテクチャ
Keycloak (JSON logs)
↓
Filebeat (log shipper)
↓
Logstash (processing & enrichment)
↓
Elasticsearch (storage & indexing)
↓
Kibana (visualization & dashboards)
8.2 Filebeat の設定
# filebeat.yml
filebeat.inputs:
- type: container
paths:
- /var/log/containers/keycloak-*.log
processors:
- decode_json_fields:
fields: ["message"]
target: "keycloak"
overwrite_keys: true
- add_fields:
target: ""
fields:
service.name: keycloak
environment: production
output.logstash:
hosts: ["logstash:5044"]
8.3 Logstash パイプライン
# logstash/pipeline/keycloak.conf
input {
beats {
port => 5044
}
}
filter {
if [service][name] == "keycloak" {
# Parse Keycloak event message
if [keycloak][message] =~ "^type=" {
kv {
source => "[keycloak][message]"
field_split => ", "
value_split => "="
target => "kc_event"
}
mutate {
add_field => {
"event_type" => "%{[kc_event][type]}"
"realm" => "%{[kc_event][realmId]}"
"client_id" => "%{[kc_event][clientId]}"
}
}
}
# GeoIP enrichment
if [kc_event][ipAddress] {
geoip {
source => "[kc_event][ipAddress]"
target => "geo"
}
}
# Detect suspicious patterns
if [kc_event][type] == "LOGIN_ERROR" {
mutate {
add_tag => ["login_failure"]
}
}
}
}
output {
if [service][name] == "keycloak" {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "keycloak-events-%{+YYYY.MM.dd}"
}
}
}
8.4 キバナダッシュボード
監視する Kibana ダッシュボードを作成します。
- ログイン成功率/失敗率— 時間の経過に伴う棒グラフ
- よくあるログインエラー— エラーの種類別の円グラフ
- 地理的位置によるログイン— 地図の視覚化
- IP によるログイン失敗— ブルートフォース検出テーブル
- ユーザー登録動向— 日別の折れ線グラフ
- 管理操作の監査— 完全な詳細を含むデータテーブル
9. Grafana Loki の統合
Grafana Loki は、ELK よりも軽量なログ集約ソリューションであり、Kubernetes 環境に適しています。
9.1 Promtail の構成
# promtail-config.yml
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: keycloak
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
regex: keycloak
action: keep
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
- source_labels: [__meta_kubernetes_pod_name]
target_label: pod
pipeline_stages:
- json:
expressions:
level: level
logger: loggerName
message: message
timestamp: timestamp
- labels:
level:
logger:
- match:
selector: '{app="keycloak"} |~ "type=LOGIN|type=REGISTER|type=LOGOUT"'
stages:
- regex:
expression: 'type=(?P<event_type>\w+), realmId=(?P<realm>[\w-]+), clientId=(?P<client_id>[\w-]+), userId=(?P<user_id>[\w-]+)'
- labels:
event_type:
realm:
9.2 Grafana ダッシュボードのクエリ
# Login failures trong 1 giờ qua
{app="keycloak"} |~ "type=LOGIN_ERROR" | json | count_over_time({app="keycloak"} |~ "LOGIN_ERROR" [1h])
# Login events theo realm
sum by (realm) (count_over_time({app="keycloak"} |~ "type=LOGIN" [5m]))
# Top IPs với login failures
{app="keycloak"} |~ "type=LOGIN_ERROR" | regexp `ipAddress=(?P<ip>[\d.]+)` | count by (ip) | sort desc | limit 10
10. SIEM統合
Keycloakイベントをセキュリティ情報およびイベント管理(SIEM)システムと統合します。
10.1 Splunk の統合
# Cấu hình Filebeat ship đến Splunk HEC
output.logstash:
enabled: false
output.http:
enabled: true
hosts: ["https://splunk-hec:8088"]
path: "/services/collector/event"
headers:
Authorization: "Splunk <HEC_TOKEN>"
format: json
10.2 SIEM の使用例
| 使用事例 | イベントパターン | アクション |
|---|---|---|
| ブルートフォース検出 | 同じ IP からの複数の LOGIN_ERROR | アラート + IP ブロック |
| アカウント乗っ取り | GeoIP からのログインは異常です | アラート + MFA が必要 |
| 権限昇格 | 管理者が管理者ロールを割り当てます | アラート + レビュー |
| データの引き出し | 異常なトークンリクエストが多い | アラート + セッションの取り消し |
| 不審な登録 | 同じIPからの複数のREGISTER | アラート + キャプチャ |
11. 監査のコンプライアンス
11.1 SOC2 要件
| SOC2制御 | キークロークの実装 |
|---|---|
| CC6.1— 論理アクセスのセキュリティ | LOGIN、LOGIN_ERROR、PASSWORD 変更のイベントログ |
| CC6.2— ユーザー認証 | MFA イベント、登録イベント |
| CC6.3— アクセス許可 | ロール/権限変更の管理者イベント |
| CC7.2— セキュリティ監視 | ログイン失敗時のリアルタイムアラート |
| CC8.1— 変更管理 | 表現を含む管理イベント |
11.2 HIPAA 要件
| HIPAA コントロール | キークロークの実装 |
|---|---|
| §164.312(b)— 監査制御 | すべてのイベント タイプ、表現を含む管理イベントを有効にする |
| §164.312(d)— 本人認証 | 認証試行のイベントログ |
| §164.308(a)(5)— セキュリティ意識 | 不審なアクティビティの電子メール通知 |
11.3 保持ポリシー
# Cấu hình event retention
# SOC2: minimum 1 năm
# HIPAA: minimum 6 năm
# Trong Keycloak (built-in store)
# Realm Settings → Events → Expiration: 365 days
# Trong Elasticsearch (centralized logging)
# ILM Policy:
# - Hot: 30 days (SSD)
# - Warm: 335 days (HDD)
# - Cold/Frozen: 5+ years (S3/GCS)
# - Delete: 7 years
12. アラートの自動化
12.1 プロメテウスのアラート
Keycloakはメトリクスを次のように公開します。/メトリクスエンドポイント (メトリクスを有効にする必要があります):
# Bật metrics
bin/kc.sh start --metrics-enabled=true
# prometheus-alerts.yml
groups:
- name: keycloak-security
rules:
- alert: HighLoginFailureRate
expr: |
sum(rate(keycloak_login_error_total[5m])) by (realm)
/
sum(rate(keycloak_login_total[5m])) by (realm)
> 0.3
for: 5m
labels:
severity: warning
annotations:
summary: "High login failure rate in realm {{ $labels.realm }}"
description: "Login failure rate is {{ $value | humanizePercentage }} (threshold: 30%)"
- alert: BruteForceDetected
expr: |
sum(increase(keycloak_login_error_total[5m])) by (realm) > 50
for: 2m
labels:
severity: critical
annotations:
summary: "Possible brute-force attack on realm {{ $labels.realm }}"
description: "{{ $value }} login failures in 5 minutes"
- alert: UnusualRegistrationSpike
expr: |
sum(increase(keycloak_registrations_total[10m])) by (realm) > 100
for: 5m
labels:
severity: warning
annotations:
summary: "Unusual registration spike in realm {{ $labels.realm }}"
12.2 アラートマネージャーのルーティング
# alertmanager.yml
route:
receiver: default
routes:
- match:
severity: critical
receiver: pagerduty-security
continue: true
- match:
severity: critical
receiver: slack-security
- match:
severity: warning
receiver: slack-ops
receivers:
- name: default
email_configs:
- to: [email protected]
- name: slack-security
slack_configs:
- api_url: https://hooks.slack.com/services/xxx
channel: '#security-alerts'
title: '{{ .GroupLabels.alertname }}'
text: '{{ .CommonAnnotations.description }}'
- name: pagerduty-security
pagerduty_configs:
- service_key: <pagerduty-integration-key>
severity: critical
13. ベストプラクティス
- ログイン イベントと管理者イベントの両方を有効にする— システム内のアクティビティを見逃さないでください。
- イベントを外部システムに送信する— 組み込みのイベント ストアだけに依存しないでください。長期保存には ELK/Loki/SIEM を使用してください。
- 管理イベント表現をオンにする— 完全な監査のために、管理操作のリクエスト/レスポンス本文を保存します。
- 適切な保持期間を設定する— コンプライアンス要件に準拠します (SOC2: 1 年、HIPAA: 6 年)。
- ログイン失敗率を監視する— ブルートフォース検出とアカウント乗っ取りに対するアラートを設定します。
- イベントを関連付ける— Keycloakイベントとアプリケーションログを組み合わせて、全体像を把握します。
- イベントログを保護する— ログ データには PII が含まれているため、保存中および転送中に暗号化してアクセスを制限する必要があります。