認可モデル

DotID の認可サービスは、AWS IAM にインスパイアされた リソースベースアクセス制御 システムを実装しています。Policy Decision Point (PDP) として機能し、呼び出し元は 誰が * * 何を どのリソースに対して 行いたいかを記述し、サービスは ALLOW または DENY を返します。

基本概念

アカウント

アカウント はトップレベルの組織コンテナ(テナント)です。すべてのリソース FRN には account-id セグメントが含まれるため、テナントごとにポリシーをスコープすることができます。

グループ

グループ は 1 つ以上の プリンシパル (ユーザーまたはサービスアカウントクライアント)をまとめます。グループは認可モデルにおける「誰が」の軸です。

各メンバーは以下の情報を持つ GroupMember として保存されます:

  • principalId -- Keycloak のサブジェクト識別子(sub クレーム)。

  • principalType -- user または client

1 つのプリンシパルは複数のグループに所属できます。

ポリシーセットとポリシー

PolicySet は関連するポリシーをグループ化する名前付きコンテナです。

Policy は PostgreSQL jsonb として保存される JSON document に実際の認可ルールを保持します。完全なスキーマについては ポリシードキュメント形式 を参照してください。

パーミッション(バインディング)

パーミッション は以下の問いに答える三方向のバインディングです:

「グループ G のメンバーがアカウント A のリソースにアクセスする際、どのポリシーが適用されるか?」

その答えは、ポリシーセット S に含まれるポリシーです。

Principal  -->  GroupMember  -->  Group
                                   |
                               Permission
                                   |
                          Account (resource scope)
                                   |
                              PolicySet
                                   |
                              Policy (1..N)
                                   |
                            Statement[]

タプル (group_id, account_id, policy_set_id) は一意です。重複するバインディングは HTTP 409 で拒否されます。

評価アルゴリズム

PolicyDecisionService は典型的な 明示的拒否優先 の評価モデルを実装しています。1 つの認可チェックは以下の手順で処理されます:

  1. リソース FRN の解析 -- FRN 文字列を検証し、不正な識別子は即座に拒否します。

  2. Resource-based policy -- if a resource policy exists for the target FRN and explicitly allows/denies the action, return early.

  3. Root user bypass -- root users have implicit full access to their own account (like AWS root), no policy attachment needed. If the principal is a root user and the target resource belongs to the same account, return ALLOW with reason ROOT_USER_BYPASS.

  4. Resolve identity-based policies -- resolves group memberships via account assignments, IAM managed/inline policies, and permission set policies for the principal.

  5. パス 1 -- 明示的拒否"Effect": "Deny" を持つすべてのステートメントを反復処理します。いずれかのステートメントが一致した場合、即座に DENY を返します(拒否は常に優先されます)。

  6. SCP evaluation -- for principals in an organization, evaluate Service Control Policies. If the action is not allowed by any SCP, return DENY.

  7. パス 1 -- 明示的拒否"Effect": "Deny" を持つすべてのステートメントを反復処理します。いずれかのステートメントが一致した場合、即座に DENY を返します(拒否は常に優先されます)。

  8. Delegated Admin Allow -- if no identity policy granted access, check whether the principal qualifies as a delegated administrator:

    • The principal must be a root user (userType == "root").

    • The principal's account must have a delegation for the action's service namespace (the prefix before the first : in the action string, e.g., "audit" from "audit:Event:Read").

    • The namespace must be eligible for delegation (see below).

    • The target resource must belong to an account within the same organization as the delegation.

    • Requests targeting the principal's own account are skipped (root users already have full access on their own account).

    • Wildcard FRN targets (account segment *) are allowed.

    If all conditions pass, the check returns matchedStatement: "DelegatedAdminAllow" and proceeds to the permission boundary check.

    Namespace delegation eligibility

    Only operational and observability namespaces may be delegated. Governance and security-critical namespaces are permanently excluded to prevent privilege escalation:

    • iam -- not delegable. A delegate could modify or remove other users' permissions, including the root user's own policies.

    • org -- not delegable. Organization structure is a management-account-only concern.

    • scp -- not delegable. Delegating SCP management would allow weakening security guardrails across the organization.

    • sts -- not delegable. Cross-account role assumption is identity infrastructure, not an operational service.

    • audit -- delegable. Read-only audit log access for org-wide compliance visibility.

    • quota -- delegable. View and manage service quotas across the organization.

    Future namespaces follow the same rule: if delegating the namespace could allow the delegate to alter, escalate, or remove permissions for other principals, it must not be delegable.

  9. Permission boundary -- if a permission boundary is set for the user, verify the action is within the boundary. If not, return DENY.

  10. Return ALLOW -- if a matching allow statement (or delegation grant) survived all checks, return ALLOW.

  11. デフォルト拒否 :どのステートメントにも一致しなかった場合、 DENY を返します。

  12. 監査ログ -- デフォルト拒否を含むすべての判定が authorization_audit_log に永続化されます。

ステートメントマッチング

ステートメントは以下の 3 つすべて のサブチェックが通過した場合にのみ一致します:

アクションマッチング

  • 完全一致:"devices:Read""devices:Read" のみに一致します。

  • グローバルワイルドカード:"*" は任意のアクションに一致します。

  • サービスプレフィックスワイルドカード:"devices:*""devices:" で始まるすべてのアクションに一致します。

リソースマッチング

  • リテラル "*" は任意のリソースに一致します。

  • それ以外の場合、パターンは FRN として解析され、FrnMatcher を使用してセグメントごとに照合されます(FRN 仕様 を参照)。

条件マッチング

条件はリクエストの context マップに基づいて追加の制約を適用します。ステートメント内のすべてのオペレーターが通過する必要があります(AND ロジック)。

サポートされる条件オペレーター

オペレーター

セマンティクス

StringEquals

actual が期待値リストに含まれている必要があります(完全一致)。

StringNotEquals

actual が期待値リストに含まれていては なりません

StringLike

actual が少なくとも 1 つの glob パターンに一致する必要があります(* = 任意の文字列)。

Bool

actual.toString() が期待値リストに含まれている必要があります(例:"true")。

未知のオペレーターは false と評価され、警告がログに記録されます。

条件キーには dotid: プレフィックスを付けることができます(検索前に除去されます)。コンテキストキーは、元の形式と camelCase から snake_case に変換された形式の両方で検索されます。

バッチ評価

バッチエンドポイントは、プリンシパルに対するグループメンバーシップとポリシーを 1 回 読み込み、事前に読み込んだデータに対して各チェックを評価します。これは個別のリクエストを発行するよりも大幅に効率的です。

Capabilities

Capabilities are account-level business qualifications stored on the Account entity in the DotID authorization service. They are distinct from — and evaluated after — the SCP/IAM policy evaluation described above.

バッチ評価

  1. Roles, SCPs, and IAM policies are evaluated (steps 1–11 above).

  2. If the result is ALLOW, the target service checks whether the account holds the required capability for the requested operation.

  3. If the capability is absent, the service returns 403 Forbidden ("account not qualified contact platform support").

Capabilities are not part of the policy document format and are not evaluated by the Policy Decision Point. They are checked independently by each service after authorization passes.

Known capabilities:

  • enroll_things — register new devices in ThingHub

  • approve_licenses — approve and issue licenses in TrustMint

  • publish_marketplace — publish products to the Bazaar marketplace

  • manage_ota_rollouts — create and manage OTA rollouts in OTAForge

Capabilities are granted and revoked by platform admins in SuperCrew. Accounts start with no capabilities. See Access Control Layers for the full three-layer model (Role → SCP → Capability) and how these layers interact.

キャッシュ無効化

認可エンティティに対するすべての変更操作(作成、更新、削除)は、グローバルな ポリシーバージョン カウンターをインクリメントし、Server-Sent Events (SSE) を介して policy.changed イベントをブロードキャストします。

ダウンストリームキャッシュは以下のいずれかを行う必要があります:

  • GET /api/v1/events/streamサブスクライブ し、イベント受信時にキャッシュを無効化する、または

  • GET /api/v1/policy-version を定期的に ポーリング する。