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

6.4 KiB

id name namespace version status package allow_ttl actions owner caring
forgejo.application-access Forgejo authenticated application access forgejo:application v1 draft flexauth.forgejo.application 10s
application.access
railiance-apps
profile enforce
caring-0.4.0-rc2 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.

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
}
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"]})})
}
[
  {
    "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"
    }
  }
]