Local Development: RBAC¶
Use this page when developing or testing Kubernetes-style RBAC manifests for multi-root and multi-intermediate CA flows.
Current Boundary¶
RBAC is file-based and declarative. Developers should not write SQL to set up RBAC.
The server can load YAML manifests at startup and apply them into internal SQLite metadata tables. The database remains an implementation detail; Git-versioned YAML files are the source of truth.
The live certificate signing path still uses the current single active ca.Authority. RBAC enforcement before signing is future write-path work. Do not assume enrollment alone grants signing permission when implementing that future work.
Configure RBAC Loading¶
RBAC is configured in the main IronRoot config.yaml:
rbac:
enabled: true
mode: file
paths:
- config/rbac/*.yaml
- config/rbac/*.yml
ironroot-dev dev-init generates:
.localdev/config/rbac/local-rbac.yaml
and writes absolute RBAC glob paths into:
.localdev/config/config.yaml
For repo-level examples, see:
config/rbac/local-rbac.yaml
examples/ca-hierarchy.yaml
Manifest Model¶
RBAC manifests use Kubernetes-style resources:
apiVersion: ironroot.io/v1alpha1
kind: CARole
metadata:
name: local-platform-issuer
spec:
rules:
- resources:
- certificates
verbs:
- request
- renew
- view
intermediateRef: local-intermediate
---
apiVersion: ironroot.io/v1alpha1
kind: CARoleBinding
metadata:
name: local-platform-issuer-binding
spec:
roleRef:
kind: CARole
name: local-platform-issuer
subjects:
- kind: Group
name: platform
Supported local resource kinds:
UserGroupServiceAccountRootCAIntermediateCARole,CARole,GlobalRoleRoleBinding,CARoleBinding,GlobalRoleBindingTokenPolicy
Certificate-related permissions should use verbs such as:
requestrenewrevokeviewmanage-intermediatemanage-rootrequest-token
Loading Rules¶
The loader:
- expands every configured glob
- ignores directories
- sorts matched files for deterministic load order
- supports multiple YAML documents per file
- validates required fields before applying anything
- rejects unknown fields
- returns clear startup errors for invalid manifests
RBAC is loaded at server startup. Restart the server after changing manifests.
Test Locally¶
Follow Up And Running, then start the server:
ironroot-server --config .localdev/config/config.yaml
On startup, the server loads every file matching the configured RBAC paths. If a manifest is invalid, startup fails with a load RBAC manifests error.
Verify the hierarchy endpoint:
curl -s http://localhost:8443/v1/status/ca-hierarchy | jq .
The response should include:
summary.rolessummary.token_policiesroots[].intermediates[].rolesroots[].intermediates[].token_policies
Verify irtop:
irtop --server http://localhost:8443
Press:
5
The CA Health view should show an access line similar to:
access policies=1 roles=1
GitOps Workflow¶
Keep RBAC manifests in Git:
config/
rbac/
roots.yaml
intermediates.yaml
roles.yaml
bindings.yaml
token-policies.yaml
Review RBAC changes like application code:
git diff -- config/rbac
go test ./internal/rbac ./internal/db ./internal/api ./internal/irtop
just docs-build
Production can use the same file model with reviewed manifests, CI validation, and deployment automation. The difference is operational discipline: production RBAC files should be reviewed, signed off, deployed through the release process, and paired with audit monitoring.
Negative Local Checks¶
Break a role binding reference:
roleRef:
kind: CARole
name: does-not-exist
Restart the server. It should fail during startup with a clear missing role error.
Break a token policy by removing intermediateRef:
kind: TokenPolicy
metadata:
name: invalid
spec:
certificateTypes:
- server
Restart the server. It should fail validation before applying the policy.
Tests To Run¶
Focused tests:
go test ./internal/rbac ./internal/db ./internal/api ./internal/irtop ./cmd/irtop
Full validation:
go test ./...
just fmt-check
just vet
just docs-build
Future Enforcement Checklist¶
When implementing signing-path RBAC, add tests that prove:
- a request without issuer permission is denied
- a token cannot request certificates from a different Intermediate CA
- requested DNS/SANs must match the policy
- requested TTL cannot exceed the policy maximum
- issuance limits are enforced
- renewal is denied when the policy disables renewal
- approval-required policies do not sign until approved
- every allow/deny decision writes an audit event
Keep enforcement close to the certificate request path, before ca.Authority.SignCSR.