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

Commit29bac36

Browse files
authored
feat: add workspace auditing (#3966)
1 parent442df9e commit29bac36

File tree

4 files changed

+91
-15
lines changed

4 files changed

+91
-15
lines changed

‎coderd/users_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,8 @@ func TestPostUsers(t *testing.T) {
391391
Password:"testing",
392392
})
393393
require.NoError(t,err)
394-
assert.Len(t,auditor.AuditLogs,1)
394+
395+
require.Len(t,auditor.AuditLogs,1)
395396
assert.Equal(t,database.AuditActionCreate,auditor.AuditLogs[0].Action)
396397
})
397398
}

‎coderd/workspaces.go

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"cdr.dev/slog"
2424

25+
"github.com/coder/coder/coderd/audit"
2526
"github.com/coder/coder/coderd/autobuild/schedule"
2627
"github.com/coder/coder/coderd/database"
2728
"github.com/coder/coder/coderd/httpapi"
@@ -248,8 +249,18 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
248249

249250
// Create a new workspace for the currently authenticated user.
250251
func (api*API)postWorkspacesByOrganization(rw http.ResponseWriter,r*http.Request) {
251-
organization:=httpmw.OrganizationParam(r)
252-
apiKey:=httpmw.APIKey(r)
252+
var (
253+
organization=httpmw.OrganizationParam(r)
254+
apiKey=httpmw.APIKey(r)
255+
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
256+
Features:api.FeaturesService,
257+
Log:api.Logger,
258+
Request:r,
259+
Action:database.AuditActionCreate,
260+
})
261+
)
262+
defercommitAudit()
263+
253264
if!api.Authorize(r,rbac.ActionCreate,
254265
rbac.ResourceWorkspace.InOrg(organization.ID).WithOwner(apiKey.UserID.String())) {
255266
httpapi.ResourceNotFound(rw)
@@ -325,7 +336,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
325336
})
326337
return
327338
}
328-
if!errors.Is(err,sql.ErrNoRows) {
339+
iferr!=nil&&!errors.Is(err,sql.ErrNoRows) {
329340
httpapi.Write(rw,http.StatusInternalServerError, codersdk.Response{
330341
Message:fmt.Sprintf("Internal error fetching workspace by name %q.",createWorkspace.Name),
331342
Detail:err.Error(),
@@ -457,6 +468,8 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
457468
})
458469
return
459470
}
471+
aReq.New=workspace
472+
460473
users,err:=api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{apiKey.UserID,workspaceBuild.InitiatorID})
461474
iferr!=nil {
462475
httpapi.Write(rw,http.StatusInternalServerError, codersdk.Response{
@@ -476,7 +489,18 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
476489
}
477490

478491
func (api*API)patchWorkspace(rw http.ResponseWriter,r*http.Request) {
479-
workspace:=httpmw.WorkspaceParam(r)
492+
var (
493+
workspace=httpmw.WorkspaceParam(r)
494+
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
495+
Features:api.FeaturesService,
496+
Log:api.Logger,
497+
Request:r,
498+
Action:database.AuditActionWrite,
499+
})
500+
)
501+
defercommitAudit()
502+
aReq.Old=workspace
503+
480504
if!api.Authorize(r,rbac.ActionUpdate,workspace) {
481505
httpapi.ResourceNotFound(rw)
482506
return
@@ -488,18 +512,20 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
488512
}
489513

490514
ifreq.Name==""||req.Name==workspace.Name {
515+
aReq.New=workspace
491516
// Nothing changed, optionally this could be an error.
492517
rw.WriteHeader(http.StatusNoContent)
493518
return
494519
}
520+
495521
// The reason we double check here is in case more fields can be
496522
// patched in the future, it's enough if one changes.
497523
name:=workspace.Name
498524
ifreq.Name!=""||req.Name!=workspace.Name {
499525
name=req.Name
500526
}
501527

502-
_,err:=api.Database.UpdateWorkspace(r.Context(), database.UpdateWorkspaceParams{
528+
newWorkspace,err:=api.Database.UpdateWorkspace(r.Context(), database.UpdateWorkspaceParams{
503529
ID:workspace.ID,
504530
Name:name,
505531
})
@@ -534,11 +560,23 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
534560
return
535561
}
536562

563+
aReq.New=newWorkspace
537564
rw.WriteHeader(http.StatusNoContent)
538565
}
539566

540567
func (api*API)putWorkspaceAutostart(rw http.ResponseWriter,r*http.Request) {
541-
workspace:=httpmw.WorkspaceParam(r)
568+
var (
569+
workspace=httpmw.WorkspaceParam(r)
570+
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
571+
Features:api.FeaturesService,
572+
Log:api.Logger,
573+
Request:r,
574+
Action:database.AuditActionWrite,
575+
})
576+
)
577+
defercommitAudit()
578+
aReq.Old=workspace
579+
542580
if!api.Authorize(r,rbac.ActionUpdate,workspace) {
543581
httpapi.ResourceNotFound(rw)
544582
return
@@ -578,10 +616,26 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
578616
})
579617
return
580618
}
619+
620+
newWorkspace:=workspace
621+
newWorkspace.AutostartSchedule=dbSched
622+
aReq.New=newWorkspace
623+
624+
rw.WriteHeader(http.StatusNoContent)
581625
}
582626

583627
func (api*API)putWorkspaceTTL(rw http.ResponseWriter,r*http.Request) {
584-
workspace:=httpmw.WorkspaceParam(r)
628+
var (
629+
workspace=httpmw.WorkspaceParam(r)
630+
aReq,commitAudit=audit.InitRequest[database.Workspace](rw,&audit.RequestParams{
631+
Features:api.FeaturesService,
632+
Log:api.Logger,
633+
Request:r,
634+
Action:database.AuditActionWrite,
635+
})
636+
)
637+
defercommitAudit()
638+
585639
if!api.Authorize(r,rbac.ActionUpdate,workspace) {
586640
httpapi.ResourceNotFound(rw)
587641
return
@@ -592,6 +646,8 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
592646
return
593647
}
594648

649+
vardbTTL sql.NullInt64
650+
595651
err:=api.Database.InTx(func(s database.Store)error {
596652
template,err:=s.GetTemplateByID(r.Context(),workspace.TemplateID)
597653
iferr!=nil {
@@ -601,7 +657,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
601657
returnxerrors.Errorf("fetch workspace template: %w",err)
602658
}
603659

604-
dbTTL,err:=validWorkspaceTTLMillis(req.TTLMillis,time.Duration(template.MaxTtl))
660+
dbTTL,err=validWorkspaceTTLMillis(req.TTLMillis,time.Duration(template.MaxTtl))
605661
iferr!=nil {
606662
return codersdk.ValidationError{Field:"ttl_ms",Detail:err.Error()}
607663
}
@@ -630,7 +686,11 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
630686
return
631687
}
632688

633-
httpapi.Write(rw,http.StatusOK,nil)
689+
newWorkspace:=workspace
690+
newWorkspace.Ttl=dbTTL
691+
aReq.New=newWorkspace
692+
693+
rw.WriteHeader(http.StatusNoContent)
634694
}
635695

636696
func (api*API)putExtendWorkspace(rw http.ResponseWriter,r*http.Request) {

‎coderd/workspaces_test.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ import (
99
"time"
1010

1111
"github.com/google/uuid"
12+
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
1314

15+
"github.com/coder/coder/coderd/audit"
1416
"github.com/coder/coder/coderd/autobuild/schedule"
1517
"github.com/coder/coder/coderd/coderdtest"
18+
"github.com/coder/coder/coderd/database"
1619
"github.com/coder/coder/coderd/rbac"
1720
"github.com/coder/coder/coderd/util/ptr"
1821
"github.com/coder/coder/codersdk"
@@ -214,12 +217,16 @@ func TestPostWorkspacesByOrganization(t *testing.T) {
214217

215218
t.Run("Create",func(t*testing.T) {
216219
t.Parallel()
217-
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
220+
auditor:=audit.NewMock()
221+
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true,Auditor:auditor})
218222
user:=coderdtest.CreateFirstUser(t,client)
219223
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
220224
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
221225
coderdtest.AwaitTemplateVersionJob(t,client,version.ID)
222226
_=coderdtest.CreateWorkspace(t,client,user.OrganizationID,template.ID)
227+
228+
require.Len(t,auditor.AuditLogs,4)
229+
assert.Equal(t,database.AuditActionCreate,auditor.AuditLogs[3].Action)
223230
})
224231

225232
t.Run("TemplateNoTTL",func(t*testing.T) {
@@ -949,7 +956,8 @@ func TestWorkspaceUpdateAutostart(t *testing.T) {
949956
t.Run(testCase.name,func(t*testing.T) {
950957
t.Parallel()
951958
var (
952-
client=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
959+
auditor=audit.NewMock()
960+
client=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true,Auditor:auditor})
953961
user=coderdtest.CreateFirstUser(t,client)
954962
version=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
955963
_=coderdtest.AwaitTemplateVersionJob(t,client,version.ID)
@@ -994,6 +1002,9 @@ func TestWorkspaceUpdateAutostart(t *testing.T) {
9941002
require.Equal(t,testCase.expectedNext,next,"unexpected next scheduled autostart time")
9951003
interval:=next.Sub(testCase.at)
9961004
require.Equal(t,testCase.expectedInterval,interval,"unexpected interval")
1005+
1006+
require.Len(t,auditor.AuditLogs,5)
1007+
assert.Equal(t,database.AuditActionWrite,auditor.AuditLogs[4].Action)
9971008
})
9981009
}
9991010

@@ -1086,7 +1097,8 @@ func TestWorkspaceUpdateTTL(t *testing.T) {
10861097
mutators=append(mutators,testCase.modifyTemplate)
10871098
}
10881099
var (
1089-
client=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
1100+
auditor=audit.NewMock()
1101+
client=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true,Auditor:auditor})
10901102
user=coderdtest.CreateFirstUser(t,client)
10911103
version=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
10921104
_=coderdtest.AwaitTemplateVersionJob(t,client,version.ID)
@@ -1116,6 +1128,9 @@ func TestWorkspaceUpdateTTL(t *testing.T) {
11161128
require.NoError(t,err,"fetch updated workspace")
11171129

11181130
require.Equal(t,testCase.ttlMillis,updated.TTLMillis,"expected autostop ttl to equal requested")
1131+
1132+
require.Len(t,auditor.AuditLogs,5)
1133+
assert.Equal(t,database.AuditActionWrite,auditor.AuditLogs[4].Action)
11191134
})
11201135
}
11211136

‎codersdk/workspaces.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ func (c *Client) UpdateWorkspaceAutostart(ctx context.Context, id uuid.UUID, req
183183
returnxerrors.Errorf("update workspace autostart: %w",err)
184184
}
185185
deferres.Body.Close()
186-
ifres.StatusCode!=http.StatusOK {
186+
ifres.StatusCode!=http.StatusNoContent {
187187
returnreadBodyAsError(res)
188188
}
189189
returnnil
@@ -203,7 +203,7 @@ func (c *Client) UpdateWorkspaceTTL(ctx context.Context, id uuid.UUID, req Updat
203203
returnxerrors.Errorf("update workspace time until shutdown: %w",err)
204204
}
205205
deferres.Body.Close()
206-
ifres.StatusCode!=http.StatusOK {
206+
ifres.StatusCode!=http.StatusNoContent {
207207
returnreadBodyAsError(res)
208208
}
209209
returnnil

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp