-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwarden.go
More file actions
116 lines (96 loc) · 4.18 KB
/
Copy pathwarden.go
File metadata and controls
116 lines (96 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Package warden provides composable permissions and authorization for Go.
//
// Warden supports RBAC (role-based), ABAC (attribute-based), and ReBAC
// (relationship-based) authorization models individually or combined.
// It is tenant-scoped by default via forge.Scope and integrates with the
// Forge ecosystem for audit logging, feature flags, and async jobs.
//
// eng, err := warden.NewEngine(
// warden.WithStore(memStore),
// )
// result, err := eng.Check(ctx, &warden.CheckRequest{
// Subject: warden.Subject{Kind: warden.SubjectUser, ID: "user_123"},
// Action: warden.Action{Name: "read"},
// Resource: warden.Resource{Type: "document", ID: "doc_456"},
// })
package warden
// SubjectKind identifies the type of actor making an authorization request.
type SubjectKind string
const (
// SubjectUser represents a human user.
SubjectUser SubjectKind = "user"
// SubjectAPIKey represents an API key (e.g., from Keysmith).
SubjectAPIKey SubjectKind = "api_key"
// SubjectService represents a service-to-service caller.
SubjectService SubjectKind = "service"
// SubjectServiceAcct represents a service account.
SubjectServiceAcct SubjectKind = "service_acct"
)
// Subject represents an actor in an authorization check.
type Subject struct {
Kind SubjectKind `json:"kind"`
ID string `json:"id"`
Attributes map[string]any `json:"attributes,omitempty"`
}
// Resource represents the target of an authorization check.
type Resource struct {
Type string `json:"type"`
ID string `json:"id"`
Attributes map[string]any `json:"attributes,omitempty"`
}
// Action represents what the subject wants to do.
type Action struct {
Name string `json:"name"`
}
// CheckRequest is the input to an authorization check.
type CheckRequest struct {
Subject Subject `json:"subject"`
Action Action `json:"action"`
Resource Resource `json:"resource"`
Context map[string]any `json:"context,omitempty"`
TenantID string `json:"tenant_id,omitempty"` // Optional: overrides context-derived tenant.
NamespacePath string `json:"namespace_path,omitempty"` // Optional: overrides context-derived namespace.
}
// CheckResult is the outcome of an authorization check.
//
// Obligations is the list of obligation names from PBAC policies that
// matched this check (allow OR deny). Obligations are side-effect
// signals — names of actions the calling system should perform
// (audit-log, require-mfa, notify-security, etc.). They don't change the
// Allowed/Decision outcome. The engine also fires the
// PolicyObligationFired plugin hook per obligation, so existing plugin
// pipelines (Chronicle audit, dispatchers) get them automatically.
type CheckResult struct {
Allowed bool `json:"allowed"`
Decision Decision `json:"decision"`
Reason string `json:"reason,omitempty"`
MatchedBy []MatchInfo `json:"matched_by,omitempty"`
Obligations []string `json:"obligations,omitempty"`
EvalTimeNs int64 `json:"eval_time_ns"`
}
// Decision is the authorization outcome.
type Decision string
const (
// DecisionAllow means the request is permitted.
DecisionAllow Decision = "allow"
// DecisionDeny means the request is denied (generic).
DecisionDeny Decision = "deny"
// DecisionDenyExplicit means an explicit deny policy matched.
DecisionDenyExplicit Decision = "deny_explicit"
// DecisionDenyDefault means no matching allow rule was found.
DecisionDenyDefault Decision = "deny_default"
// DecisionDenyNoRoles means the subject has no roles assigned.
DecisionDenyNoRoles Decision = "deny_no_roles"
// DecisionDenyNoPerms means no role grants the required permission.
DecisionDenyNoPerms Decision = "deny_no_perms"
// DecisionDenyCondition means an ABAC condition blocked the request.
DecisionDenyCondition Decision = "deny_condition"
// DecisionDenyRelation means no matching relation was found.
DecisionDenyRelation Decision = "deny_relation"
)
// MatchInfo describes what rule matched during evaluation.
type MatchInfo struct {
Source string `json:"source"` // "rbac", "abac", "rebac"
RuleID string `json:"rule_id,omitempty"`
Detail string `json:"detail,omitempty"`
}