Contents
1. ID/アカウント管理要件(TC3 ガイドブックベース)
本セクションの概要
マルチテナント SaaS においては、テナント単位でユーザー情報・権限・監査ログを完全に分離することが最重要課題です。ここでは、TC3 が公開している「ID・アカウント管理要件チェックリスト」から、実装計画の出発点となる必須項目を抜粋し、ポイントごとに解説します。
1.1 必須要件一覧(TC3 チェックリスト)
以下は TC3 が定義する13項目のうち、特に実装時に注意すべき5点です。各項目は テナント分離・最小権限・監査可能性 の観点から抽出しています。
| 項目 | 内容 | 実装上の留意点 |
|---|---|---|
| テナントごとのユーザー属性分離 | テナント ID に基づくスキーマ分割または行レベルフィルタリングを徹底 | DB レイヤで tenant_id カラムを必須化し、全クエリに自動付与 |
| ロール・権限の階層管理 | 管理者/一般ユーザーといったロールをテナント単位で定義し、最小特権の原則を適用 | RBAC 設計時はロール継承ツリーを明文化 |
| 監査ログのテナントタグ付与 | 認証・認可イベントにテナント識別子を付与し、検索や保持期間を個別管理 | ログ出力フォーマットは JSON 化し、ELK 等で集約 |
| パスワードポリシーと MFA の強制 | テナントごとのセキュリティ要件に合わせてパスワードルール・多要素認証を一元管理 | ポリシーエンジンは外部化し、リアルタイムで更新可能に |
| 外部 IdP 連携のテナント別設定 | Google、Azure AD 等の外部 IdP をテナント単位で切り替える仕組みを提供 | IdP エイリアスと属性マッピングを自動生成するスクリプトが必要 |
出典:TC3 ガイドブック「ID・アカウント管理要件チェックリスト」(PDF ダウンロード)
2. Keycloak の基本概念とマルチテナント適用方法
本セクションの概要
Keycloak は レルム・クライアント・ロール・ユーザーフェデレーション という四つの主要コンポーネントで構成されます。これらをどのように組み合わせるかが、テナント分離方式(レルム単位 vs 共有レルム)選択の鍵となります。
2.1 レルム・クライアント・ロールの役割
| コンポーネント | 説明 | マルチテナントへの活用例 |
|---|---|---|
| レルム | 認証情報・設定を論理的に分離する領域。テナントごとに独立したデータベーススキーマを持つことができる。 | テナント毎に tenant-123 というレルムを作成し、パスワードポリシーやメールテンプレートを個別管理(Qiita 事例参照) |
| クライアント | OAuth2/OIDC・SAML の保護対象アプリケーション。テナントごとに別クライアント ID を割り当てることでリダイレクト URI を分離できる。 | tenant-123-app、tenant-456-app などテナント固有のクライアントを自動生成 |
| ロール | 権限の粒度を決める要素。レルム全体または特定クライアントに紐付く。 | admin-tenant-123、user-tenant-123 といったテナントスコープロールで最小権限を実現 |
2.2 ユーザーフェデレーションの活用
外部ディレクトリ(LDAP/AD)と同期させる機能です。テナントごとの社内 AD をそれぞれフェデレーション設定で接続すれば、Keycloak 側にユーザー情報を重複保存せずに済みます。
ポイント:フェデレーションは「認証委譲」だけでなく、属性マッピング(例:
tenant-id)を付与できる点がマルチテナント設計で有効です。
3. アーキテクチャ比較:レルム単位分離 vs 共有レルム+テナント属性
本セクションの概要
テナントごとに レルム を作る方式と、1つのレルム内で テナント属性(グループ・スコープ) によって区別する方式は、それぞれメリット・デメリットが異なります。運用コスト・拡張性・セキュリティ観点から比較し、選択指針を示します。
3.1 レルム単位分離の特徴
レルムごとに完全に設定が独立するため 「設定漏れ」 のリスクは最小化できます。一方でレルム数が増えると管理負荷が顕在化します。
| メリット | デメリット |
|---|---|
| テナントごとのパスワードポリシー・メールテンプレートを自由に変更可能 | レルム作成/削除が手動になるケースが多く、運用自動化が必須 |
| DB でもテーブル単位で分離できるためバックアップ・復元がテナント単位で実行可能 | カスタム拡張(イベントリスナー等)を全レルムに展開する際、デプロイ回数が増える |
| テナント間の権限境界が物理的に分かれるためセキュリティ監査がシンプル | テナント増加で Keycloak の管理コンソールが肥大化し、UI が遅くなることも |
根拠:Note に掲載された 2025 年の記事では「レルム単位のマルチテナントは運用コストが増大しやすい」と指摘されています(※ Note 記事: https://note.com/tsysk/n/nd8ced9e54df9)
3.2 共有レルム+テナント属性方式の特徴
1つのレルムで全テナントを管理するため リソース効率 が高く、共通機能のデプロイがシンプルになります。ただし 権限分離の設計が複雑 になる点に注意が必要です。
| 実装ポイント | 注意すべき点 |
|---|---|
テナント属性としてグループ を tenant-{id} の形式で作成し、ユーザーを所属させる |
グループ削除時に残存ロールやクライアントマッピングが残らないよう徹底的なクリーンアップが必要 |
クライアントスコープ tenant-{id}-read 等でトークンに属性を埋め込む |
スコープ漏れがあると他テナントのリソースへ不正アクセス可能になるため、ABAC ポリシーで必ずチェック |
| ロールベース + 属性ベース のハイブリッド制御 | RBAC だけでは属性情報を考慮できないケースが多いため、Keycloak の「ポリシーベース認可」機能を併用 |
4. 実装ガイド:Keycloak 25.x を使ったマルチテナント SSO 構築手順
本セクションの概要
Keycloak 25 系で新たに提供された ポリシーベース認可 と イベントリスナー拡張 を活用し、レルム単位・共有レルムいずれのパターンでもテナント属性による細粒度アクセス制御と監査ログ外部送信を実現します。
4.1 テナント属性ベースのポリシー例
以下は tenant-id クレームが 123 のユーザーだけにリソースへのアクセスを許可する JavaScript ポリシーです。Authorization Services に登録して Resource に紐付けます。
|
1 2 3 4 5 6 7 8 9 |
{ "name": "TenantAccessPolicy", "type": "js", "logic": "POSITIVE", "config": { "code": "var tenant = token.get('tenant_id');\nif (tenant == '123') { true } else { false };" } } |
4.2 認証成功時のイベントリスナーで ELK へ送信
Keycloak の Event Listener SPI にカスタム JAR をデプロイし、認証・認可イベントを JSON 形式で標準出力に流すだけで Fluent Bit が取得できます。
|
1 2 3 4 |
# カスタムリスナーデプロイ手順(概要) docker cp my-listener.jar keycloak:/opt/keycloak/providers/ kubectl rollout restart deployment/keycloak # 再起動でプラグインを有効化 |
参考:Keycloak 公式ドキュメント – Event Listener SPI (https://www.keycloak.org/docs/latest/server_development/#_event_listener_spi)
4.3 OIDC クライアント作成例(PKCE 有効化)
テナントごとにクライアントを自動生成し、pkceCodeChallengeMethod=S256 を必須化します。
|
1 2 3 4 5 6 7 8 |
kcadm.sh create clients -r $REALM \ -s clientId=tenant-123-app \ -s enabled=true \ -s 'redirectUris=["https://app.example.com/callback"]' \ -s publicClient=true \ -s standardFlowEnabled=true \ -s pkceCodeChallengeMethod=S256 |
4.4 外部 IdP のテナント別切替フロー
- テナント毎に
alias=google-tenant-123等で Identity Provider を登録。 - 認証フローに「テナント選択」画面(カスタム Authentication Flow)を挿入し、ユーザーが選んだ ID に応じて IdP エイリアスへリダイレクト。
- IdP Mapper で
tenant-idクレームをトークンに付与。
この構成により 単一 Keycloak インスタンス でテナント別外部 IdP を柔軟に運用できます。
5. 自動化・デプロイ・運用:CLI / Terraform / Ansible と Kubernetes 上のスケーラブル構成
本セクションの概要
マルチテナント環境では テナント追加/削除 が頻繁に発生します。そのたびに手作業で設定を行うとミスが起きやすくなるため、IaC(Infrastructure as Code)による自動化が不可欠です。ここでは kcadm.sh、Terraform、Ansible を用いたプロビジョニング例と、Kubernetes 上でのデプロイ・可観測性確保手順を示します。
5.1 kcadm.sh によるテナント自動プロビジョニング
以下シェルスクリプトは CI/CD パイプラインから呼び出す想定です。レルム作成 → デフォルトクライアント作成 → ログ出力 の流れを自動化します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#!/usr/bin/env bash set -euo pipefail REALM="master" TOKEN=$(kcadm.sh config credentials \ --server http://keycloak:8080 \ --realm $REALM \ --user admin \ --password "${KC_ADMIN_PASS}" | jq -r .access_token) # 例:テナント tenant-456 用レルム作成 kcadm.sh create realms -s realm=tenant-456 -s enabled=true -b # デフォルト OIDC クライアント作成 kcadm.sh create clients -r tenant-456 \ -s clientId=web-app \ -s publicClient=true \ -s standardFlowEnabled=true echo "✅ テナント tenant-456 のプロビジョニングが完了しました。" |
5.2 Terraform(Keycloak Provider)での宣言的管理
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
provider "keycloak" { client_id = "admin-cli" client_secret = var.keycloak_admin_secret url = "https://keycloak.example.com/auth" } resource "keycloak_realm" "tenant" { realm = var.tenant_id enabled = true } resource "keycloak_openid_client" "web_app" { realm_id = keycloak_realm.tenant.id client_id = "web-app" access_type = "PUBLIC" standard_flow_enabled = true redirect_uris = ["https://app.example.com/callback"] } |
5.3 Ansible(community.general.kcadm)での手順
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
- name: Create tenant realm community.general.kcadm: server_url: http://keycloak:8080/auth username: admin password: "{{ keycloak_admin_pass }}" command: create realms payload: realm: "{{ tenant_id }}" enabled: true - name: Add OIDC client to the new realm community.general.kcadm: server_url: http://keycloak:8080/auth username: admin password: "{{ keycloak_admin_pass }}" command: create clients -r {{ tenant_id }} payload: clientId: web-app publicClient: true standardFlowEnabled: true |
5.4 Docker イメージと Kubernetes デプロイ
Dockerfile(カスタムテーマ・プロバイダー同梱)
|
1 2 3 4 5 6 |
FROM quay.io/keycloak/keycloak:25.0 COPY ./themes /opt/keycloak/themes COPY ./providers/*.jar /opt/keycloak/providers/ ENV KC_DB=postgres \ KC_HOSTNAME=keycloak.example.com |
Kubernetes マニフェスト(OpenShift でも同様)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
apiVersion: apps/v1 kind: Deployment metadata: name: keycloak spec: replicas: 3 selector: matchLabels: app: keycloak template: metadata: labels: app: keycloak spec: containers: - name: keycloak image: myrepo/keycloak-custom:latest envFrom: - secretRef: name: keycloak-secret ports: - containerPort: 8080 livenessProbe: httpGet: path: /realms/master/protocol/openid-connect/token port: 8080 initialDelaySeconds: 30 periodSeconds: 15 readinessProbe: httpGet: path: /realms/master/protocol/openid-connect/auth port: 8080 initialDelaySeconds: 10 periodSeconds: 10 --- apiVersion: v1 kind: Service metadata: name: keycloak spec: type: LoadBalancer selector: app: keycloak ports: - port: 80 targetPort: 8080 |
5.5 可観測性・バックアップ戦略
| 項目 | 実装例 |
|---|---|
| ログ集約 | Keycloak の standalone.xml を JSON ログに切替え、標準出力へ流すだけで Fluent Bit が取得。ELK スタックへ転送し検索可能な監査ログ基盤を構築。 |
| ヘルスチェック | K8s の livenessProbe/readinessProbe を上記エンドポイントに設定し、障害検知と自動復旧を実現。 |
| バックアップ | PostgreSQL の PITR と kcadm.sh get realms -r <realm> -f export.json によるレルムエクスポートを週次で実行し、S3 等に保存。 |
5.6 セキュリティベストプラクティス(簡易チェックリスト)
- パスワードポリシー:最低12文字・大文字・小文字・数字・特殊文字を必須 (
passwordPolicy="length(12) and upperCase(1) and lowerCase(1) and digits(1) and specialChars(1)") - MFA 強制:全テナントで TOTP または WebAuthn を
required-action=CONFIGURE_TOTPで必須化。 - クライアントシークレット管理:K8s Secret に格納し、Pod 起動時に環境変数経由で注入。ローテーションは
kcadm.sh update clients/<id> -r <realm> -s secret=<new>で自動化。 - 最小権限の原則:テナント属性ロールだけを付与し、不要な管理者権限は除外。
6. まとめ(要点)
- ID/アカウント管理要件は TC3 のチェックリストに沿って、テナント単位のユーザー属性・権限・監査ログを徹底的に分離すべきです。
- Keycloak の四大コンポーネント(レルム・クライアント・ロール・フェデレーション)を正しく組み合わせることで、マルチテナント設計の土台が構築できます。
- レルム単位分離は設定独立性とセキュリティ面で優れる一方、運用コストが増大します(Note 2025 記事参照)。
- 共有レルム+テナント属性方式はリソース効率が高くスケールしやすいが、RBAC と ABAC のハイブリッド設計が必須です。
- Keycloak 25.x のポリシーベース認可・イベントリスナーを活用すれば、テナント属性ベースの細粒度アクセス制御と監査ログ外部送信が実装可能です。
- 自動化は
kcadm.sh、Terraform、Ansible のいずれかで IaC 化し、Kubernetes 上にスケーラブルなデプロイを行うのがベストプラクティスです。
これらのポイントを踏まえて実装すれば、Keycloak を中心とした 安全・拡張性の高いマルチテナント SSO が実現できます。
参考文献
-
TC3 「ID・アカウント管理要件チェックリスト」
https://info.tc3.co.jp/saas-id-management-guide-book -
Qiita 記事「Keycloak のレルム単位分離でマルチテナントを実装」
https://qiita.com/ntaka329/items/ec582768365f4fe4b919 -
Note(2025年)「レルム単位のマルチテナントは運用コストが増大しやすい」
https://note.com/tsysk/n/nd8ced9e54df9 -
Keycloak 公式ドキュメント – Event Listener SPI
https://www.keycloak.org/docs/latest/server_development/#_event_listener_spi -
Keycloak 公式 GitHub(Provider)
https://github.com/keycloak/keycloak