flex-auth/examples/user-engine/policy_package.md
tegwick b74756791a
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 32s
Authorize scoped public registration applicants
2026-08-14 09:26:12 +02:00

5.7 KiB

id name namespace version status package actions owner fixtures caring activation metadata
user-engine.portal.authorize user-engine portal authorization user-engine:portal v1 ready flexauth.user_engine.portal
*
team:platform-security
policy_fixtures.yaml
profile enforce canonical_roles organization_relations scopes planes capabilities exposure_modes conditions restrictions
caring-0.4.0-rc2 false
Operator
Administrator
User
ServiceProvider
Customer
level id tenant
Platform platform:user-engine platform:root
level id
Tenant tenant:dynamic
Identity
Policy
Audit
Read
Create
Update
Delete
Grant
Audit
Metadata
Logged
PrivilegeEscalationBlocked
TenantBoundary
mode
local
source flex_auth_contract
examples/user-engine/policy_package.md protected-system-v0

user-engine portal authorization

The portal supplies verified identity claims. This policy enforces platform, tenant, and self boundaries and denies unknown role/context combinations.

import future.keywords.if
import future.keywords.in

roles := object.get(object.get(input.subject, "attributes", {}), "roles", [])
subject_tenant := object.get(input.subject, "tenant", "")
resource_tenant := object.get(input.resource, "tenant", input.tenant)
self_request := object.get(input.context, "self", false)
resource_type := object.get(input.resource, "type", "")
subject_issuer := object.get(object.get(input.subject, "attributes", {}), "issuer", "")

registration_applicant if {
  "registration-applicant" in roles
  subject_issuer == "urn:netkingdom:public-registration"
  same_tenant
  startswith(input.action, "registration.")
  resource_type in {"user-engine:registration", "user-engine:registration-factor"}
}

decision := {"effect": "allow", "reason": "platform_operator"} if {
  valid_system
  "platform-operator" in roles
} else := {"effect": "allow", "reason": "tenant_admin"} if {
  valid_system
  same_tenant
  "tenant-admin" in roles
} else := {"effect": "allow", "reason": "self_service"} if {
  valid_system
  same_tenant
  self_request == true
} else := {"effect": "allow", "reason": "registration_applicant"} if {
  valid_system
  registration_applicant
} else := {"effect": "deny", "reason": first_denial} if { true }

valid_system if { input.resource.system == "user-engine" }
same_tenant if { subject_tenant != ""; subject_tenant == input.tenant; resource_tenant == input.tenant }

default first_denial := "no_matching_role_or_context"
first_denial := "wrong_system" if { not valid_system }
else := "cross_tenant" if { subject_tenant != ""; subject_tenant != input.tenant }

Tests

package flexauth.user_engine.portal_test
import future.keywords.if
import data.flexauth.user_engine.portal

base := {"tenant": "tenant:friendly:binky", "subject": {"id": "u1", "type": "human", "tenant": "tenant:friendly:binky", "attributes": {"roles": []}}, "action": "me.read", "resource": {"id": "u1", "type": "user-engine:me", "system": "user-engine", "tenant": "tenant:friendly:binky"}, "context": {"self": true}}

test_self_allowed if { portal.decision.effect == "allow" with input as base }
test_tenant_admin_allowed if { portal.decision.effect == "allow" with input as object.union(base, {"subject": object.union(base.subject, {"attributes": {"roles": ["tenant-admin"]}}), "context": {}}) }
test_platform_operator_cross_tenant_allowed if { portal.decision.effect == "allow" with input as object.union(base, {"subject": object.union(base.subject, {"tenant": "platform:root", "attributes": {"roles": ["platform-operator"]}}), "context": {}}) }
test_cross_tenant_denied if { portal.decision.reason == "cross_tenant" with input as object.union(base, {"subject": object.union(base.subject, {"tenant": "tenant:family:other"})}) }
test_missing_role_denied if { portal.decision.effect == "deny" with input as {"tenant": "tenant:friendly:binky", "subject": {"id": "u1", "type": "human", "tenant": "tenant:friendly:binky", "attributes": {"roles": []}}, "action": "membership.write", "resource": {"id": "m1", "type": "user-engine:membership", "system": "user-engine", "tenant": "tenant:friendly:binky"}, "context": {}} }
test_wrong_system_denied if { portal.decision.reason == "wrong_system" with input as object.union(base, {"resource": object.union(base.resource, {"system": "other"})}) }
test_registration_applicant_allowed if { portal.decision.reason == "registration_applicant" with input as {"tenant": "tenant:friendly:binky", "subject": {"id": "applicant", "type": "human", "tenant": "tenant:friendly:binky", "attributes": {"roles": ["registration-applicant"], "issuer": "urn:netkingdom:public-registration"}}, "action": "registration.start", "resource": {"id": "new", "type": "user-engine:registration", "system": "user-engine", "tenant": "tenant:friendly:binky"}, "context": {}} }
test_registration_applicant_other_action_denied if { portal.decision.effect == "deny" with input as {"tenant": "tenant:friendly:binky", "subject": {"id": "applicant", "type": "human", "tenant": "tenant:friendly:binky", "attributes": {"roles": ["registration-applicant"], "issuer": "urn:netkingdom:public-registration"}}, "action": "membership.write", "resource": {"id": "m1", "type": "user-engine:membership", "system": "user-engine", "tenant": "tenant:friendly:binky"}, "context": {}} }
test_registration_applicant_wrong_issuer_denied if { portal.decision.effect == "deny" with input as {"tenant": "tenant:friendly:binky", "subject": {"id": "applicant", "type": "human", "tenant": "tenant:friendly:binky", "attributes": {"roles": ["registration-applicant"], "issuer": "untrusted"}}, "action": "registration.start", "resource": {"id": "new", "type": "user-engine:registration", "system": "user-engine", "tenant": "tenant:friendly:binky"}, "context": {}} }