Documentation
¶
Index ¶
- Constants
- Variables
- func ClassifyChangeSource(user authnv1.UserInfo) string
- func ConvertLinks(celLinks []cel.Link, resolveKind KindResolver) ([]v1alpha1.ActivityLink, error)
- func ExtractTenant(user authnv1.UserInfo) v1alpha1.ActivityTenant
- func ExtractTenantFromAnnotations(eventMap map[string]any) v1alpha1.ActivityTenant
- func GetNestedString(m map[string]any, keys ...string) string
- func IsHumanActor(actor v1alpha1.ActivityActor) bool
- func IsSystemActor(actor v1alpha1.ActivityActor) bool
- func NewRESTMapperFromConfig(config *rest.Config) (meta.ResettableRESTMapper, error)
- func ResolveActor(user authnv1.UserInfo) v1alpha1.ActivityActor
- type ActivityBuilder
- type AuditPolicyLookup
- type DLQConfig
- type DLQPublisher
- type DeadLetterEvent
- type DeadLetterResource
- type DeadLetterTenant
- type ErrorType
- type EvaluationResult
- type EventPolicyLookup
- type EventProcessor
- type EventType
- type KindResolver
- type MatchedPolicy
- type NATSDLQPublisher
- type PolicyEvaluationError
- type PolicyRule
- type PolicySpec
- type PolicyUpdater
- type ResourceResolver
- type RuleSpec
Constants ¶
const ( ChangeSourceHuman = "human" ChangeSourceSystem = "system" )
ChangeSource constants for activity classification.
const ( ActorTypeUser = "user" ActorTypeSystem = "system" ActorTypeController = "controller" )
ActorType constants for actor classification.
const ( TenantTypePlatform = types.TenantTypePlatform TenantTypeOrganization = types.TenantTypeOrganization TenantTypeProject = types.TenantTypeProject TenantTypeUser = types.TenantTypeUser )
Re-export tenant type constants for use within the processor package.
Variables ¶
var ( // ErrKindResolution indicates a failure to resolve a resource name to its Kind. // Example: resolving "deployments" -> "Deployment" via API discovery. ErrKindResolution = errors.New("kind resolution failed") // ErrActivityBuild indicates a failure to build an Activity from the input. // This wraps errors from link conversion, kind resolution during activity building, etc. ErrActivityBuild = errors.New("activity build failed") )
Sentinel errors for error classification.
Functions ¶
func ClassifyChangeSource ¶
ClassifyChangeSource determines whether an activity was initiated by a human or by the system (controllers, service accounts, etc.). System accounts always use a "system:" prefix for the username.
func ConvertLinks ¶
func ConvertLinks(celLinks []cel.Link, resolveKind KindResolver) ([]v1alpha1.ActivityLink, error)
ConvertLinks converts CEL links to Activity links. If resolveKind is provided, it will be used to resolve plural resource names to Kind. Returns error if kind resolution fails.
func ExtractTenant ¶
func ExtractTenant(user authnv1.UserInfo) v1alpha1.ActivityTenant
ExtractTenant extracts tenant information from user extra fields.
func ExtractTenantFromAnnotations ¶
func ExtractTenantFromAnnotations(eventMap map[string]any) v1alpha1.ActivityTenant
ExtractTenantFromAnnotations reads scope annotations from event metadata and returns the corresponding ActivityTenant. Falls back to platform scope when the type annotation is absent or empty.
func GetNestedString ¶
GetNestedString extracts a string from a map, supporting nested access with multiple keys.
func IsHumanActor ¶
func IsHumanActor(actor v1alpha1.ActivityActor) bool
IsHumanActor returns true if the actor represents a human user.
func IsSystemActor ¶
func IsSystemActor(actor v1alpha1.ActivityActor) bool
IsSystemActor returns true if the actor represents a system component.
func NewRESTMapperFromConfig ¶
func NewRESTMapperFromConfig(config *rest.Config) (meta.ResettableRESTMapper, error)
NewRESTMapperFromConfig creates a ResettableRESTMapper from a Kubernetes rest.Config. Uses a cached discovery client for efficient API group/resource lookups.
func ResolveActor ¶
func ResolveActor(user authnv1.UserInfo) v1alpha1.ActivityActor
ResolveActor extracts actor information from the audit user field.
Actor types:
- user: Human users authenticated via OIDC or other providers
- system: Kubernetes controllers, service accounts, and other system components
Types ¶
type ActivityBuilder ¶
ActivityBuilder contains the common fields needed to build an Activity.
func (*ActivityBuilder) BuildFromAudit ¶
func (b *ActivityBuilder) BuildFromAudit( audit *auditv1.Event, summary string, links []cel.Link, resolveKind KindResolver, ) (*v1alpha1.Activity, error)
BuildFromAudit constructs an Activity from an audit event. If resolveKind is provided, it will be used to resolve resource names to Kind in links. Returns error if link conversion fails.
func (*ActivityBuilder) BuildFromEvent ¶
func (b *ActivityBuilder) BuildFromEvent( eventMap map[string]interface{}, summary string, links []cel.Link, resolveKind KindResolver, ) (*v1alpha1.Activity, error)
BuildFromEvent constructs an Activity from a Kubernetes event. If resolveKind is provided, it will be used to resolve resource names to Kind in links. Returns error if link conversion fails.
type AuditPolicyLookup ¶
type AuditPolicyLookup interface {
// MatchAudit looks up matching audit rules for the given resource and
// evaluates them against the provided audit map.
// Returns the first matching result, or nil if no policy matched.
MatchAudit(apiGroup, resource string, auditMap map[string]any) (*MatchedPolicy, error)
}
AuditPolicyLookup is the interface used by AuditProcessor to look up and evaluate activity policies against audit log events.
type DLQConfig ¶
type DLQConfig struct {
// Enabled controls whether failed events are published to the DLQ.
Enabled bool
// StreamName is the NATS JetStream stream name for the DLQ.
StreamName string
// SubjectPrefix is the subject prefix for DLQ messages.
// Messages are published to: <prefix>.<event_type>.<api_group>.<kind>
SubjectPrefix string
}
DLQConfig contains configuration for the dead-letter queue.
func DefaultDLQConfig ¶
func DefaultDLQConfig() DLQConfig
DefaultDLQConfig returns the default DLQ configuration.
type DLQPublisher ¶
type DLQPublisher interface {
// PublishAuditFailure publishes a failed audit event to the DLQ.
// policyVersion should be the policy.Generation when available, or 0 if no policy.
// Returns nil if the DLQ is disabled.
PublishAuditFailure(ctx context.Context, payload json.RawMessage, policyName string, policyVersion int64, ruleIndex int, errorType ErrorType, err error, resource *DeadLetterResource, tenant *DeadLetterTenant) error
// PublishEventFailure publishes a failed Kubernetes event to the DLQ.
// policyVersion should be the policy.Generation when available, or 0 if no policy.
// Returns nil if the DLQ is disabled.
PublishEventFailure(ctx context.Context, payload json.RawMessage, policyName string, policyVersion int64, ruleIndex int, errorType ErrorType, err error, resource *DeadLetterResource, tenant *DeadLetterTenant) error
}
DLQPublisher publishes failed events to the dead-letter queue.
func NewDLQPublisher ¶
func NewDLQPublisher(js nats.JetStreamContext, config DLQConfig) DLQPublisher
NewDLQPublisher creates a new DLQ publisher. Returns nil if the DLQ is disabled.
type DeadLetterEvent ¶
type DeadLetterEvent struct {
// Type identifies whether this is an audit log or Kubernetes event.
Type EventType `json:"type"`
// OriginalPayload contains the raw event JSON that failed processing.
OriginalPayload json.RawMessage `json:"originalPayload"`
// Error contains the error message from the failed processing attempt.
Error string `json:"error"`
// ErrorType classifies the type of error (cel_match, cel_summary, unmarshal).
ErrorType ErrorType `json:"errorType"`
// PolicyName is the name of the ActivityPolicy that failed evaluation.
PolicyName string `json:"policyName"`
// PolicyVersion is the policy.Generation when the failure occurred.
// Used to trigger immediate retry when the policy is updated.
PolicyVersion int64 `json:"policyVersion"`
// RuleIndex is the index of the rule within the policy that failed.
// -1 indicates the error occurred before rule evaluation.
RuleIndex int `json:"ruleIndex"`
// Timestamp is when the failure occurred.
Timestamp metav1.Time `json:"timestamp"`
// Tenant contains multi-tenancy information if available.
Tenant *DeadLetterTenant `json:"tenant,omitempty"`
// Resource contains information about the target resource.
Resource *DeadLetterResource `json:"resource,omitempty"`
// RetryCount tracks how many times this event has been retried.
RetryCount int `json:"retryCount"`
// LastRetryAt is when the last retry attempt occurred.
LastRetryAt *metav1.Time `json:"lastRetryAt,omitempty"`
// NextRetryAfter is when the event becomes eligible for the next retry.
// Nil means the event has not been retried yet.
NextRetryAfter *metav1.Time `json:"nextRetryAfter,omitempty"`
}
DeadLetterEvent wraps a failed event with error context for debugging.
type DeadLetterResource ¶
type DeadLetterResource struct {
// APIGroup is the API group of the resource (empty for core resources).
APIGroup string `json:"apiGroup,omitempty"`
// Kind is the kind of the resource.
Kind string `json:"kind,omitempty"`
// Name is the name of the resource.
Name string `json:"name,omitempty"`
// Namespace is the namespace of the resource (empty for cluster-scoped).
Namespace string `json:"namespace,omitempty"`
}
DeadLetterResource contains resource information for a dead-lettered event.
type DeadLetterTenant ¶
type DeadLetterTenant struct {
// Type is the tenant type (platform, organization, project).
Type string `json:"type,omitempty"`
// Name is the tenant name.
Name string `json:"name,omitempty"`
}
DeadLetterTenant contains tenant information for a dead-lettered event.
func NewDeadLetterTenantFromActivity ¶
func NewDeadLetterTenantFromActivity(tenantType, tenantName string) *DeadLetterTenant
NewDeadLetterTenantFromActivity creates a DeadLetterTenant from an ActivityTenant. Returns nil if the input tenant has default/empty values.
type ErrorType ¶
type ErrorType string
ErrorType classifies the type of error that caused DLQ routing.
const ( // ErrorTypeCELMatch indicates the CEL match expression failed to evaluate. // Example: A match expression like "audit.verb == 'create'" fails due to // missing fields or type mismatches in the audit event. ErrorTypeCELMatch ErrorType = "cel_match" // ErrorTypeCELSummary indicates the CEL summary template failed to render. // Example: A summary template like "{{ actor }} created {{ resource.name }}" // fails because "resource.name" doesn't exist or has an unexpected type. ErrorTypeCELSummary ErrorType = "cel_summary" // ErrorTypeUnmarshal indicates the event JSON could not be parsed. // Example: Malformed JSON in the NATS message payload, or unexpected // structure that doesn't match the expected audit event schema. ErrorTypeUnmarshal ErrorType = "unmarshal" // ErrorTypeKindResolve indicates the resource-to-kind resolution failed. // Example: An audit event references resource "widgets" but no CRD or // built-in resource with that plural name exists in the API discovery cache. ErrorTypeKindResolve ErrorType = "kind_resolve" )
type EvaluationResult ¶
type EvaluationResult struct {
// Activity is the generated activity, or nil if no rule matched
Activity *v1alpha1.Activity
// MatchedRuleIndex is the index of the rule that matched, or -1 if none matched
MatchedRuleIndex int
// MatchedRuleType is "audit" or "event" depending on which rule matched
MatchedRuleType string
// MatchedRuleName is the name of the matched rule from the policy spec
MatchedRuleName string
}
EvaluationResult contains the result of evaluating policy rules against an input.
func EvaluateAuditRules ¶
func EvaluateAuditRules( spec *v1alpha1.ActivityPolicySpec, audit *auditv1.Event, resolveKind KindResolver, ) (*EvaluationResult, error)
EvaluateAuditRules evaluates audit rules against an audit log input. Returns the generated Activity if a rule matches, or nil if no rule matched. If resolveKind is provided, it will be used to resolve resource names to Kind in links.
func EvaluateEventRules ¶
func EvaluateEventRules( spec *v1alpha1.ActivityPolicySpec, eventData interface{}, resolveKind KindResolver, ) (*EvaluationResult, error)
EvaluateEventRules evaluates event rules against a Kubernetes event input. Returns the generated Activity if a rule matches, or nil if no rule matched. If resolveKind is provided, it will be used to resolve resource names to Kind in links.
type EventPolicyLookup ¶
type EventPolicyLookup interface {
// MatchEvent looks up matching event rules for the given resource and
// evaluates them against the provided event map.
// Returns the first matching result, or nil if no policy matched.
MatchEvent(apiGroup, kind string, eventMap map[string]any) (*MatchedPolicy, error)
}
EventPolicyLookup is the interface used by EventProcessor to look up and evaluate activity policies against Kubernetes events. activityprocessor.PolicyCache provides an adapter that satisfies this interface.
type EventProcessor ¶
type EventProcessor struct {
// contains filtered or unexported fields
}
EventProcessor processes Kubernetes events from a NATS JetStream pull consumer and generates Activity records via ActivityPolicy event rules.
func NewEventProcessor ¶
func NewEventProcessor( js nats.JetStreamContext, streamName string, consumerName string, activityPrefix string, policyLookup EventPolicyLookup, workers int, batchSize int, dlqPublisher DLQPublisher, ) *EventProcessor
NewEventProcessor creates a new event processor. js is the JetStream context used for both consuming events and publishing activities. streamName is the NATS stream to consume from (e.g., "EVENTS"). consumerName is the durable pull consumer name. activityPrefix is the subject prefix for publishing generated activities. policyLookup is used to evaluate events against ActivityPolicy event rules. dlqPublisher is used to publish failed events to the dead-letter queue.
type EventType ¶
type EventType string
EventType identifies the type of event that failed processing.
type KindResolver ¶
KindResolver resolves a plural resource name to its Kind using API discovery. Returns error if resolution fails.
func NewKindResolver ¶
func NewKindResolver(mapper meta.ResettableRESTMapper) KindResolver
NewKindResolver creates a KindResolver that uses a ResettableRESTMapper. On cache miss, it resets the discovery cache and retries to handle newly registered CRDs.
type MatchedPolicy ¶
type MatchedPolicy struct {
// PolicyName is the name of the matching policy.
PolicyName string
// Generation is the policy generation (version) that produced this match.
Generation int64
// APIGroup is the API group of the target resource.
APIGroup string
// Kind is the kind of the target resource.
Kind string
// Summary is the generated activity summary.
Summary string
// Links contains clickable references extracted from link() calls in the summary template.
Links []cel.Link
}
MatchedPolicy contains the result of matching an event against policy rules.
type NATSDLQPublisher ¶
type NATSDLQPublisher struct {
// contains filtered or unexported fields
}
NATSDLQPublisher implements DLQPublisher using NATS JetStream.
func (*NATSDLQPublisher) PublishAuditFailure ¶
func (p *NATSDLQPublisher) PublishAuditFailure(ctx context.Context, payload json.RawMessage, policyName string, policyVersion int64, ruleIndex int, errorType ErrorType, err error, resource *DeadLetterResource, tenant *DeadLetterTenant) error
PublishAuditFailure publishes a failed audit event to the DLQ.
func (*NATSDLQPublisher) PublishEventFailure ¶
func (p *NATSDLQPublisher) PublishEventFailure(ctx context.Context, payload json.RawMessage, policyName string, policyVersion int64, ruleIndex int, errorType ErrorType, err error, resource *DeadLetterResource, tenant *DeadLetterTenant) error
PublishEventFailure publishes a failed Kubernetes event to the DLQ.
type PolicyEvaluationError ¶
PolicyEvaluationError wraps an error with policy context for DLQ routing.
func NewPolicyEvaluationError ¶
func NewPolicyEvaluationError(policyName string, ruleIndex int, err error) *PolicyEvaluationError
NewPolicyEvaluationError creates a new PolicyEvaluationError.
func (*PolicyEvaluationError) Error ¶
func (e *PolicyEvaluationError) Error() string
func (*PolicyEvaluationError) Unwrap ¶
func (e *PolicyEvaluationError) Unwrap() error
type PolicyRule ¶
type PolicyRule interface {
// IsValid returns true if the rule compiled successfully.
IsValid() bool
// EvaluateEventMatch evaluates the match expression against an event map.
EvaluateEventMatch(eventMap map[string]any) (bool, error)
// EvaluateAuditMatch evaluates the match expression against an audit map.
EvaluateAuditMatch(auditMap map[string]any) (bool, error)
// EvaluateSummary evaluates the summary template with the given variables.
// Returns the rendered summary, any links collected via link() calls, and any error.
EvaluateSummary(vars map[string]any) (string, []cel.Link, error)
}
PolicyRule represents a compiled activity policy rule for CEL evaluation. This is the minimal interface that EventProcessor and AuditProcessor need to match events/audit records against policy rules. The activityprocessor package provides concrete implementations of this interface.
type PolicySpec ¶
type PolicySpec struct {
// Name is the policy name.
Name string
// APIGroup is the target resource's API group.
APIGroup string
// Kind is the target resource's kind.
Kind string
// Resource is the plural resource name.
Resource string
// ResourceVersion is used for cache invalidation.
ResourceVersion string
// AuditRules are the CEL match/summary rule pairs for audit events.
AuditRules []RuleSpec
// EventRules are the CEL match/summary rule pairs for Kubernetes events.
EventRules []RuleSpec
}
PolicySpec contains the minimal information needed to add a policy to the cache.
type PolicyUpdater ¶
type PolicyUpdater interface {
// AddPolicy adds a policy to the cache.
AddPolicy(policy *PolicySpec) error
// UpdatePolicy updates a policy in the cache.
UpdatePolicy(oldPolicy, newPolicy *PolicySpec) error
// RemovePolicy removes a policy from the cache.
RemovePolicy(policy *PolicySpec)
}
PolicyUpdater is the interface used by the Processor to update the policy cache when ActivityPolicy resources change.
type ResourceResolver ¶
ResourceResolver resolves a Kind to its plural resource name using API discovery.
func NewResourceResolver ¶
func NewResourceResolver(mapper meta.ResettableRESTMapper) ResourceResolver
NewResourceResolver creates a ResourceResolver that uses a ResettableRESTMapper. On cache miss, it resets the discovery cache and retries.