feat(policy): add credential grant authorization package
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02e47-6aac-7ee1-914d-0584c75d3c81
This commit is contained in:
parent
df54c1b8f5
commit
acbaa4a7c9
12 changed files with 476 additions and 3 deletions
|
|
@ -103,6 +103,36 @@ func TestRunCheckOpsWarden(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRunRailiancePlatformCredentialGrantContract(t *testing.T) {
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
code := run([]string{"test-policy", "--file", railiancePlatformPath("policy_package.md")}, &stdout, &stderr)
|
||||||
|
if code != 0 || !strings.Contains(stdout.String(), `"valid": true`) {
|
||||||
|
t.Fatalf("test-policy code = %d, stderr = %s, stdout = %s", code, stderr.String(), stdout.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout.Reset()
|
||||||
|
stderr.Reset()
|
||||||
|
code = run([]string{
|
||||||
|
"check",
|
||||||
|
"--registry", railiancePlatformPath("registry_snapshot.json"),
|
||||||
|
"--policy", railiancePlatformPath("policy_package.md"),
|
||||||
|
"--request", railiancePlatformPath("check_request_allow.json"),
|
||||||
|
}, &stdout, &stderr)
|
||||||
|
if code != 0 {
|
||||||
|
t.Fatalf("check code = %d, stderr = %s", code, stderr.String())
|
||||||
|
}
|
||||||
|
var decision api.DecisionEnvelope
|
||||||
|
if err := json.Unmarshal(stdout.Bytes(), &decision); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if decision.Effect != api.DecisionEffectAllow || decision.Reason != "credential_grant_allowed" {
|
||||||
|
t.Fatalf("decision = %s/%s; want allow/credential_grant_allowed", decision.Effect, decision.Reason)
|
||||||
|
}
|
||||||
|
if decision.Binding == nil || decision.Binding.Context["requested_ttl_seconds"] != float64(900) {
|
||||||
|
t.Fatalf("binding = %+v; want normalized numeric TTL", decision.Binding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestServeOpsWardenCheckContract(t *testing.T) {
|
func TestServeOpsWardenCheckContract(t *testing.T) {
|
||||||
logPath := filepath.Join(t.TempDir(), "decisions.jsonl")
|
logPath := filepath.Join(t.TempDir(), "decisions.jsonl")
|
||||||
engine, err := buildEngine(context.Background(), opsPath("registry_snapshot.json"), opsPath("policy_package.md"), logPath)
|
engine, err := buildEngine(context.Background(), opsPath("registry_snapshot.json"), opsPath("policy_package.md"), logPath)
|
||||||
|
|
@ -370,6 +400,10 @@ func opsPath(name string) string {
|
||||||
return filepath.Join("..", "..", "examples", "ops-warden", name)
|
return filepath.Join("..", "..", "examples", "ops-warden", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func railiancePlatformPath(name string) string {
|
||||||
|
return filepath.Join("..", "..", "examples", "railiance-platform", name)
|
||||||
|
}
|
||||||
|
|
||||||
func opsWardenProductionSignRequest(subjectID, actor, actorType, principal string, ttlHours float64) api.CheckRequest {
|
func opsWardenProductionSignRequest(subjectID, actor, actorType, principal string, ttlHours float64) api.CheckRequest {
|
||||||
return api.CheckRequest{
|
return api.CheckRequest{
|
||||||
ID: "check:ops-warden-production-" + actor,
|
ID: "check:ops-warden-production-" + actor,
|
||||||
|
|
|
||||||
16
docs/railiance-platform-action-vocabulary.md
Normal file
16
docs/railiance-platform-action-vocabulary.md
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Railiance Platform credential-grant action vocabulary
|
||||||
|
|
||||||
|
flex-auth uses one protected-system action for the credential broker:
|
||||||
|
|
||||||
|
| Action | Resource type | Meaning |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `issue` | `credential-grant` | Authorize issuance of one bounded credential lease from a registered grant. |
|
||||||
|
|
||||||
|
The request subject is the requesting actor. `context.bound_subject` is the
|
||||||
|
identity to which the resulting credential is bound. Grant id, credential
|
||||||
|
type, issuer, audience, TTL ceiling, permitted actor classes, purposes, and
|
||||||
|
delivery modes are registry-owned resource attributes, not caller assertions.
|
||||||
|
|
||||||
|
`context.requested_ttl_seconds` is numeric seconds. Parsing the broker's source
|
||||||
|
duration string happens once in the selected wire translator; the policy
|
||||||
|
rejects strings to prevent unit ambiguity.
|
||||||
16
examples/railiance-platform/README.md
Normal file
16
examples/railiance-platform/README.md
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Railiance Platform credential-grant example
|
||||||
|
|
||||||
|
This package provides the flex-auth side of `FLEX-WP-0012`: registered grant
|
||||||
|
metadata, representative requester subjects, a default-deny `issue` policy,
|
||||||
|
and fixtures for TTL, actor type, purpose, delivery mode, and unknown grants.
|
||||||
|
|
||||||
|
The wire translation is intentionally outside the policy. Both candidate
|
||||||
|
integration shapes must emit `requested_ttl_seconds` as a positive number;
|
||||||
|
duration strings such as `15m` are rejected rather than guessed.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run ./cmd/flex-auth load-registry --file examples/railiance-platform/registry_snapshot.json
|
||||||
|
go run ./cmd/flex-auth test-policy --file examples/railiance-platform/policy_package.md
|
||||||
|
go run ./cmd/flex-auth check --registry examples/railiance-platform/registry_snapshot.json --policy examples/railiance-platform/policy_package.md --request examples/railiance-platform/check_request_allow.json
|
||||||
|
go run ./cmd/flex-auth check --registry examples/railiance-platform/registry_snapshot.json --policy examples/railiance-platform/policy_package.md --request examples/railiance-platform/check_request_deny_unknown.json
|
||||||
|
```
|
||||||
21
examples/railiance-platform/check_request_allow.json
Normal file
21
examples/railiance-platform/check_request_allow.json
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"id": "check:credential-grant-allow-http-shape",
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"subject": {
|
||||||
|
"id": "agent:codex/railiance-platform",
|
||||||
|
"type": "Agent"
|
||||||
|
},
|
||||||
|
"action": "issue",
|
||||||
|
"resource": {
|
||||||
|
"id": "credential-grant:rapp-postgres/audit-core-runtime",
|
||||||
|
"type": "credential-grant",
|
||||||
|
"system": "railiance-platform"
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"actor_type": "approved-agent",
|
||||||
|
"bound_subject": "agent:codex/railiance-platform",
|
||||||
|
"purpose": "audit-core-runtime",
|
||||||
|
"delivery_mode": "exec-env",
|
||||||
|
"requested_ttl_seconds": 900
|
||||||
|
}
|
||||||
|
}
|
||||||
21
examples/railiance-platform/check_request_deny_unknown.json
Normal file
21
examples/railiance-platform/check_request_deny_unknown.json
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"id": "check:credential-grant-unknown-http-shape",
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"subject": {
|
||||||
|
"id": "agent:codex/railiance-platform",
|
||||||
|
"type": "Agent"
|
||||||
|
},
|
||||||
|
"action": "issue",
|
||||||
|
"resource": {
|
||||||
|
"id": "credential-grant:unknown/grant",
|
||||||
|
"type": "credential-grant",
|
||||||
|
"system": "railiance-platform"
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"actor_type": "approved-agent",
|
||||||
|
"bound_subject": "agent:codex/railiance-platform",
|
||||||
|
"purpose": "unknown",
|
||||||
|
"delivery_mode": "exec-env",
|
||||||
|
"requested_ttl_seconds": 900
|
||||||
|
}
|
||||||
|
}
|
||||||
59
examples/railiance-platform/policy_fixtures.yaml
Normal file
59
examples/railiance-platform/policy_fixtures.yaml
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
- id: fixture:credential-grant-allow
|
||||||
|
request: &allow_request
|
||||||
|
id: check:credential-grant-allow
|
||||||
|
tenant: tenant:platform
|
||||||
|
subject: {id: agent:codex/railiance-platform, type: Agent}
|
||||||
|
action: issue
|
||||||
|
resource:
|
||||||
|
id: credential-grant:rapp-postgres/audit-core-runtime
|
||||||
|
type: credential-grant
|
||||||
|
system: railiance-platform
|
||||||
|
attributes:
|
||||||
|
grant_id: rapp-postgres/audit-core-runtime
|
||||||
|
credential_type: openbao-database-credential
|
||||||
|
issuer: openbao
|
||||||
|
audience: audit-core
|
||||||
|
max_ttl_seconds: 3600
|
||||||
|
allowed_actor_types: [human-operator, approved-agent, ci-runner]
|
||||||
|
allowed_purposes: [audit-core-runtime]
|
||||||
|
allowed_delivery_modes: [exec-env]
|
||||||
|
context: &allow_context
|
||||||
|
actor_type: approved-agent
|
||||||
|
bound_subject: agent:codex/railiance-platform
|
||||||
|
purpose: audit-core-runtime
|
||||||
|
delivery_mode: exec-env
|
||||||
|
requested_ttl_seconds: 900
|
||||||
|
expect: {effect: allow, reason: credential_grant_allowed}
|
||||||
|
- id: fixture:credential-grant-ttl-deny
|
||||||
|
request:
|
||||||
|
<<: *allow_request
|
||||||
|
id: check:credential-grant-ttl-deny
|
||||||
|
context: {<<: *allow_context, requested_ttl_seconds: 5400}
|
||||||
|
expect: {effect: deny, reason: ttl_out_of_bounds}
|
||||||
|
- id: fixture:credential-grant-actor-type-deny
|
||||||
|
request:
|
||||||
|
<<: *allow_request
|
||||||
|
id: check:credential-grant-actor-deny
|
||||||
|
context: {<<: *allow_context, actor_type: unapproved-agent}
|
||||||
|
expect: {effect: deny, reason: actor_type_not_allowed}
|
||||||
|
- id: fixture:credential-grant-purpose-deny
|
||||||
|
request:
|
||||||
|
<<: *allow_request
|
||||||
|
id: check:credential-grant-purpose-deny
|
||||||
|
context: {<<: *allow_context, purpose: unrelated-purpose}
|
||||||
|
expect: {effect: deny, reason: purpose_not_allowed}
|
||||||
|
- id: fixture:credential-grant-delivery-deny
|
||||||
|
request:
|
||||||
|
<<: *allow_request
|
||||||
|
id: check:credential-grant-delivery-deny
|
||||||
|
context: {<<: *allow_context, delivery_mode: chat}
|
||||||
|
expect: {effect: deny, reason: delivery_mode_not_allowed}
|
||||||
|
- id: fixture:credential-grant-unknown-deny
|
||||||
|
request:
|
||||||
|
<<: *allow_request
|
||||||
|
id: check:credential-grant-unknown-deny
|
||||||
|
resource:
|
||||||
|
id: credential-grant:unknown/grant
|
||||||
|
type: credential-grant
|
||||||
|
system: railiance-platform
|
||||||
|
expect: {effect: deny, reason: unknown_grant}
|
||||||
158
examples/railiance-platform/policy_package.md
Normal file
158
examples/railiance-platform/policy_package.md
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
---
|
||||||
|
id: railiance-platform.credential-grant.issue
|
||||||
|
name: Railiance Platform credential-grant issuance
|
||||||
|
namespace: railiance-platform:credential-grant
|
||||||
|
version: v1
|
||||||
|
status: ready
|
||||||
|
package: flexauth.railiance_platform.credential_grant
|
||||||
|
actions: [issue]
|
||||||
|
owner: team:platform-security
|
||||||
|
fixtures: [policy_fixtures.yaml]
|
||||||
|
caring:
|
||||||
|
profile: caring-0.4.0-rc2
|
||||||
|
enforce: false
|
||||||
|
canonical_roles: [Operator]
|
||||||
|
organization_relations: [ServiceProvider]
|
||||||
|
scopes:
|
||||||
|
- level: Platform
|
||||||
|
id: platform:credential-broker
|
||||||
|
tenant: tenant:platform
|
||||||
|
planes: [Identity, Secret, Audit]
|
||||||
|
capabilities: [Use, Operate, Audit]
|
||||||
|
exposure_modes: [Metadata]
|
||||||
|
conditions: [PurposeBound, TimeLimited, Logged]
|
||||||
|
restrictions: [PrivilegeEscalationBlocked, SecretAccessBlocked]
|
||||||
|
activation: {mode: local}
|
||||||
|
metadata:
|
||||||
|
source: examples/railiance-platform/policy_package.md
|
||||||
|
ttl_unit: seconds
|
||||||
|
---
|
||||||
|
|
||||||
|
# Railiance Platform Credential-grant Issuance
|
||||||
|
|
||||||
|
The policy evaluates non-secret grant metadata only. Duration strings such as
|
||||||
|
`15m` must be parsed by the eventual wire translator into the numeric
|
||||||
|
`context.requested_ttl_seconds`; Rego never infers duration units.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
```rego
|
||||||
|
import future.keywords.if
|
||||||
|
import future.keywords.in
|
||||||
|
|
||||||
|
decision := {"effect": "allow", "reason": "credential_grant_allowed"} if {
|
||||||
|
allowed
|
||||||
|
} else := {"effect": "deny", "reason": first_denial} if {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
allowed if {
|
||||||
|
input.action == "issue"
|
||||||
|
input.resource.system == "railiance-platform"
|
||||||
|
input.resource.type == "credential-grant"
|
||||||
|
input.tenant == "tenant:platform"
|
||||||
|
known_grant
|
||||||
|
actor_type_allowed
|
||||||
|
purpose_allowed
|
||||||
|
delivery_mode_allowed
|
||||||
|
ttl_allowed
|
||||||
|
has_bound_subject
|
||||||
|
}
|
||||||
|
|
||||||
|
default first_denial := "no_matching_rule"
|
||||||
|
|
||||||
|
first_denial := "wrong_action" if {
|
||||||
|
input.action != "issue"
|
||||||
|
} else := "wrong_system" if {
|
||||||
|
input.resource.system != "railiance-platform"
|
||||||
|
} else := "wrong_resource_type" if {
|
||||||
|
input.resource.type != "credential-grant"
|
||||||
|
} else := "wrong_tenant" if {
|
||||||
|
input.tenant != "tenant:platform"
|
||||||
|
} else := "unknown_grant" if {
|
||||||
|
not known_grant
|
||||||
|
} else := "actor_type_not_allowed" if {
|
||||||
|
not actor_type_allowed
|
||||||
|
} else := "purpose_not_allowed" if {
|
||||||
|
not purpose_allowed
|
||||||
|
} else := "delivery_mode_not_allowed" if {
|
||||||
|
not delivery_mode_allowed
|
||||||
|
} else := "ttl_out_of_bounds" if {
|
||||||
|
not ttl_allowed
|
||||||
|
} else := "missing_subject_binding" if {
|
||||||
|
not has_bound_subject
|
||||||
|
}
|
||||||
|
|
||||||
|
known_grant if {
|
||||||
|
is_string(input.resource.attributes.grant_id)
|
||||||
|
input.resource.id == sprintf("credential-grant:%s", [input.resource.attributes.grant_id])
|
||||||
|
is_number(input.resource.attributes.max_ttl_seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
actor_type_allowed if {
|
||||||
|
is_string(input.context.actor_type)
|
||||||
|
input.context.actor_type in input.resource.attributes.allowed_actor_types
|
||||||
|
}
|
||||||
|
|
||||||
|
purpose_allowed if {
|
||||||
|
is_string(input.context.purpose)
|
||||||
|
input.context.purpose != ""
|
||||||
|
input.context.purpose in input.resource.attributes.allowed_purposes
|
||||||
|
}
|
||||||
|
|
||||||
|
delivery_mode_allowed if {
|
||||||
|
is_string(input.context.delivery_mode)
|
||||||
|
input.context.delivery_mode in input.resource.attributes.allowed_delivery_modes
|
||||||
|
}
|
||||||
|
|
||||||
|
ttl_allowed if {
|
||||||
|
is_number(input.context.requested_ttl_seconds)
|
||||||
|
input.context.requested_ttl_seconds > 0
|
||||||
|
input.context.requested_ttl_seconds <= input.resource.attributes.max_ttl_seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
has_bound_subject if {
|
||||||
|
is_string(input.context.bound_subject)
|
||||||
|
input.context.bound_subject != ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
```rego test
|
||||||
|
package flexauth.railiance_platform.credential_grant_test
|
||||||
|
|
||||||
|
import future.keywords.if
|
||||||
|
import data.flexauth.railiance_platform.credential_grant
|
||||||
|
|
||||||
|
request := {
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"subject": {"id": "agent:codex/railiance-platform", "type": "Agent"},
|
||||||
|
"action": "issue",
|
||||||
|
"resource": {
|
||||||
|
"id": "credential-grant:rapp-postgres/audit-core-runtime",
|
||||||
|
"type": "credential-grant",
|
||||||
|
"system": "railiance-platform",
|
||||||
|
"attributes": {
|
||||||
|
"grant_id": "rapp-postgres/audit-core-runtime",
|
||||||
|
"max_ttl_seconds": 3600,
|
||||||
|
"allowed_actor_types": ["human-operator", "approved-agent", "ci-runner"],
|
||||||
|
"allowed_purposes": ["audit-core-runtime"],
|
||||||
|
"allowed_delivery_modes": ["exec-env"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"context": {"actor_type": "approved-agent", "bound_subject": "agent:codex/railiance-platform", "purpose": "audit-core-runtime", "delivery_mode": "exec-env", "requested_ttl_seconds": 900}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_allow if {
|
||||||
|
credential_grant.decision.effect == "allow" with input as request
|
||||||
|
}
|
||||||
|
|
||||||
|
test_ttl_string_denied if {
|
||||||
|
credential_grant.decision.reason == "ttl_out_of_bounds" with input as object.union(request, {"context": object.union(request.context, {"requested_ttl_seconds": "15m"})})
|
||||||
|
}
|
||||||
|
|
||||||
|
test_unknown_grant_denied if {
|
||||||
|
credential_grant.decision.reason == "unknown_grant" with input as object.union(request, {"resource": {"id": "credential-grant:missing", "type": "credential-grant", "system": "railiance-platform", "attributes": {}}})
|
||||||
|
}
|
||||||
|
```
|
||||||
19
examples/railiance-platform/protected_system_manifest.yaml
Normal file
19
examples/railiance-platform/protected_system_manifest.yaml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
id: railiance-platform
|
||||||
|
name: Railiance Platform Credential Broker
|
||||||
|
resource_types:
|
||||||
|
- name: credential-grant
|
||||||
|
scope_level: Resource
|
||||||
|
planes: [Identity, Secret, Audit]
|
||||||
|
metadata:
|
||||||
|
description: Non-secret authorization metadata for a bounded credential lease.
|
||||||
|
actions:
|
||||||
|
- name: issue
|
||||||
|
capabilities: [Use, Operate, Audit]
|
||||||
|
planes: [Identity, Secret, Audit]
|
||||||
|
exposure_modes: [Metadata]
|
||||||
|
metadata:
|
||||||
|
required_context: [actor_type, bound_subject, purpose, delivery_mode, requested_ttl_seconds]
|
||||||
|
caring_profiles: [caring-0.4.0-rc2]
|
||||||
|
metadata:
|
||||||
|
flex_auth_contract: protected-system-v0
|
||||||
|
tenant: tenant:platform
|
||||||
45
examples/railiance-platform/registry_snapshot.json
Normal file
45
examples/railiance-platform/registry_snapshot.json
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"systems": [
|
||||||
|
{
|
||||||
|
"id": "railiance-platform",
|
||||||
|
"name": "Railiance Platform Credential Broker",
|
||||||
|
"resource_types": [
|
||||||
|
{
|
||||||
|
"name": "credential-grant",
|
||||||
|
"scope_level": "Resource",
|
||||||
|
"planes": ["Identity", "Secret", "Audit"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"name": "issue",
|
||||||
|
"capabilities": ["Use", "Operate", "Audit"],
|
||||||
|
"planes": ["Identity", "Secret", "Audit"],
|
||||||
|
"exposure_modes": ["Metadata"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"caring_profiles": ["caring-0.4.0-rc2"],
|
||||||
|
"metadata": {"tenant": "tenant:platform"}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resource_manifests": [
|
||||||
|
{
|
||||||
|
"id": "railiance-platform-credential-grants",
|
||||||
|
"system": "railiance-platform",
|
||||||
|
"resources": [
|
||||||
|
{"id": "credential-grant:rapp-postgres/audit-core-runtime", "type": "credential-grant", "owner": "team:platform-security", "attributes": {"grant_id": "rapp-postgres/audit-core-runtime", "credential_type": "openbao-database-credential", "issuer": "openbao", "audience": "audit-core", "max_ttl_seconds": 3600, "allowed_actor_types": ["human-operator", "approved-agent", "ci-runner"], "allowed_purposes": ["audit-core-runtime"], "allowed_delivery_modes": ["exec-env"]}},
|
||||||
|
{"id": "credential-grant:rapp-postgres/audit-core-migration", "type": "credential-grant", "owner": "team:platform-security", "attributes": {"grant_id": "rapp-postgres/audit-core-migration", "credential_type": "openbao-database-credential", "issuer": "openbao", "audience": "audit-core", "max_ttl_seconds": 1800, "allowed_actor_types": ["human-operator", "approved-agent", "ci-runner"], "allowed_purposes": ["audit-core-migration"], "allowed_delivery_modes": ["exec-env"]}},
|
||||||
|
{"id": "credential-grant:ops-warden/warden-sign", "type": "credential-grant", "owner": "team:platform-security", "attributes": {"grant_id": "ops-warden/warden-sign", "credential_type": "openbao-token", "issuer": "openbao", "audience": "ops-warden", "max_ttl_seconds": 3600, "allowed_actor_types": ["human-operator", "approved-agent", "ci-runner"], "allowed_purposes": ["flex-auth-openbao-smoke", "ops-warden-production-sign-smoke"], "allowed_delivery_modes": ["exec-env", "response-wrap", "local-token-file", "kubernetes-auth"]}}
|
||||||
|
],
|
||||||
|
"actions": ["issue"],
|
||||||
|
"caring_profile": "caring-0.4.0-rc2",
|
||||||
|
"metadata": {"tenant": "tenant:platform"}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tenants": [{"id": "tenant:platform", "name": "Platform Tenant"}],
|
||||||
|
"subjects": [
|
||||||
|
{"id": "operator:platform", "type": "Human", "roles": ["Operator"], "tenant": "tenant:platform"},
|
||||||
|
{"id": "agent:codex/railiance-platform", "type": "Agent", "roles": ["Operator"], "tenant": "tenant:platform"},
|
||||||
|
{"id": "ci:railiance-platform", "type": "Automation", "roles": ["Operator"], "tenant": "tenant:platform"}
|
||||||
|
]
|
||||||
|
}
|
||||||
44
examples/railiance-platform/resource_manifest.yaml
Normal file
44
examples/railiance-platform/resource_manifest.yaml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
id: railiance-platform-credential-grants
|
||||||
|
system: railiance-platform
|
||||||
|
resources:
|
||||||
|
- id: credential-grant:rapp-postgres/audit-core-runtime
|
||||||
|
type: credential-grant
|
||||||
|
owner: team:platform-security
|
||||||
|
attributes:
|
||||||
|
grant_id: rapp-postgres/audit-core-runtime
|
||||||
|
credential_type: openbao-database-credential
|
||||||
|
issuer: openbao
|
||||||
|
audience: audit-core
|
||||||
|
max_ttl_seconds: 3600
|
||||||
|
allowed_actor_types: [human-operator, approved-agent, ci-runner]
|
||||||
|
allowed_purposes: [audit-core-runtime]
|
||||||
|
allowed_delivery_modes: [exec-env]
|
||||||
|
- id: credential-grant:rapp-postgres/audit-core-migration
|
||||||
|
type: credential-grant
|
||||||
|
owner: team:platform-security
|
||||||
|
attributes:
|
||||||
|
grant_id: rapp-postgres/audit-core-migration
|
||||||
|
credential_type: openbao-database-credential
|
||||||
|
issuer: openbao
|
||||||
|
audience: audit-core
|
||||||
|
max_ttl_seconds: 1800
|
||||||
|
allowed_actor_types: [human-operator, approved-agent, ci-runner]
|
||||||
|
allowed_purposes: [audit-core-migration]
|
||||||
|
allowed_delivery_modes: [exec-env]
|
||||||
|
- id: credential-grant:ops-warden/warden-sign
|
||||||
|
type: credential-grant
|
||||||
|
owner: team:platform-security
|
||||||
|
attributes:
|
||||||
|
grant_id: ops-warden/warden-sign
|
||||||
|
credential_type: openbao-token
|
||||||
|
issuer: openbao
|
||||||
|
audience: ops-warden
|
||||||
|
max_ttl_seconds: 3600
|
||||||
|
allowed_actor_types: [human-operator, approved-agent, ci-runner]
|
||||||
|
allowed_purposes: [flex-auth-openbao-smoke, ops-warden-production-sign-smoke]
|
||||||
|
allowed_delivery_modes: [exec-env, response-wrap, local-token-file, kubernetes-auth]
|
||||||
|
actions: [issue]
|
||||||
|
caring_profile: caring-0.4.0-rc2
|
||||||
|
metadata:
|
||||||
|
flex_auth_contract: resource-registration-v0
|
||||||
|
tenant: tenant:platform
|
||||||
23
examples/railiance-platform/subject_manifest.yaml
Normal file
23
examples/railiance-platform/subject_manifest.yaml
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
id: subjects:railiance-platform
|
||||||
|
tenants:
|
||||||
|
- id: tenant:platform
|
||||||
|
name: Platform Tenant
|
||||||
|
subjects:
|
||||||
|
- id: operator:platform
|
||||||
|
type: Human
|
||||||
|
display_name: Platform Operator
|
||||||
|
organization_relation: ServiceProvider
|
||||||
|
roles: [Operator]
|
||||||
|
tenant: tenant:platform
|
||||||
|
- id: agent:codex/railiance-platform
|
||||||
|
type: Agent
|
||||||
|
display_name: Railiance Platform Agent
|
||||||
|
organization_relation: ServiceProvider
|
||||||
|
roles: [Operator]
|
||||||
|
tenant: tenant:platform
|
||||||
|
- id: ci:railiance-platform
|
||||||
|
type: Automation
|
||||||
|
display_name: Railiance Platform CI
|
||||||
|
organization_relation: ServiceProvider
|
||||||
|
roles: [Operator]
|
||||||
|
tenant: tenant:platform
|
||||||
|
|
@ -135,7 +135,7 @@ place duration normalization explicitly.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: FLEX-WP-0012-T02
|
id: FLEX-WP-0012-T02
|
||||||
status: todo
|
status: done
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "7e9c4e59-e59c-4617-a87f-99142952fe78"
|
state_hub_task_id: "7e9c4e59-e59c-4617-a87f-99142952fe78"
|
||||||
```
|
```
|
||||||
|
|
@ -168,11 +168,20 @@ id. Verify against the real binary: `test-policy`, `load-registry`, and
|
||||||
Done when all Rego tests and fixtures pass and default-deny is demonstrated
|
Done when all Rego tests and fixtures pass and default-deny is demonstrated
|
||||||
for an unregistered grant.
|
for an unregistered grant.
|
||||||
|
|
||||||
|
Completed 2026-08-23. `examples/railiance-platform/` registers all three
|
||||||
|
current catalog grants and representative requester subjects. The policy uses
|
||||||
|
numeric `requested_ttl_seconds`; duration parsing belongs to the selected wire
|
||||||
|
translator, and strings are explicitly denied. Three embedded Rego tests and
|
||||||
|
six external fixtures pass, covering allow, TTL, actor type, purpose, delivery
|
||||||
|
mode, and unknown-grant default deny. Real `load-registry` and `check` commands
|
||||||
|
returned `credential_grant_allowed` for the registered runtime grant and
|
||||||
|
`unknown_grant` for an unregistered id.
|
||||||
|
|
||||||
## T03 - Implement the decided integration and prove it end to end
|
## T03 - Implement the decided integration and prove it end to end
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: FLEX-WP-0012-T03
|
id: FLEX-WP-0012-T03
|
||||||
status: todo
|
status: wait
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "3335b2b7-cf1a-411d-95b3-03c4b4c35659"
|
state_hub_task_id: "3335b2b7-cf1a-411d-95b3-03c4b4c35659"
|
||||||
```
|
```
|
||||||
|
|
@ -199,6 +208,10 @@ request metadata only. Nothing in this workplan should read, log, or persist a
|
||||||
credential value; if a task appears to require one, that is a signal the
|
credential value; if a task appears to require one, that is a signal the
|
||||||
design has drifted, not a reason to handle secrets here.
|
design has drifted, not a reason to handle secrets here.
|
||||||
|
|
||||||
|
Waiting on T01's wire-translation decision. The policy-side normalized request
|
||||||
|
contract is implemented; either integration option must produce its numeric
|
||||||
|
TTL field without changing policy semantics.
|
||||||
|
|
||||||
Done when allow and all four denials are demonstrated against the real helper
|
Done when allow and all four denials are demonstrated against the real helper
|
||||||
over real HTTP, `go test ./...` is green, and `gofmt`/`go vet` are clean.
|
over real HTTP, `go test ./...` is green, and `gofmt`/`go vet` are clean.
|
||||||
|
|
||||||
|
|
@ -206,7 +219,7 @@ over real HTTP, `go test ./...` is green, and `gofmt`/`go vet` are clean.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: FLEX-WP-0012-T04
|
id: FLEX-WP-0012-T04
|
||||||
status: todo
|
status: wait
|
||||||
priority: low
|
priority: low
|
||||||
state_hub_task_id: "40015a87-040c-4d48-b360-fd5566dbc552"
|
state_hub_task_id: "40015a87-040c-4d48-b360-fd5566dbc552"
|
||||||
```
|
```
|
||||||
|
|
@ -225,3 +238,7 @@ actually meant before promising an endpoint.
|
||||||
|
|
||||||
Update `docs/` with a credential-grant action vocabulary, matching the
|
Update `docs/` with a credential-grant action vocabulary, matching the
|
||||||
existing per-consumer vocabulary docs.
|
existing per-consumer vocabulary docs.
|
||||||
|
|
||||||
|
The source-side action vocabulary is now present at
|
||||||
|
`docs/railiance-platform-action-vocabulary.md`; final consumer/deployment
|
||||||
|
handoff waits on T01 and T03.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue