Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf44c89d

Browse files
authored
chore: enforce orgid in audit logs where required (#12283)
* chore: enforce orgid in audit logs where required
1 parent74b749b commitf44c89d

File tree

6 files changed

+154
-80
lines changed

6 files changed

+154
-80
lines changed

‎coderd/audit/request.go

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"database/sql"
66
"encoding/json"
7+
"flag"
78
"fmt"
89
"net"
910
"net/http"
@@ -25,6 +26,9 @@ type RequestParams struct {
2526
AuditAuditor
2627
Log slog.Logger
2728

29+
// OrganizationID is only provided when possible. If an audit resource extends
30+
// beyond the org scope, leave this as the nil uuid.
31+
OrganizationID uuid.UUID
2832
Request*http.Request
2933
Action database.AuditAction
3034
AdditionalFields json.RawMessage
@@ -96,7 +100,7 @@ func ResourceTarget[T Auditable](tgt T) string {
96100
case database.HealthSettings:
97101
return""// no target?
98102
default:
99-
panic(fmt.Sprintf("unknown resource %T",tgt))
103+
panic(fmt.Sprintf("unknown resource %T for ResourceTarget",tgt))
100104
}
101105
}
102106

@@ -129,7 +133,7 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
129133
// Artificial ID for auditing purposes
130134
returntyped.ID
131135
default:
132-
panic(fmt.Sprintf("unknown resource %T",tgt))
136+
panic(fmt.Sprintf("unknown resource %T for ResourceID",tgt))
133137
}
134138
}
135139

@@ -160,8 +164,57 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
160164
case database.HealthSettings:
161165
returndatabase.ResourceTypeHealthSettings
162166
default:
163-
panic(fmt.Sprintf("unknown resource %T",typed))
167+
panic(fmt.Sprintf("unknown resource %T for ResourceType",typed))
168+
}
169+
}
170+
171+
// ResourceRequiresOrgID will ensure given resources are always audited with an
172+
// organization ID.
173+
funcResourceRequiresOrgID[TAuditable]()bool {
174+
vartgtT
175+
switchany(tgt).(type) {
176+
case database.Template, database.TemplateVersion:
177+
returntrue
178+
case database.Workspace, database.WorkspaceBuild:
179+
returntrue
180+
case database.AuditableGroup:
181+
returntrue
182+
case database.User:
183+
returnfalse
184+
case database.GitSSHKey:
185+
returnfalse
186+
case database.APIKey:
187+
returnfalse
188+
case database.License:
189+
returnfalse
190+
case database.WorkspaceProxy:
191+
returnfalse
192+
case database.AuditOAuthConvertState:
193+
// The merge state is for the given user
194+
returnfalse
195+
case database.HealthSettings:
196+
// Artificial ID for auditing purposes
197+
returnfalse
198+
default:
199+
panic(fmt.Sprintf("unknown resource %T for ResourceRequiresOrgID",tgt))
200+
}
201+
}
202+
203+
// requireOrgID will either panic (in unit tests) or log an error (in production)
204+
// if the given resource requires an organization ID and the provided ID is nil.
205+
funcrequireOrgID[TAuditable](ctx context.Context,id uuid.UUID,log slog.Logger) uuid.UUID {
206+
ifResourceRequiresOrgID[T]()&&id==uuid.Nil {
207+
vartgtT
208+
resourceName:=fmt.Sprintf("%T",tgt)
209+
ifflag.Lookup("test.v")!=nil {
210+
// In unit tests we panic to fail the tests
211+
panic(fmt.Sprintf("missing required organization ID for resource %q",resourceName))
212+
}
213+
log.Error(ctx,"missing required organization ID for resource in audit log",
214+
slog.F("resource",resourceName),
215+
)
164216
}
217+
returnid
165218
}
166219

167220
// InitRequest initializes an audit log for a request. It returns a function
@@ -243,6 +296,7 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request
243296
StatusCode:int32(sw.Status),
244297
RequestID:httpmw.RequestID(p.Request),
245298
AdditionalFields:p.AdditionalFields,
299+
OrganizationID:requireOrgID[T](logCtx,p.OrganizationID,p.Log),
246300
}
247301
err:=p.Audit.Export(ctx,auditLog)
248302
iferr!=nil {
@@ -276,7 +330,7 @@ func BackgroundAudit[T Auditable](ctx context.Context, p *BackgroundAuditParams[
276330
ID:uuid.New(),
277331
Time:dbtime.Now(),
278332
UserID:p.UserID,
279-
OrganizationID:p.OrganizationID,
333+
OrganizationID:requireOrgID[T](ctx,p.OrganizationID,p.Log),
280334
Ip:ip,
281335
UserAgent: sql.NullString{},
282336
ResourceType:either(p.Old,p.New,ResourceType[T],p.Action),

‎coderd/templates.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,11 @@ func (api *API) deleteTemplate(rw http.ResponseWriter, r *http.Request) {
5757
template=httpmw.TemplateParam(r)
5858
auditor=*api.Auditor.Load()
5959
aReq,commitAudit=audit.InitRequest[database.Template](rw,&audit.RequestParams{
60-
Audit:auditor,
61-
Log:api.Logger,
62-
Request:r,
63-
Action:database.AuditActionDelete,
60+
Audit:auditor,
61+
Log:api.Logger,
62+
Request:r,
63+
Action:database.AuditActionDelete,
64+
OrganizationID:template.OrganizationID,
6465
})
6566
)
6667
defercommitAudit()
@@ -123,16 +124,18 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
123124
apiKey=httpmw.APIKey(r)
124125
auditor=*api.Auditor.Load()
125126
templateAudit,commitTemplateAudit=audit.InitRequest[database.Template](rw,&audit.RequestParams{
126-
Audit:auditor,
127-
Log:api.Logger,
128-
Request:r,
129-
Action:database.AuditActionCreate,
127+
Audit:auditor,
128+
Log:api.Logger,
129+
Request:r,
130+
Action:database.AuditActionCreate,
131+
OrganizationID:organization.ID,
130132
})
131133
templateVersionAudit,commitTemplateVersionAudit=audit.InitRequest[database.TemplateVersion](rw,&audit.RequestParams{
132-
Audit:auditor,
133-
Log:api.Logger,
134-
Request:r,
135-
Action:database.AuditActionWrite,
134+
Audit:auditor,
135+
Log:api.Logger,
136+
Request:r,
137+
Action:database.AuditActionWrite,
138+
OrganizationID:organization.ID,
136139
})
137140
)
138141
defercommitTemplateAudit()
@@ -542,10 +545,11 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
542545
auditor=*api.Auditor.Load()
543546
portSharer=*api.PortSharer.Load()
544547
aReq,commitAudit=audit.InitRequest[database.Template](rw,&audit.RequestParams{
545-
Audit:auditor,
546-
Log:api.Logger,
547-
Request:r,
548-
Action:database.AuditActionWrite,
548+
Audit:auditor,
549+
Log:api.Logger,
550+
Request:r,
551+
Action:database.AuditActionWrite,
552+
OrganizationID:template.OrganizationID,
549553
})
550554
)
551555
defercommitAudit()

‎coderd/templateversions.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,10 +1040,11 @@ func (api *API) postArchiveTemplateVersions(rw http.ResponseWriter, r *http.Requ
10401040
template=httpmw.TemplateParam(r)
10411041
auditor=*api.Auditor.Load()
10421042
aReq,commitAudit=audit.InitRequest[database.Template](rw,&audit.RequestParams{
1043-
Audit:auditor,
1044-
Log:api.Logger,
1045-
Request:r,
1046-
Action:database.AuditActionWrite,
1043+
Audit:auditor,
1044+
Log:api.Logger,
1045+
Request:r,
1046+
Action:database.AuditActionWrite,
1047+
OrganizationID:template.OrganizationID,
10471048
})
10481049
)
10491050
defercommitAudit()
@@ -1122,10 +1123,11 @@ func (api *API) setArchiveTemplateVersion(archive bool) func(rw http.ResponseWri
11221123
templateVersion=httpmw.TemplateVersionParam(r)
11231124
auditor=*api.Auditor.Load()
11241125
aReq,commitAudit=audit.InitRequest[database.TemplateVersion](rw,&audit.RequestParams{
1125-
Audit:auditor,
1126-
Log:api.Logger,
1127-
Request:r,
1128-
Action:database.AuditActionWrite,
1126+
Audit:auditor,
1127+
Log:api.Logger,
1128+
Request:r,
1129+
Action:database.AuditActionWrite,
1130+
OrganizationID:templateVersion.OrganizationID,
11291131
})
11301132
)
11311133
defercommitAudit()
@@ -1207,10 +1209,11 @@ func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Reque
12071209
template=httpmw.TemplateParam(r)
12081210
auditor=*api.Auditor.Load()
12091211
aReq,commitAudit=audit.InitRequest[database.Template](rw,&audit.RequestParams{
1210-
Audit:auditor,
1211-
Log:api.Logger,
1212-
Request:r,
1213-
Action:database.AuditActionWrite,
1212+
Audit:auditor,
1213+
Log:api.Logger,
1214+
Request:r,
1215+
Action:database.AuditActionWrite,
1216+
OrganizationID:template.OrganizationID,
12141217
})
12151218
)
12161219
defercommitAudit()
@@ -1310,10 +1313,11 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
13101313
organization=httpmw.OrganizationParam(r)
13111314
auditor=*api.Auditor.Load()
13121315
aReq,commitAudit=audit.InitRequest[database.TemplateVersion](rw,&audit.RequestParams{
1313-
Audit:auditor,
1314-
Log:api.Logger,
1315-
Request:r,
1316-
Action:database.AuditActionCreate,
1316+
Audit:auditor,
1317+
Log:api.Logger,
1318+
Request:r,
1319+
Action:database.AuditActionCreate,
1320+
OrganizationID:organization.ID,
13171321
})
13181322

13191323
req codersdk.CreateTemplateVersionRequest

‎coderd/workspaces.go

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
345345
Request:r,
346346
Action:database.AuditActionCreate,
347347
AdditionalFields:wriBytes,
348+
OrganizationID:organization.ID,
348349
})
349350

350351
defercommitAudit()
@@ -644,10 +645,11 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
644645
workspace=httpmw.WorkspaceParam(r)
645646
auditor=api.Auditor.Load()
646647
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
647-
Audit:*auditor,
648-
Log:api.Logger,
649-
Request:r,
650-
Action:database.AuditActionWrite,
648+
Audit:*auditor,
649+
Log:api.Logger,
650+
Request:r,
651+
Action:database.AuditActionWrite,
652+
OrganizationID:workspace.OrganizationID,
651653
})
652654
)
653655
defercommitAudit()
@@ -734,10 +736,11 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
734736
workspace=httpmw.WorkspaceParam(r)
735737
auditor=api.Auditor.Load()
736738
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
737-
Audit:*auditor,
738-
Log:api.Logger,
739-
Request:r,
740-
Action:database.AuditActionWrite,
739+
Audit:*auditor,
740+
Log:api.Logger,
741+
Request:r,
742+
Action:database.AuditActionWrite,
743+
OrganizationID:workspace.OrganizationID,
741744
})
742745
)
743746
defercommitAudit()
@@ -808,10 +811,11 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
808811
workspace=httpmw.WorkspaceParam(r)
809812
auditor=api.Auditor.Load()
810813
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
811-
Audit:*auditor,
812-
Log:api.Logger,
813-
Request:r,
814-
Action:database.AuditActionWrite,
814+
Audit:*auditor,
815+
Log:api.Logger,
816+
Request:r,
817+
Action:database.AuditActionWrite,
818+
OrganizationID:workspace.OrganizationID,
815819
})
816820
)
817821
defercommitAudit()
@@ -896,10 +900,11 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
896900
oldWorkspace=workspace
897901
auditor=api.Auditor.Load()
898902
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
899-
Audit:*auditor,
900-
Log:api.Logger,
901-
Request:r,
902-
Action:database.AuditActionWrite,
903+
Audit:*auditor,
904+
Log:api.Logger,
905+
Request:r,
906+
Action:database.AuditActionWrite,
907+
OrganizationID:workspace.OrganizationID,
903908
})
904909
)
905910
aReq.Old=oldWorkspace
@@ -1094,10 +1099,11 @@ func (api *API) putFavoriteWorkspace(rw http.ResponseWriter, r *http.Request) {
10941099
}
10951100

10961101
aReq,commitAudit:=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
1097-
Audit:*auditor,
1098-
Log:api.Logger,
1099-
Request:r,
1100-
Action:database.AuditActionWrite,
1102+
Audit:*auditor,
1103+
Log:api.Logger,
1104+
Request:r,
1105+
Action:database.AuditActionWrite,
1106+
OrganizationID:workspace.OrganizationID,
11011107
})
11021108
defercommitAudit()
11031109
aReq.Old=workspace
@@ -1140,10 +1146,11 @@ func (api *API) deleteFavoriteWorkspace(rw http.ResponseWriter, r *http.Request)
11401146
}
11411147

11421148
aReq,commitAudit:=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
1143-
Audit:*auditor,
1144-
Log:api.Logger,
1145-
Request:r,
1146-
Action:database.AuditActionWrite,
1149+
Audit:*auditor,
1150+
Log:api.Logger,
1151+
Request:r,
1152+
Action:database.AuditActionWrite,
1153+
OrganizationID:workspace.OrganizationID,
11471154
})
11481155

11491156
defercommitAudit()
@@ -1178,10 +1185,11 @@ func (api *API) putWorkspaceAutoupdates(rw http.ResponseWriter, r *http.Request)
11781185
workspace=httpmw.WorkspaceParam(r)
11791186
auditor=api.Auditor.Load()
11801187
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
1181-
Audit:*auditor,
1182-
Log:api.Logger,
1183-
Request:r,
1184-
Action:database.AuditActionWrite,
1188+
Audit:*auditor,
1189+
Log:api.Logger,
1190+
Request:r,
1191+
Action:database.AuditActionWrite,
1192+
OrganizationID:workspace.OrganizationID,
11851193
})
11861194
)
11871195
defercommitAudit()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp