generated from coulomb/repo-seed
401 lines
14 KiB
Markdown
401 lines
14 KiB
Markdown
# Enterprise Access-Control Integration
|
|
|
|
Date: 2026-05-04
|
|
|
|
## Purpose
|
|
|
|
This note explains how Markitect's access-control gateway should integrate with
|
|
enterprise IAM while respecting the local NetKingdom/key-cape direction.
|
|
|
|
The answer is yes: trust zones and access groups can map to canonical directory
|
|
group membership, but Markitect should not trust raw AD group names directly.
|
|
The enterprise shape should be:
|
|
|
|
```text
|
|
OIDC/SAML/SCIM identity and directory plane
|
|
-> canonical subject claims
|
|
-> policy map and/or policy decision point
|
|
-> Markitect policy gateway
|
|
-> filtered document/query/context results
|
|
```
|
|
|
|
Markitect is the policy enforcement point for Markdown knowledge results. It
|
|
should validate and normalize identity data through adapters, then call a policy
|
|
decision point through the existing policy interfaces.
|
|
|
|
## Canonical Enterprise Shape
|
|
|
|
The canonical enterprise pattern is the PEP/PDP/PIP/PAP split:
|
|
|
|
| Component | Markitect fit |
|
|
| --- | --- |
|
|
| PEP: policy enforcement point | `AccessPolicyGateway` at query, search, context, workflow, export, and assisted-prompt boundaries. |
|
|
| PDP: policy decision point | Local label policy for development; OpenFGA/SpiceDB, OPA/Rego, Cedar, or enterprise authorization service through adapters. |
|
|
| PIP: policy information point | NetKingdom/key-cape OIDC claims, directory group resolution, object labels, backend metadata, workflow context, and environment attributes. |
|
|
| PAP: policy administration point | Enterprise IAM/policy administration, plus versioned Markitect mapping files for labels, actions, trust zones, and emergency rules. |
|
|
|
|
This keeps Markitect small and auditable. It enforces decisions where Markdown
|
|
knowledge leaves a boundary, but it does not become the enterprise directory,
|
|
SSO provider, or policy administration system.
|
|
|
|
## Local Infrastructure Fit
|
|
|
|
The local canon already points the right way:
|
|
|
|
- NetKingdom SSO is the reference identity provider.
|
|
- Keycloak is the reference OIDC provider, with privacyIDEA-backed MFA.
|
|
- key-cape is the lightweight OIDC/profile-enforcement path for local,
|
|
sandbox, and bootstrap scenarios.
|
|
- Services should trust OIDC tokens, validate issuer/audience/signature/expiry,
|
|
and authorize from explicit roles/scopes.
|
|
|
|
Markitect should therefore consume the NetKingdom IAM profile rather than
|
|
create its own identity standard.
|
|
|
|
## Enterprise Reference Architecture
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
AD["AD / LDAP / HRIS"] --> SCIM["SCIM / Directory Sync<br/>(PIP)"]
|
|
SCIM --> IdP["NetKingdom SSO<br/>Keycloak / key-cape-compatible OIDC"]
|
|
IdP --> Token["OIDC Access Token<br/>roles, scopes, groups, org, assurance"]
|
|
Token --> Mapper["Identity Claim Mapper"]
|
|
Mapper --> Subject["PolicySubject"]
|
|
Source["Markdown objects<br/>labels, paths, trust zones"] --> Object["PolicyObject"]
|
|
Subject --> Gateway["Markitect AccessPolicyGateway<br/>(PEP)"]
|
|
Object --> Gateway
|
|
Gateway --> PDP["Policy Decision Point<br/>local / OpenFGA / OPA / Cedar"]
|
|
PDP --> Decision["PolicyDecision + audit metadata"]
|
|
Decision --> Boundary["Filtered query/search/context results"]
|
|
```
|
|
|
|
### Identity Plane
|
|
|
|
OIDC should be the default authentication path for users and services. SAML may
|
|
remain relevant for enterprise federation, but Markitect should normalize both
|
|
into the same subject shape.
|
|
|
|
The canonical accepted claims should follow the NetKingdom IAM profile:
|
|
|
|
- `iss`
|
|
- `sub`
|
|
- `aud`
|
|
- `exp`
|
|
- `iat`
|
|
- `scope` or `scp`
|
|
- `preferred_username`
|
|
- `roles` or `realm_access.roles`
|
|
- recommended `groups`, `azp`, `email`, `name`
|
|
|
|
For humans, Authorization Code + PKCE is the right login flow. For services,
|
|
client credentials or workload identity should produce short-lived service
|
|
tokens. OAuth token exchange can support hub-to-hub delegation where a service
|
|
acts on behalf of a user.
|
|
|
|
### Directory And Group Plane
|
|
|
|
Enterprise directories remain authoritative for group membership. Provisioning
|
|
should use a standard such as SCIM where possible; AD/LDAP synchronization into
|
|
Keycloak is also reasonable when NetKingdom owns the identity plane.
|
|
|
|
Important design rule:
|
|
|
|
```text
|
|
directory groups -> canonical roles/scopes/trust labels -> Markitect subject
|
|
```
|
|
|
|
Avoid:
|
|
|
|
```text
|
|
raw AD group name -> direct Markitect privilege
|
|
```
|
|
|
|
Reasons:
|
|
|
|
- AD group names change and often encode organizational accidents.
|
|
- Token group claims can be too large for large organizations.
|
|
- Privilege should be expressed as app roles/scopes or an explicit mapping file.
|
|
- Group membership freshness must be visible in the decision trail.
|
|
|
|
For Microsoft Entra-style group claims, large tenants may hit token group
|
|
overage. Markitect should therefore support a group-resolution adapter rather
|
|
than assuming all groups are always present in the token.
|
|
|
|
### Policy Plane
|
|
|
|
The existing Markitect interfaces already provide the main policy boundary:
|
|
|
|
```text
|
|
AccessPolicyGateway.authorize(subject, action, object_id, context)
|
|
AccessPolicyGateway.filter_results(subject, action, results, context)
|
|
AccessPolicyGateway.explain_decision(decision_id)
|
|
```
|
|
|
|
The existing data models also fit enterprise needs:
|
|
|
|
- `PolicySubject`: identity, roles, groups/labels, allowed actions, attributes.
|
|
- `PolicyObject`: path, labels, trust zone, attributes.
|
|
- `PolicyDecision`: stable decision id, effect, reason, labels, trust zone,
|
|
metadata.
|
|
- `PolicyFilterResult`: filtered results, decisions, diagnostics, summary.
|
|
|
|
The adapter seams are also correct:
|
|
|
|
- `RelationshipPolicyAdapter` for OpenFGA/SpiceDB/Zanzibar-style checks.
|
|
- `RulePolicyAdapter` for OPA/Rego, Cedar, or other ABAC engines.
|
|
|
|
This follow-up adds the missing interface layer:
|
|
|
|
```text
|
|
OIDC token or SAML assertion -> verified EnterpriseIdentity -> PolicySubject
|
|
```
|
|
|
|
Concrete adapters must validate issuer, audience, expiry, signature, and
|
|
assurance metadata before any authorization decision is made. The core package
|
|
now exposes protocol/data boundaries for this without taking a dependency on
|
|
Keycloak, Entra, LDAP, SCIM, OpenFGA, OPA, or Cedar client libraries.
|
|
|
|
The current Markitect-side implementation provides deterministic local
|
|
building blocks:
|
|
|
|
- `NetKingdomIdentityClaimsAdapter` validates required IAM-profile claims,
|
|
issuer, audience, token timestamps, roles/scopes, and production rejection of
|
|
local development issuers for already trusted claims or explicit JWT fixtures.
|
|
- `EnterprisePolicyMap` and `LocalEnterprisePolicyMapper` map groups, roles,
|
|
and scopes into `PolicySubject` labels, trust zones, actions, and diagnostic
|
|
attributes.
|
|
- `StaticDirectoryGroupResolver` models group freshness and overage without a
|
|
live directory dependency.
|
|
- `FlexAuthResourceManifest` describes Markitect knowledge resources for
|
|
future flex-auth registration.
|
|
- `LocalDecisionLogStore` provides a JSONL development/test sink for decision
|
|
records.
|
|
|
|
Live OIDC discovery, JWKS signature verification, directory synchronization,
|
|
central policy administration, and durable enterprise audit should be provided
|
|
by flex-auth/key-cape-facing adapters rather than Markitect core.
|
|
|
|
## Canonical Subject Mapping
|
|
|
|
Recommended normalized shape:
|
|
|
|
```yaml
|
|
subject:
|
|
id: "oidc:<issuer>#<sub>"
|
|
display_name: "Ada Lovelace"
|
|
principal_type: human | service
|
|
issuer: "https://sso.example.org/realms/netkingdom"
|
|
audience: ["markitect-tool"]
|
|
authorized_party: "markitect-cli"
|
|
roles: [viewer, operator]
|
|
scopes: [openid, profile, hub:read]
|
|
groups:
|
|
- /markitect/readers
|
|
- /platform/architecture
|
|
allowed_labels: [public, internal]
|
|
trust_zones: [public, internal]
|
|
assurance:
|
|
mfa: true
|
|
acr: "..."
|
|
amr: ["pwd", "otp"]
|
|
directory:
|
|
source: keycloak | entra | ldap | scim
|
|
refreshed_at: "2026-05-04T10:00:00Z"
|
|
```
|
|
|
|
The mapping file should translate enterprise groups and app roles to Markitect
|
|
labels and actions:
|
|
|
|
```yaml
|
|
id: markitect-enterprise-policy-map
|
|
issuer: https://sso.example.org/realms/netkingdom
|
|
audiences: [markitect-tool]
|
|
groups:
|
|
/markitect/readers:
|
|
allowed_labels: [public, internal]
|
|
actions: [query, search, read]
|
|
/markitect/stewards:
|
|
allowed_labels: [public, internal, restricted]
|
|
actions: [query, search, read, package, export]
|
|
roles:
|
|
admin:
|
|
allowed_labels: [public, internal, restricted]
|
|
actions: [query, search, read, package, export, policy-admin]
|
|
scopes:
|
|
markitect:read:
|
|
actions: [query, search, read]
|
|
trust_zones:
|
|
internal:
|
|
required_groups: [/markitect/readers]
|
|
```
|
|
|
|
Command-line subject mapping:
|
|
|
|
```text
|
|
mkt policy subject examples/policy/netkingdom-claims.yaml \
|
|
--policy-map examples/policy/enterprise-policy-map.yaml
|
|
```
|
|
|
|
## Data/Object Mapping
|
|
|
|
Markdown remains the source-friendly object labeling layer:
|
|
|
|
```yaml
|
|
---
|
|
policy:
|
|
labels: [internal]
|
|
trust_zone: internal
|
|
owner: team:platform-architecture
|
|
---
|
|
```
|
|
|
|
A Markitect knowledge base can publish an explicit flex-auth resource manifest:
|
|
|
|
```yaml
|
|
id: markitect-example-knowledge-base
|
|
system: markitect-tool
|
|
actions: [read, query, search, package, export]
|
|
resources:
|
|
- id: knowledge-base:markitect-example
|
|
type: knowledge_base
|
|
- id: document:internal-note
|
|
type: document
|
|
parent: knowledge-base:markitect-example
|
|
path: examples/policy/private/internal-note.md
|
|
labels: [internal]
|
|
trust_zone: internal
|
|
```
|
|
|
|
For enterprise environments, object metadata should eventually include:
|
|
|
|
- content labels/classification
|
|
- repository/path
|
|
- owning team or project
|
|
- business domain
|
|
- tenancy/org
|
|
- retention or export constraints
|
|
- provenance of label assignment
|
|
|
|
Path rules remain useful as a safety net, but document labels and backend
|
|
metadata should become authoritative for cached/context-package retrieval.
|
|
|
|
## Enforcement Points
|
|
|
|
Markitect should enforce policy at every point where knowledge leaves a
|
|
boundary:
|
|
|
|
- `mkt cache query`
|
|
- `mkt search`
|
|
- context package creation and activation
|
|
- workflow outputs
|
|
- assisted/LLM prompt assembly
|
|
- export/render steps
|
|
- backend APIs or future MCP resources
|
|
|
|
The highest-risk point is context assembly for agents. Before WP-0008 turns
|
|
context caches into agent memory, policy must be able to answer:
|
|
|
|
- who is activating the context package?
|
|
- which token or service account is acting?
|
|
- which labels/trust zones are included?
|
|
- was anything denied or redacted?
|
|
- can this package be reactivated later under the same policy assumptions?
|
|
|
|
## Interface Confirmation
|
|
|
|
The WP-0009 infrastructure is a good foundation. It already has:
|
|
|
|
- policy gateway protocol
|
|
- local label gateway
|
|
- explainable decisions
|
|
- filter-before-return behavior
|
|
- query/search integration
|
|
- relationship and rule adapter boundaries
|
|
|
|
This follow-up adds these provider-neutral interfaces in
|
|
`markitect_tool.policy.adapters`:
|
|
|
|
1. `IdentityClaimsAdapter`
|
|
- validates OIDC/JWT/SAML assertions
|
|
- normalizes NetKingdom/key-cape-compatible claims into
|
|
`EnterpriseIdentity`
|
|
|
|
2. `DirectoryGroupResolver`
|
|
- resolves group overage or stale claims
|
|
- supports SCIM/Graph/LDAP/Keycloak admin APIs behind adapters
|
|
- records freshness and source provenance
|
|
|
|
3. `EnterprisePolicyMapper`
|
|
- maps canonical groups, roles, scopes, and tenants to Markitect labels,
|
|
trust zones, actions, and object constraints
|
|
|
|
4. `DecisionLogStore`
|
|
- persists policy decisions for query/context/workflow runs
|
|
- records token hash, subject id, action, object id, policy version, result,
|
|
reason, and redaction status
|
|
|
|
5. workflow/runtime policy injection
|
|
- `subject_from_token`
|
|
- `policy_map`
|
|
- `required_assurance`
|
|
- `emergency_justification`
|
|
|
|
Concrete implementations remain future work. This is deliberate: key-cape and
|
|
NetKingdom should own identity issuance and profile compliance, while
|
|
Markitect owns normalization, policy envelopes, diagnostics, and enforcement at
|
|
knowledge boundaries.
|
|
|
|
## Recommended Direction
|
|
|
|
Do not make AD/LDAP/Entra groups a Markitect core dependency.
|
|
|
|
Instead:
|
|
|
|
1. Accept NetKingdom/key-cape-compatible OIDC tokens.
|
|
2. Normalize claims into `PolicySubject`.
|
|
3. Map enterprise groups/roles/scopes to Markitect labels/trust zones/actions.
|
|
4. Use the existing `AccessPolicyGateway` as the enforcement point.
|
|
5. Let OpenFGA/SpiceDB/OPA/Cedar attach through adapter protocols where a
|
|
deployment needs stronger central policy.
|
|
6. Persist decisions before using this for production agent memory or exports.
|
|
|
|
## flex-auth Boundary
|
|
|
|
The preferred long-term shape is a separate `flex-auth` service/repo under the
|
|
NetKingdom authorization umbrella. In that model, Markitect remains a resource
|
|
consumer and policy enforcement point. flex-auth owns the central resource
|
|
registry, enterprise group/role/scope mapping, external PDP adapters, and
|
|
durable decision logs.
|
|
|
|
The product survey, Keycloak/Entra analysis, and boundary recommendation now
|
|
live in the sibling `flex-auth` repo:
|
|
`flex-auth/docs/flex-auth-authorization-registry-research.md`.
|
|
|
|
Implementation follow-up is tracked there:
|
|
|
|
- `FLEX-WP-0002`: standalone policy-as-code core and check APIs.
|
|
- `FLEX-WP-0003`: flex-auth service-side Markitect consumer integration.
|
|
- `FLEX-WP-0004`: delegated PDP and directory adapters.
|
|
|
|
Markitect should not implement a live flex-auth service client until
|
|
`FLEX-WP-0003` stabilizes the resource-registration and check/batch_check API.
|
|
|
|
## Sources
|
|
|
|
- OpenID Connect Core 1.0: https://openid.net/specs/openid-connect-core-1_0.html
|
|
- OAuth 2.0 Token Exchange, RFC 8693: https://www.rfc-editor.org/rfc/rfc8693
|
|
- SCIM Protocol, RFC 7644: https://datatracker.ietf.org/doc/rfc7644
|
|
- NIST SP 800-162 ABAC guide: https://csrc.nist.gov/pubs/sp/800/162/upd2/final
|
|
- NIST glossary, Policy Enforcement Point:
|
|
https://csrc.nist.gov/glossary/term/policy_enforcement_point
|
|
- NIST glossary, Policy Decision Point:
|
|
https://csrc.nist.gov/glossary/term/policy_decision_point
|
|
- NIST glossary, Policy Information Point:
|
|
https://csrc.nist.gov/glossary/term/policy_information_point
|
|
- Keycloak Server Administration Guide: https://www.keycloak.org/docs/latest/server_admin/
|
|
- Microsoft Entra group claims: https://learn.microsoft.com/en-us/security/zero-trust/develop/configure-tokens-group-claims-app-roles
|
|
- OpenFGA concepts: https://openfga.dev/docs/concepts
|
|
- Open Policy Agent policy language: https://www.openpolicyagent.org/docs/policy-language
|
|
- Cedar policy language: https://docs.cedarpolicy.com/
|
|
- Local canon: `/home/worsch/the-custodian/canon/standards/iam-profile_v0.1.md`
|