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
This commit is contained in:
parent
d328a26010
commit
ca0cb75729
24 changed files with 2980 additions and 4 deletions
196
examples/forgejo-application-access/policy.md
Normal file
196
examples/forgejo-application-access/policy.md
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
---
|
||||
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"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
38
examples/forgejo-application-access/registry_snapshot.json
Normal file
38
examples/forgejo-application-access/registry_snapshot.json
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"systems": [
|
||||
{
|
||||
"id": "forgejo",
|
||||
"name": "Synthetic test only",
|
||||
"resource_types": [
|
||||
{
|
||||
"name": "application"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "application.access"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"subjects": [],
|
||||
"resource_manifests": [
|
||||
{
|
||||
"id": "forgejo.synthetic.resources",
|
||||
"system": "forgejo",
|
||||
"resources": [
|
||||
{
|
||||
"id": "application:forgejo",
|
||||
"type": "application",
|
||||
"attributes": {
|
||||
"identity_issuer": "https://issuer.invalid",
|
||||
"tenant": "tenant:synthetic"
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
"application.access"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue