Skip to content

Commit 4b1b83f

Browse files
author
Praveenrajmani
committed
Add audit log categorization and enhanced filtering options
This commit introduces comprehensive audit log categorization and enhanced filtering capabilities for API, audit, and error logs: - Add AuditCategory enum with 15 categories (config, user, service-account, policy, group, bucket, lifecycle, replication, notification, encryption, cors, versioning, service, kms, site-replication, pool, idp, log-recorder) - Add AuditAction enum with common actions (create, update, delete, enable, disable, set, reset, restore, clear, start, stop, restart, attach, detach) - Extend Audit struct with Category, Action, and Details fields for richer audit event metadata - Add MaxPerNode field to APILogOpts, AuditLogOpts, and ErrorLogOpts to limit log entries retrieved per cluster node - Add Category filter to AuditLogOpts for filtering by audit category - Introduce detailed audit structures for different categories (ConfigAuditDetails, UserAuditDetails, ServiceAccountAuditDetails, PolicyAuditDetails, GroupAuditDetails, BucketConfigAuditDetails, ServiceAuditDetails) - Generate msgp serialization code for new audit types These changes enable more granular audit log queries and structured audit event tracking across MinIO admin operations.
1 parent d6fea89 commit 4b1b83f

File tree

6 files changed

+7394
-91
lines changed

6 files changed

+7394
-91
lines changed

api-logs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type APILogOpts struct {
4242
Interval time.Duration `json:"interval,omitempty"`
4343
Origin log.Origin `json:"origin,omitempty"`
4444
Type log.APIType `json:"type,omitempty"`
45+
MaxPerNode int `json:"maxPerNode,omitempty"`
4546
}
4647

4748
// GetAPILogs fetches the persisted API logs from MinIO

audit-logs.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ import (
3434

3535
// AuditLogOpts represents the options for the audit logs
3636
type AuditLogOpts struct {
37-
Node string `json:"node,omitempty"`
38-
API string `json:"api,omitempty"`
39-
Bucket string `json:"bucket,omitempty"`
40-
Interval time.Duration `json:"interval,omitempty"`
37+
Node string `json:"node,omitempty"`
38+
API string `json:"api,omitempty"`
39+
Bucket string `json:"bucket,omitempty"`
40+
Interval time.Duration `json:"interval,omitempty"`
41+
Category log.AuditCategory `json:"category,omitempty"`
42+
MaxPerNode int `json:"maxPerNode,omitempty"`
4143
}
4244

4345
// GetAuditLogs fetches the persisted audit logs from MinIO

error-logs.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ import (
3434

3535
// ErrorLogOpts represents the options for the ErrorLogs
3636
type ErrorLogOpts struct {
37-
Node string `json:"node,omitempty"`
38-
API string `json:"api,omitempty"`
39-
Bucket string `json:"bucket,omitempty"`
40-
Prefix string `json:"prefix,omitempty"`
41-
Interval time.Duration `json:"interval,omitempty"`
37+
Node string `json:"node,omitempty"`
38+
API string `json:"api,omitempty"`
39+
Bucket string `json:"bucket,omitempty"`
40+
Prefix string `json:"prefix,omitempty"`
41+
Interval time.Duration `json:"interval,omitempty"`
42+
MaxPerNode int `json:"maxPerNode,omitempty"`
4243
}
4344

4445
// GetErrorLogs fetches the persisted error logs from MinIO

log/audit.go

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,204 @@ import (
2525
//msgp:tag json
2626
//go:generate msgp -d clearomitted -d "timezone utc" $GOFILE
2727

28+
// AuditCategory represents the category of audit event
29+
type AuditCategory string
30+
31+
const (
32+
AuditCategoryConfig AuditCategory = "config"
33+
AuditCategoryUser AuditCategory = "user"
34+
AuditCategoryServiceAccount AuditCategory = "service-account"
35+
AuditCategoryPolicy AuditCategory = "policy"
36+
AuditCategoryGroup AuditCategory = "group"
37+
AuditCategoryBucket AuditCategory = "bucket"
38+
AuditCategoryLifecycle AuditCategory = "lifecycle"
39+
AuditCategoryReplication AuditCategory = "replication"
40+
AuditCategoryNotification AuditCategory = "notification"
41+
AuditCategoryEncryption AuditCategory = "encryption"
42+
AuditCategoryCORS AuditCategory = "cors"
43+
AuditCategoryVersioning AuditCategory = "versioning"
44+
AuditCategoryService AuditCategory = "service"
45+
AuditCategoryKMS AuditCategory = "kms"
46+
AuditCategorySiteRepl AuditCategory = "site-replication"
47+
AuditCategoryPool AuditCategory = "pool"
48+
AuditCategoryIDP AuditCategory = "idp"
49+
AuditCategoryLogRecorder AuditCategory = "log-recorder"
50+
)
51+
52+
// AuditAction represents the type of action performed
53+
type AuditAction string
54+
55+
const (
56+
AuditActionCreate AuditAction = "create"
57+
AuditActionUpdate AuditAction = "update"
58+
AuditActionDelete AuditAction = "delete"
59+
AuditActionEnable AuditAction = "enable"
60+
AuditActionDisable AuditAction = "disable"
61+
AuditActionSet AuditAction = "set"
62+
AuditActionReset AuditAction = "reset"
63+
AuditActionRestore AuditAction = "restore"
64+
AuditActionClear AuditAction = "clear"
65+
AuditActionStart AuditAction = "start"
66+
AuditActionStop AuditAction = "stop"
67+
AuditActionRestart AuditAction = "restart"
68+
AuditActionAttach AuditAction = "attach"
69+
AuditActionDetach AuditAction = "detach"
70+
)
71+
2872
// Audit represents the user triggered audit events
2973
type Audit struct {
3074
Version string `json:"version"`
3175
Time time.Time `json:"time"`
3276
Node string `json:"node,omitempty"`
3377
APIName string `json:"apiName,omitempty"`
78+
Category AuditCategory `json:"category,omitempty"`
79+
Action AuditAction `json:"action,omitempty"`
3480
Bucket string `json:"bucket,omitempty"`
3581
Tags map[string]string `json:"tags,omitempty"`
3682
RequestID string `json:"requestID,omitempty"`
3783
ReqClaims map[string]interface{} `json:"requestClaims,omitempty"`
3884
SourceHost string `json:"sourceHost,omitempty"`
3985
AccessKey string `json:"accessKey,omitempty"`
4086
ParentUser string `json:"parentUser,omitempty"`
87+
Details map[string]interface{} `json:"details,omitempty"`
88+
}
89+
90+
// ConfigAuditDetails captures config mutation details
91+
type ConfigAuditDetails struct {
92+
SubSystem string `json:"subSystem,omitempty"`
93+
Target string `json:"target,omitempty"`
94+
Key string `json:"key,omitempty"`
95+
OldValue string `json:"oldValue,omitempty"`
96+
NewValue string `json:"newValue,omitempty"`
97+
}
98+
99+
// UserAuditDetails captures user mutation details
100+
type UserAuditDetails struct {
101+
UserName string `json:"userName"`
102+
UserType string `json:"userType,omitempty"`
103+
Field string `json:"field,omitempty"`
104+
OldValue string `json:"oldValue,omitempty"`
105+
NewValue string `json:"newValue,omitempty"`
106+
OldStatus string `json:"oldStatus,omitempty"`
107+
NewStatus string `json:"newStatus,omitempty"`
108+
Policies []string `json:"policies,omitempty"`
109+
Groups []string `json:"groups,omitempty"`
110+
}
111+
112+
// ServiceAccountAuditDetails captures service account details
113+
type ServiceAccountAuditDetails struct {
114+
AccountName string `json:"accountName"`
115+
ParentUser string `json:"parentUser,omitempty"`
116+
Policies []string `json:"policies,omitempty"`
117+
Expiration time.Time `json:"expiration,omitempty"`
118+
UpdatedName string `json:"updatedName,omitempty"`
119+
UpdatedStatus string `json:"updatedStatus,omitempty"`
120+
UpdatedPolicy bool `json:"updatedPolicy,omitempty"`
121+
UpdatedExpiry bool `json:"updatedExpiry,omitempty"`
122+
UpdatedSecretKey bool `json:"updatedSecretKey,omitempty"`
123+
}
124+
125+
// PolicyAuditDetails captures policy mutation details
126+
type PolicyAuditDetails struct {
127+
PolicyName string `json:"policyName"`
128+
OldPolicy string `json:"oldPolicy,omitempty"`
129+
NewPolicy string `json:"newPolicy,omitempty"`
130+
Operation string `json:"operation,omitempty"`
131+
User string `json:"user,omitempty"`
132+
Group string `json:"group,omitempty"`
133+
PoliciesAttached []string `json:"policiesAttached,omitempty"`
134+
PoliciesDetached []string `json:"policiesDetached,omitempty"`
135+
}
136+
137+
// GroupAuditDetails captures group mutation details
138+
type GroupAuditDetails struct {
139+
GroupName string `json:"groupName"`
140+
MembersAdded []string `json:"membersAdded,omitempty"`
141+
MembersRemoved []string `json:"membersRemoved,omitempty"`
142+
OldStatus string `json:"oldStatus,omitempty"`
143+
NewStatus string `json:"newStatus,omitempty"`
144+
}
145+
146+
// BucketConfigAuditDetails captures bucket configuration changes
147+
type BucketConfigAuditDetails struct {
148+
BucketName string `json:"bucketName"`
149+
ConfigType string `json:"configType,omitempty"`
150+
OldConfig string `json:"oldConfig,omitempty"`
151+
NewConfig string `json:"newConfig,omitempty"`
152+
TargetBucket string `json:"targetBucket,omitempty"`
153+
TagKeys []string `json:"tagKeys,omitempty"`
154+
TagCount int `json:"tagCount,omitempty"`
155+
}
156+
157+
// ServiceAuditDetails captures service operation details
158+
type ServiceAuditDetails struct {
159+
ServiceName string `json:"serviceName,omitempty"`
160+
Operation string `json:"operation,omitempty"`
161+
Status string `json:"status,omitempty"`
162+
IAMImport *IAMImportDetails `json:"iamImport,omitempty"`
163+
}
164+
165+
// IAMImportDetails captures IAM import operation counts
166+
type IAMImportDetails struct {
167+
UsersAdded int `json:"usersAdded,omitempty"`
168+
PoliciesAdded int `json:"policiesAdded,omitempty"`
169+
GroupsAdded int `json:"groupsAdded,omitempty"`
170+
SvcAcctsAdded int `json:"svcAcctsAdded,omitempty"`
171+
UsersRemoved int `json:"usersRemoved,omitempty"`
172+
PoliciesRemoved int `json:"policiesRemoved,omitempty"`
173+
GroupsRemoved int `json:"groupsRemoved,omitempty"`
174+
SvcAcctsRemoved int `json:"svcAcctsRemoved,omitempty"`
175+
UsersSkipped int `json:"usersSkipped,omitempty"`
176+
PoliciesSkipped int `json:"policiesSkipped,omitempty"`
177+
GroupsSkipped int `json:"groupsSkipped,omitempty"`
178+
SvcAcctsSkipped int `json:"svcAcctsSkipped,omitempty"`
179+
UsersFailed int `json:"usersFailed,omitempty"`
180+
PoliciesFailed int `json:"policiesFailed,omitempty"`
181+
GroupsFailed int `json:"groupsFailed,omitempty"`
182+
SvcAcctsFailed int `json:"svcAcctsFailed,omitempty"`
183+
}
184+
185+
// KMSAuditDetails captures KMS operation details
186+
type KMSAuditDetails struct {
187+
KeyID string `json:"keyId,omitempty"`
188+
Operation string `json:"operation,omitempty"`
189+
}
190+
191+
// PoolAuditDetails captures pool operation details
192+
type PoolAuditDetails struct {
193+
PoolIndex int `json:"poolIndex,omitempty"`
194+
Endpoints []string `json:"endpoints,omitempty"`
195+
Operation string `json:"operation,omitempty"`
196+
}
197+
198+
// SiteReplicationAuditDetails captures site replication details
199+
type SiteReplicationAuditDetails struct {
200+
SiteName string `json:"siteName,omitempty"`
201+
Endpoint string `json:"endpoint,omitempty"`
202+
Operation string `json:"operation,omitempty"`
203+
Sites []string `json:"sites,omitempty"`
204+
}
205+
206+
// IDPAuditDetails captures identity provider configuration details
207+
type IDPAuditDetails struct {
208+
IDPName string `json:"idpName,omitempty"`
209+
IDPType string `json:"idpType,omitempty"`
210+
ConfigKey string `json:"configKey,omitempty"`
211+
OldValue string `json:"oldValue,omitempty"`
212+
NewValue string `json:"newValue,omitempty"`
213+
}
214+
215+
// LogRecorderAuditDetails captures log recorder configuration details
216+
type LogRecorderAuditDetails struct {
217+
LogType string `json:"logType,omitempty"`
218+
OldEnabled bool `json:"oldEnabled,omitempty"`
219+
NewEnabled bool `json:"newEnabled,omitempty"`
220+
OldLimit string `json:"oldLimit,omitempty"`
221+
NewLimit string `json:"newLimit,omitempty"`
222+
OldFlushCount int `json:"oldFlushCount,omitempty"`
223+
NewFlushCount int `json:"newFlushCount,omitempty"`
224+
OldFlushInterval string `json:"oldFlushInterval,omitempty"`
225+
NewFlushInterval string `json:"newFlushInterval,omitempty"`
41226
}
42227

43228
// String returns a canonical string for Audit
@@ -47,13 +232,16 @@ func (a Audit) String() string {
47232
toTime("time", a.Time),
48233
toString("node", a.Node),
49234
toString("apiName", a.APIName),
235+
toString("category", string(a.Category)),
236+
toString("action", string(a.Action)),
50237
toString("bucket", a.Bucket),
51238
toMap("tags", a.Tags),
52239
toString("requestID", a.RequestID),
53240
toInterfaceMap("requestClaims", a.ReqClaims),
54241
toString("sourceHost", a.SourceHost),
55242
toString("accessKey", a.AccessKey),
56243
toString("parentUser", a.ParentUser),
244+
toInterfaceMap("details", a.Details),
57245
}
58246
values = filterAndSort(values)
59247
return strings.Join(values, ",")

0 commit comments

Comments
 (0)