feat(plugins/localauthz): in-process Enforcer for scenario_stub RBAC demo (infra-admin v1.1 PR-5)#815
Conversation
…o_stub Adds plugins/localauthz — an EnginePlugin registering module type 'authz.local'. The module reads config.policies [][]string ([sub,obj,act] triples), registers itself via ProvidesServices + app.RegisterService so infra.admin's app.GetService(authz_module, &Enforcer) resolves it, and implements: Enforce(sub, obj, act string, extra ...string) (bool, error) Exact-match semantics: allow-effect, default-deny, no Casbin dependency. The variadic extra...string matches module/infra_admin.go:142 Enforcer exactly. Also wires localauthz.New() into plugins/all/extras_stub.go (//go:build scenario_stub) alongside the existing stub provider, and adds DOCUMENTATION.md row for the new authz.local module type (required by TestDocumentationCoverage). Tests: - TestPlugin_ModuleFactories: 'authz.local' registered - TestEnforce_Table: 9-case table (operator allow, viewer partial, deny, unknown) - TestEnforce_VariadicCompatible: extra args silently accepted, no panic - TestEnforce_EmptyPolicies: default-deny with zero policies - TestDefaultPlugins_ContainsLocalAuthz: tagged build includes plugin Untagged build: localauthz absent (existing TestDefaultPlugins_BaseExcludesStub) Tagged build: go build -tags scenario_stub ./cmd/server → exit 0 lint: 0 issues Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…_stub) builds Production-exclusion guard for the in-process authz.local enforcer (was uncommitted in the shared worktree). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a lightweight, in-process authorization plugin (authz.local) intended for scenario_stub builds so infra-admin scenario(s) can demonstrate server-side RBAC without relying on the external-only Casbin authz plugin.
Changes:
- Introduces
plugins/localauthzEnginePlugin providing an in-processEnforce(sub,obj,act,...)implementation backed by exact-match policy triples. - Wires the plugin into
plugins/allonly under thescenario_stubbuild tag, with tests guarding both inclusion (tagged) and exclusion (untagged). - Documents the new
authz.localmodule type as scenario-only inDOCUMENTATION.md.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/localauthz/plugin.go | Adds the in-process authz.local module + policy parsing + service registration. |
| plugins/localauthz/plugin_test.go | Adds unit tests for factory registration and enforcement behavior. |
| plugins/all/extras_stub.go | Registers localauthz in the scenario-only default plugin set. |
| plugins/all/extras_stub_test.go | Asserts localauthz is included under scenario_stub. |
| plugins/all/extras_base_test.go | Asserts localauthz is excluded without scenario_stub. |
| DOCUMENTATION.md | Documents authz.local as scenario-only. |
| // Each policy is a [subject, object, action] triple. A request is allowed | ||
| // when it exactly matches at least one triple; all other requests are denied. |
| // policy is a parsed [subject, object, action] triple. | ||
| type policy struct{ sub, obj, act string } |
| // Init parses the policies from config and logs a startup message. | ||
| func (m *localAuthzModule) Init(app modular.Application) error { | ||
| m.policies = parsePolicies(m.cfg) | ||
| app.Logger().Info("authz.local: loaded policies", | ||
| "module", m.name, | ||
| "count", len(m.policies), | ||
| ) | ||
| return nil |
| var enf enforcer | ||
| for _, svc := range sa.ProvidesServices() { | ||
| if e, ok := svc.Instance.(enforcer); ok { | ||
| enf = e | ||
| } | ||
| } | ||
| // Variadic: extra args must not panic or cause error. | ||
| got, err := enf.Enforce("u", "o", "a", "extra1", "extra2") |
| var enf enforcer | ||
| for _, svc := range sa.ProvidesServices() { | ||
| if e, ok := svc.Instance.(enforcer); ok { | ||
| enf = e | ||
| } | ||
| } | ||
| got, err := enf.Enforce("anyone", "infra:apply", "allow") |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
⏱ Benchmark Results✅ No significant performance regressions detected. benchstat comparison (baseline → PR)
|
|
Closing — wrong approach. Per maintainer feedback, scenario test fixtures (stub iac.provider, in-process enforcer) must NOT live in the workflow engine repo (even build-tagged). The established pattern (scenarios 85/86/87) is a scenario-owned cmd/server/main.go that imports the engine via NewEngineBuilder().WithPlugin(...) and registers fixtures from the scenario repo. Reworking: (1) revert the scenario_stub mechanism + stub provider/enforcer from workflow core; (2) scenario 92 gets its own cmd/server/main.go with fixtures in workflow-scenarios. Tracking in the rework. |
What
PR-5 (amendment, ADR-0009) of the infra-admin v1.1 program. Adds a build-tagged (
scenario_stub) in-processEnforcerso scenario 92 can demonstrate v1.1 server-side write-tier RBAC.Why (backport)
Execution disproved a design assumption:
infra.adminresolvesauthz_moduleas an in-process GoEnforcer(app.GetService+ type-assert), butauthz.casbinis external-only (workflow-plugin-authzgRPC plugin) — the host gets aRemoteModuleproxy with no GoEnforce. So the scenario couldn't boot with RBAC. Droppingauthz_module(authn-only) would weaken the locked security scope (forbidden). Fix = a minimal in-process Enforcer, scenario-only.Changes
plugins/localauthz— EnginePlugin registering module typeauthz.local: readsconfig.policies([sub,obj,act] triples), registers itself as a service (ProvidesServices), implementsEnforce(sub,obj,act string, extra ...string)(bool,error)(exact-match, allow-effect, default-deny — matchesmodule/infra_admin.goEnforcer). No casbin dep.plugins/all/extras_stub.go(//go:build scenario_stub) — appendslocalauthz.New()(alongside the P1 stub provider). Production builds exclude it (guard testTestDefaultPlugins_BaseExcludesLocalAuthz).Verification
go test ./plugins/localauthz/4/4 + tagged/untagged exclusion tests +go build -tags scenario_stub ./cmd/server+golangci-lint --new-from-rev=origin/main0 issues. Two-stage reviewed (spec + quality SHIP-IT). Rollback: revert — untagged builds unaffected (scenario-only). ADR-0009.🤖 Generated with Claude Code