access-engine/examples/forgejo-application-access/policy.md
tegwick ca0cb75729
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 1m22s
Add producer-owned authenticated Go decision client and validated Forgejo profile
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a14bfc-9643-7872-aa12-98326dcf25e7
2026-10-18 01:20:05 +02:00

196 lines
6.4 KiB
Markdown

---
id: forgejo.application-access
name: Forgejo authenticated application access
namespace: forgejo:application
version: v1
status: draft
package: flexauth.forgejo.application
allow_ttl: 10s
actions: [application.access]
owner: railiance-apps
caring:
profile: caring-0.4.0-rc2
enforce: false
---
This source policy enforces the original three-group any-of in the sole PDP.
The registry identifies the application tenant and admitted issuer. Fresh identity
and UserInfo facts arrive only in request context from the admitted Forgejo caller,
which verifies issuer JOSE and current UserInfo before this request. They are not
static subject registry attributes. This policy requires aal2 assurance.
The PEP independently verifies the ID token and supplies fresh UserInfo groups;
the authenticated workload caller may represent only the Forgejo system. A
decision authorizes one login callback, never a later HTTP/Git/SSH/API operation.
The accompanying registry is synthetic test data, not an estate admission.
```rego
import rego.v1
default decision := {"effect": "deny", "reason": "application_access_refused"}
original_groups := {"forge-admins", "forge-coulomb-owners", "forge-coulomb-readers"}
decision := {"effect": "allow", "reason": "current_authenticated_application_access"} if {
input.action == "application.access"
object.get(input, "purpose", "") == ""
input.resource.id == "application:forgejo"
input.resource.type == "application"
input.resource.system == "forgejo"
input.tenant == input.resource.tenant
input.tenant == input.resource.attributes.tenant
input.subject.tenant == input.tenant
input.context.identity_tenant == input.tenant
input.subject.id == input.context.identity_subject
input.subject.type == input.context.identity_principal_type
input.subject.type == "human"
input.context.identity_issuer == input.resource.attributes.identity_issuer
input.context.identity_assurance == "aal2"
is_array(input.context.required_groups_any_of)
count(input.context.required_groups_any_of) == 3
{g | g := input.context.required_groups_any_of[_]} == original_groups
is_array(input.context.current_userinfo_groups)
every value in input.context.current_userinfo_groups { is_string(value) }
some group in input.context.current_userinfo_groups
group in original_groups
is_string(input.context.decisionpep_request_nonce)
count(input.context.decisionpep_request_nonce) == 64
}
```
```rego test
package flexauth.forgejo.application_test
import rego.v1
import data.flexauth.forgejo.application
valid_request := {
"tenant": "tenant:synthetic",
"subject": {
"id": "user:synthetic",
"type": "human",
"tenant": "tenant:synthetic"
},
"action": "application.access",
"resource": {
"id": "application:forgejo",
"type": "application",
"system": "forgejo",
"tenant": "tenant:synthetic",
"attributes": {
"tenant": "tenant:synthetic",
"identity_issuer": "https://issuer.invalid"
}
},
"context": {
"identity_tenant": "tenant:synthetic",
"identity_subject": "user:synthetic",
"identity_principal_type": "human",
"identity_issuer": "https://issuer.invalid",
"identity_assurance": "aal2",
"current_userinfo_groups": [
"forge-admins"
],
"required_groups_any_of": [
"forge-admins",
"forge-coulomb-owners",
"forge-coulomb-readers"
],
"decisionpep_request_nonce": "0000000000000000000000000000000000000000000000000000000000000000"
}
}
test_original_groups_allow if {
every group in ["forge-admins", "forge-coulomb-owners", "forge-coulomb-readers"] {
application.decision.effect == "allow" with input as object.union(valid_request, {"context": object.union(valid_request.context, {"current_userinfo_groups": [group]})})
}
}
test_outsider_denied if {
application.decision.effect == "deny" with input as object.union(valid_request, {"context": object.union(valid_request.context, {"current_userinfo_groups": ["outsider"]})})
}
test_missing_identity_denied if {
application.decision.effect == "deny" with input as object.union(object.remove(valid_request, ["context"]), {"context": object.remove(valid_request.context, ["identity_issuer"])})
}
test_low_assurance_denied if {
application.decision.effect == "deny" with input as object.union(valid_request, {"context": object.union(valid_request.context, {"identity_assurance": "aal1"})})
}
test_changed_group_contract_denied if {
application.decision.effect == "deny" with input as object.union(valid_request, {"context": object.union(valid_request.context, {"required_groups_any_of": ["outsider"]})})
}
```
```yaml fixture
[
{
"id": "allowed-original-group",
"request": {
"tenant": "tenant:synthetic",
"subject": {
"id": "user:synthetic",
"type": "human",
"tenant": "tenant:synthetic"
},
"action": "application.access",
"resource": {
"id": "application:forgejo",
"type": "application",
"system": "forgejo",
"tenant": "tenant:synthetic",
"attributes": {
"tenant": "tenant:synthetic",
"identity_issuer": "https://issuer.invalid"
}
},
"context": {
"identity_tenant": "tenant:synthetic",
"identity_subject": "user:synthetic",
"identity_principal_type": "human",
"identity_issuer": "https://issuer.invalid",
"identity_assurance": "aal2",
"current_userinfo_groups": [
"forge-admins"
],
"required_groups_any_of": [
"forge-admins",
"forge-coulomb-owners",
"forge-coulomb-readers"
],
"decisionpep_request_nonce": "0000000000000000000000000000000000000000000000000000000000000000"
}
},
"expect": {
"effect": "allow",
"reason": "current_authenticated_application_access"
}
},
{
"id": "missing-identity-context",
"request": {
"tenant": "tenant:synthetic",
"subject": {
"id": "user:synthetic",
"type": "human",
"tenant": "tenant:synthetic"
},
"action": "application.access",
"resource": {
"id": "application:forgejo",
"type": "application",
"system": "forgejo",
"tenant": "tenant:synthetic",
"attributes": {
"tenant": "tenant:synthetic",
"identity_issuer": "https://issuer.invalid"
}
},
"context": {}
},
"expect": {
"effect": "deny",
"reason": "application_access_refused"
}
}
]
```