Documentation
¶
Overview ¶
Package plugin defines the plugin system for Warden. Plugins are notified of lifecycle events (check performed, role created, policy updated, etc.) and can react — logging, metrics, tracing, etc.
Each lifecycle hook is a separate interface so plugins opt in only to the events they care about.
Index ¶
- type AfterCheck
- type Audit
- type BeforeCheck
- type Event
- type MetricsRecorder
- type PermissionAttached
- type PermissionCreated
- type PermissionDeleted
- type PermissionDetached
- type Plugin
- type PolicyCreated
- type PolicyDeleted
- type PolicyObligationFired
- type PolicyUpdated
- type Registry
- func (r *Registry) EmitAfterCheck(ctx context.Context, req, result any)
- func (r *Registry) EmitAudit(ctx context.Context, ev Event)
- func (r *Registry) EmitBeforeCheck(ctx context.Context, req any)
- func (r *Registry) EmitPermissionAttached(ctx context.Context, roleID id.RoleID, permID id.PermissionID)
- func (r *Registry) EmitPermissionCreated(ctx context.Context, p *permission.Permission)
- func (r *Registry) EmitPermissionDeleted(ctx context.Context, permID id.PermissionID)
- func (r *Registry) EmitPermissionDetached(ctx context.Context, roleID id.RoleID, permID id.PermissionID)
- func (r *Registry) EmitPolicyCreated(ctx context.Context, p *policy.Policy)
- func (r *Registry) EmitPolicyDeleted(ctx context.Context, polID id.PolicyID)
- func (r *Registry) EmitPolicyObligationFired(ctx context.Context, polID id.PolicyID, obligation string, req, result any)
- func (r *Registry) EmitPolicyUpdated(ctx context.Context, p *policy.Policy)
- func (r *Registry) EmitRelationDeleted(ctx context.Context, relID id.RelationID)
- func (r *Registry) EmitRelationWritten(ctx context.Context, t *relation.Tuple)
- func (r *Registry) EmitRoleAssigned(ctx context.Context, a *assignment.Assignment)
- func (r *Registry) EmitRoleCreated(ctx context.Context, rl *role.Role)
- func (r *Registry) EmitRoleDeleted(ctx context.Context, roleID id.RoleID)
- func (r *Registry) EmitRoleUnassigned(ctx context.Context, a *assignment.Assignment)
- func (r *Registry) EmitRoleUpdated(ctx context.Context, rl *role.Role)
- func (r *Registry) EmitShutdown(ctx context.Context)
- func (r *Registry) Plugins() []Plugin
- func (r *Registry) Register(p Plugin)
- func (r *Registry) SetMetrics(m MetricsRecorder)
- func (r *Registry) Validate(p Plugin) []string
- type RelationDeleted
- type RelationWritten
- type RoleAssigned
- type RoleCreated
- type RoleDeleted
- type RoleUnassigned
- type RoleUpdated
- type Shutdown
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AfterCheck ¶
AfterCheck is called after an authorization check completes. The req parameter is *warden.CheckRequest; result is *warden.CheckResult.
type Audit ¶ added in v1.7.0
Audit is called for every mutation, in addition to whichever typed hook above also fires for it.
type BeforeCheck ¶
BeforeCheck is called before an authorization check is evaluated. The req parameter is *warden.CheckRequest (passed as any to avoid import cycle).
type Event ¶ added in v1.7.0
type Event struct {
Actor any
RequestID string
TraceID string
At time.Time
// Action is one of: "role.created", "role.updated", "role.deleted",
// "permission.created", "permission.deleted", "permission.attached",
// "permission.detached", "assignment.created", "assignment.deleted",
// "relation.written", "relation.deleted", "policy.created",
// "policy.updated", "policy.deleted", "resourcetype.created",
// "resourcetype.updated", "resourcetype.deleted", "declarative.applied",
// "permission.updated", "role.permissions_set", "maintenance.run",
// "maintenance.cache_invalidated".
Action string
TenantID string
EntityID string
Entity any
Before any
}
Event describes a single mutation for the audit trail. It is fired for every mutation in addition to the typed hooks above, so a plugin that wants a complete audit stream can implement just Audit instead of every typed hook individually.
Actor is warden.Actor, passed as `any` to avoid an import cycle (plugin cannot import the root warden package); it carries Kind, ID and Via. Entity is the entity after the change, or nil on delete. Before is the entity as it stood before an update or a delete (role, policy, permission, assignment, resource type and relation deletes all set it). It is nil on a create, and on an update or delete whose read of the old entity failed.
type MetricsRecorder ¶ added in v1.7.0
type MetricsRecorder interface {
HookError(hook, plugin string)
}
MetricsRecorder is the minimal metrics surface the registry needs. It mirrors (and is satisfied by) warden.Metrics' HookError method without importing the root package, which would create an import cycle.
type PermissionAttached ¶
type PermissionAttached interface {
OnPermissionAttached(ctx context.Context, roleID id.RoleID, permID id.PermissionID) error
}
PermissionAttached is called after a permission is attached to a role.
type PermissionCreated ¶
type PermissionCreated interface {
OnPermissionCreated(ctx context.Context, p *permission.Permission) error
}
PermissionCreated is called after a permission is created.
type PermissionDeleted ¶
type PermissionDeleted interface {
OnPermissionDeleted(ctx context.Context, permID id.PermissionID) error
}
PermissionDeleted is called after a permission is deleted.
type PermissionDetached ¶
type PermissionDetached interface {
OnPermissionDetached(ctx context.Context, roleID id.RoleID, permID id.PermissionID) error
}
PermissionDetached is called after a permission is detached from a role.
type Plugin ¶
type Plugin interface {
// Name returns a unique human-readable name for the plugin.
Name() string
}
Plugin is the base interface all plugins must implement.
type PolicyCreated ¶
PolicyCreated is called after a policy is created.
type PolicyDeleted ¶
PolicyDeleted is called after a policy is deleted.
type PolicyObligationFired ¶
type PolicyObligationFired interface {
OnPolicyObligationFired(ctx context.Context, polID id.PolicyID, obligation string, req, result any) error
}
PolicyObligationFired is called for every obligation emitted during a Check evaluation — once per (policy, obligation_name) pair. Plugins implementing this hook can react to side-effect signals like "audit-log", "require-mfa", or "notify-security" without having to scan CheckResult.Obligations themselves.
Fired after the engine has merged decisions across RBAC / ReBAC / ABAC, so the obligation list is already deduplicated. policyID identifies the matched policy that produced the obligation; obligation is the named action to perform.
type PolicyUpdated ¶
PolicyUpdated is called after a policy is updated.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds registered plugins and dispatches lifecycle events. It type-caches plugins at registration time so emit calls iterate only over plugins implementing the relevant hook.
Every dispatch is panic-recovered per hook: one misbehaving plugin can neither crash the calling goroutine nor stop other plugins in the same Emit call from running.
It is safe for concurrent use. Engine.Plugins() hands the registry to any caller, so a Register can arrive while checks are emitting. Register only ever appends, so an Emit reads the hook slice's header under the read lock and iterates outside it: a later append writes past that header's length or into a new array, and the plugins it adds are notified from the next Emit on.
func NewRegistry ¶
NewRegistry creates a plugin registry with the given logger.
func (*Registry) EmitAfterCheck ¶
EmitAfterCheck notifies all plugins that implement AfterCheck.
func (*Registry) EmitAudit ¶ added in v1.7.0
EmitAudit notifies all plugins that implement Audit. Called for every mutation, in addition to whichever typed Emit* also fires for it.
func (*Registry) EmitBeforeCheck ¶
EmitBeforeCheck notifies all plugins that implement BeforeCheck.
func (*Registry) EmitPermissionAttached ¶
func (r *Registry) EmitPermissionAttached(ctx context.Context, roleID id.RoleID, permID id.PermissionID)
EmitPermissionAttached notifies all plugins that implement PermissionAttached.
func (*Registry) EmitPermissionCreated ¶
func (r *Registry) EmitPermissionCreated(ctx context.Context, p *permission.Permission)
EmitPermissionCreated notifies all plugins that implement PermissionCreated.
func (*Registry) EmitPermissionDeleted ¶
func (r *Registry) EmitPermissionDeleted(ctx context.Context, permID id.PermissionID)
EmitPermissionDeleted notifies all plugins that implement PermissionDeleted.
func (*Registry) EmitPermissionDetached ¶
func (r *Registry) EmitPermissionDetached(ctx context.Context, roleID id.RoleID, permID id.PermissionID)
EmitPermissionDetached notifies all plugins that implement PermissionDetached.
func (*Registry) EmitPolicyCreated ¶
EmitPolicyCreated notifies all plugins that implement PolicyCreated.
func (*Registry) EmitPolicyDeleted ¶
EmitPolicyDeleted notifies all plugins that implement PolicyDeleted.
func (*Registry) EmitPolicyObligationFired ¶
func (r *Registry) EmitPolicyObligationFired(ctx context.Context, polID id.PolicyID, obligation string, req, result any)
EmitPolicyObligationFired notifies all plugins that implement PolicyObligationFired. Called once per obligation produced by the engine after merging RBAC / ReBAC / ABAC results.
func (*Registry) EmitPolicyUpdated ¶
EmitPolicyUpdated notifies all plugins that implement PolicyUpdated.
func (*Registry) EmitRelationDeleted ¶
func (r *Registry) EmitRelationDeleted(ctx context.Context, relID id.RelationID)
EmitRelationDeleted notifies all plugins that implement RelationDeleted.
func (*Registry) EmitRelationWritten ¶
EmitRelationWritten notifies all plugins that implement RelationWritten.
func (*Registry) EmitRoleAssigned ¶
func (r *Registry) EmitRoleAssigned(ctx context.Context, a *assignment.Assignment)
EmitRoleAssigned notifies all plugins that implement RoleAssigned.
func (*Registry) EmitRoleCreated ¶
EmitRoleCreated notifies all plugins that implement RoleCreated.
func (*Registry) EmitRoleDeleted ¶
EmitRoleDeleted notifies all plugins that implement RoleDeleted.
func (*Registry) EmitRoleUnassigned ¶
func (r *Registry) EmitRoleUnassigned(ctx context.Context, a *assignment.Assignment)
EmitRoleUnassigned notifies all plugins that implement RoleUnassigned.
func (*Registry) EmitRoleUpdated ¶
EmitRoleUpdated notifies all plugins that implement RoleUpdated.
func (*Registry) EmitShutdown ¶
EmitShutdown notifies all plugins that implement Shutdown.
func (*Registry) Plugins ¶
Plugins returns all registered plugins, in registration order. The slice is the caller's own copy.
func (*Registry) Register ¶
Register adds a plugin and type-asserts it into all applicable hook caches. Plugins are notified in registration order.
If the plugin implements none of the known hook interfaces, Register logs a Warn: a plugin that only implements Plugin does nothing, which is almost always a wiring mistake (wrong interface signature, typo'd method name, etc).
func (*Registry) SetMetrics ¶ added in v1.7.0
func (r *Registry) SetMetrics(m MetricsRecorder)
SetMetrics installs a metrics sink for hook-error counting. Passing nil is a no-op (the registry keeps its current sink, defaulting to a noop).
type RelationDeleted ¶
type RelationDeleted interface {
OnRelationDeleted(ctx context.Context, relID id.RelationID) error
}
RelationDeleted is called after a relation tuple is deleted, once per tuple, with that tuple's ID (never the zero ID). A REST delete by key whose read of the matching tuples named none (it failed, or found nothing) fires no RelationDeleted; it clears the engine's cache for its tenant itself, and when the read failed its one audit event names the key instead of a tuple.
type RelationWritten ¶
RelationWritten is called after a relation tuple is written.
type RoleAssigned ¶
type RoleAssigned interface {
OnRoleAssigned(ctx context.Context, a *assignment.Assignment) error
}
RoleAssigned is called after a role is assigned to a subject.
type RoleCreated ¶
RoleCreated is called after a role is created.
type RoleDeleted ¶
RoleDeleted is called after a role is deleted.
type RoleUnassigned ¶
type RoleUnassigned interface {
OnRoleUnassigned(ctx context.Context, a *assignment.Assignment) error
}
RoleUnassigned is called after a role is unassigned from a subject.
type RoleUpdated ¶
RoleUpdated is called after a role is updated.