From 58258bab8a21d66d0edd4e065cc88db693b57586 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 8 Feb 2023 20:16:41 +0000 Subject: [PATCH 01/10] added license audit resource --- coderd/apidoc/docs.go | 6 +++-- coderd/apidoc/swagger.json | 6 +++-- coderd/audit/request.go | 8 ++++++ coderd/database/dump.sql | 3 ++- .../000097_add_resource_type_license.down.sql | 2 ++ .../000097_add_resource_type_license.up.sql | 3 +++ coderd/database/models.go | 5 +++- codersdk/audit.go | 1 + docs/admin/audit-logs.md | 1 + docs/api/schemas.md | 1 + enterprise/audit/table.go | 26 ++++++++++++------- site/src/api/typesGenerated.ts | 2 ++ 12 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 coderd/database/migrations/000097_add_resource_type_license.down.sql create mode 100644 coderd/database/migrations/000097_add_resource_type_license.up.sql diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 2559e1e0ed619..a6765ce97c0f7 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -7202,7 +7202,8 @@ const docTemplate = `{ "workspace_build", "git_ssh_key", "api_key", - "group" + "group", + "license" ], "x-enum-varnames": [ "ResourceTypeTemplate", @@ -7212,7 +7213,8 @@ const docTemplate = `{ "ResourceTypeWorkspaceBuild", "ResourceTypeGitSSHKey", "ResourceTypeAPIKey", - "ResourceTypeGroup" + "ResourceTypeGroup", + "ResourceTypeLicense" ] }, "codersdk.Response": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 97acc0d3e3f36..93c1fa76ad62e 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -6457,7 +6457,8 @@ "workspace_build", "git_ssh_key", "api_key", - "group" + "group", + "license" ], "x-enum-varnames": [ "ResourceTypeTemplate", @@ -6467,7 +6468,8 @@ "ResourceTypeWorkspaceBuild", "ResourceTypeGitSSHKey", "ResourceTypeAPIKey", - "ResourceTypeGroup" + "ResourceTypeGroup", + "ResourceTypeLicense" ] }, "codersdk.Response": { diff --git a/coderd/audit/request.go b/coderd/audit/request.go index 186434345ce82..633253b6821a1 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "net/http" + "strconv" "github.com/google/uuid" "github.com/tabbed/pqtype" @@ -71,6 +72,8 @@ func ResourceTarget[T Auditable](tgt T) string { case database.APIKey: // this isn't used return "" + case database.License: + return strconv.FormatInt(int64(typed.ID), 10) default: panic(fmt.Sprintf("unknown resource %T", tgt)) } @@ -94,6 +97,9 @@ func ResourceID[T Auditable](tgt T) uuid.UUID { return typed.Group.ID case database.APIKey: return typed.UserID + case database.License: + // this isn't right + return uuid.Nil default: panic(fmt.Sprintf("unknown resource %T", tgt)) } @@ -117,6 +123,8 @@ func ResourceType[T Auditable](tgt T) database.ResourceType { return database.ResourceTypeGroup case database.APIKey: return database.ResourceTypeApiKey + case database.License: + return database.ResourceTypeLicense default: panic(fmt.Sprintf("unknown resource %T", tgt)) } diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index e8bf641dd59e6..9de86360f02a7 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -93,7 +93,8 @@ CREATE TYPE resource_type AS ENUM ( 'git_ssh_key', 'api_key', 'group', - 'workspace_build' + 'workspace_build', + 'license' ); CREATE TYPE user_status AS ENUM ( diff --git a/coderd/database/migrations/000097_add_resource_type_license.down.sql b/coderd/database/migrations/000097_add_resource_type_license.down.sql new file mode 100644 index 0000000000000..d1d1637f4fa90 --- /dev/null +++ b/coderd/database/migrations/000097_add_resource_type_license.down.sql @@ -0,0 +1,2 @@ +-- It's not possible to drop enum values from enum types, so the UP has "IF NOT +-- EXISTS". diff --git a/coderd/database/migrations/000097_add_resource_type_license.up.sql b/coderd/database/migrations/000097_add_resource_type_license.up.sql new file mode 100644 index 0000000000000..43656a940b83d --- /dev/null +++ b/coderd/database/migrations/000097_add_resource_type_license.up.sql @@ -0,0 +1,3 @@ +ALTER TYPE resource_type + ADD VALUE IF NOT EXISTS 'license'; + diff --git a/coderd/database/models.go b/coderd/database/models.go index ce5d2204a7266..22b9709c9fa54 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -883,6 +883,7 @@ const ( ResourceTypeApiKey ResourceType = "api_key" ResourceTypeGroup ResourceType = "group" ResourceTypeWorkspaceBuild ResourceType = "workspace_build" + ResourceTypeLicense ResourceType = "license" ) func (e *ResourceType) Scan(src interface{}) error { @@ -930,7 +931,8 @@ func (e ResourceType) Valid() bool { ResourceTypeGitSshKey, ResourceTypeApiKey, ResourceTypeGroup, - ResourceTypeWorkspaceBuild: + ResourceTypeWorkspaceBuild, + ResourceTypeLicense: return true } return false @@ -947,6 +949,7 @@ func AllResourceTypeValues() []ResourceType { ResourceTypeApiKey, ResourceTypeGroup, ResourceTypeWorkspaceBuild, + ResourceTypeLicense, } } diff --git a/codersdk/audit.go b/codersdk/audit.go index 49648e5e9440a..13f6fd334e1ea 100644 --- a/codersdk/audit.go +++ b/codersdk/audit.go @@ -22,6 +22,7 @@ const ( ResourceTypeGitSSHKey ResourceType = "git_ssh_key" ResourceTypeAPIKey ResourceType = "api_key" ResourceTypeGroup ResourceType = "group" + ResourceTypeLicense ResourceType = "license" ) func (r ResourceType) FriendlyString() string { diff --git a/docs/admin/audit-logs.md b/docs/admin/audit-logs.md index a705b9e371d56..25c6d719c31df 100644 --- a/docs/admin/audit-logs.md +++ b/docs/admin/audit-logs.md @@ -14,6 +14,7 @@ We track the following resources: | APIKey
write |
FieldTracked
created_atfalse
expires_atfalse
hashed_secretfalse
idfalse
ip_addressfalse
last_usedfalse
lifetime_secondsfalse
login_typefalse
scopefalse
updated_atfalse
user_idfalse
| | Group
create, write, delete |
FieldTracked
avatar_urltrue
idtrue
memberstrue
nametrue
organization_idfalse
quota_allowancetrue
| | GitSSHKey
create |
FieldTracked
created_atfalse
private_keytrue
public_keytrue
updated_atfalse
user_idtrue
| +| License
create, delete |
FieldTracked
exptrue
idtrue
jwtfalse
uploaded_atfalse
uuidfalse
| | Template
write, delete |
FieldTracked
active_version_idtrue
allow_user_cancel_workspace_jobstrue
created_atfalse
created_bytrue
default_ttltrue
deletedfalse
descriptiontrue
display_nametrue
group_acltrue
icontrue
idtrue
is_privatetrue
min_autostart_intervaltrue
nametrue
organization_idfalse
provisionertrue
updated_atfalse
user_acltrue
| | TemplateVersion
create, write |
FieldTracked
created_atfalse
created_bytrue
idtrue
job_idfalse
nametrue
organization_idfalse
readmetrue
template_idtrue
updated_atfalse
| | User
create, write, delete |
FieldTracked
avatar_urlfalse
created_atfalse
deletedtrue
emailtrue
hashed_passwordtrue
idtrue
last_seen_atfalse
login_typefalse
rbac_rolestrue
statustrue
updated_atfalse
usernametrue
| diff --git a/docs/api/schemas.md b/docs/api/schemas.md index ccb651b521411..c9046578917df 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -3991,6 +3991,7 @@ Parameter represents a set value for the scope. | `git_ssh_key` | | `api_key` | | `group` | +| `license` | ## codersdk.Response diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index ffc0f303bd25a..b5fe6f651942c 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -13,16 +13,15 @@ import ( // AuditableResources map (below) as our documentation - generated in scripts/auditdocgen/main.go - // depends upon it. var AuditActionMap = map[string][]codersdk.AuditAction{ - "GitSSHKey": {codersdk.AuditActionCreate}, - "OrganizationMember": {}, - "Organization": {}, - "Template": {codersdk.AuditActionWrite, codersdk.AuditActionDelete}, - "TemplateVersion": {codersdk.AuditActionCreate, codersdk.AuditActionWrite}, - "User": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete}, - "Workspace": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete}, - "WorkspaceBuild": {codersdk.AuditActionStart, codersdk.AuditActionStop}, - "Group": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete}, - "APIKey": {codersdk.AuditActionWrite}, + "GitSSHKey": {codersdk.AuditActionCreate}, + "Template": {codersdk.AuditActionWrite, codersdk.AuditActionDelete}, + "TemplateVersion": {codersdk.AuditActionCreate, codersdk.AuditActionWrite}, + "User": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete}, + "Workspace": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete}, + "WorkspaceBuild": {codersdk.AuditActionStart, codersdk.AuditActionStop}, + "Group": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete}, + "APIKey": {codersdk.AuditActionWrite}, + "License": {codersdk.AuditActionCreate, codersdk.AuditActionDelete}, } type Action string @@ -147,6 +146,13 @@ var AuditableResources = auditMap(map[any]map[string]Action{ "ip_address": ActionIgnore, "scope": ActionIgnore, }, + &database.License{}: { + "id": ActionTrack, + "uploaded_at": ActionIgnore, + "jwt": ActionIgnore, + "exp": ActionTrack, + "uuid": ActionIgnore, + }, }) // auditMap converts a map of struct pointers to a map of struct names as diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 471e2e5eb07cf..86fe9cb965b52 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1180,6 +1180,7 @@ export type ResourceType = | "api_key" | "git_ssh_key" | "group" + | "license" | "template" | "template_version" | "user" @@ -1189,6 +1190,7 @@ export const ResourceTypes: ResourceType[] = [ "api_key", "git_ssh_key", "group", + "license", "template", "template_version", "user", From 6c7429243b45a7025d85be85250f77edfa4b764f Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 8 Feb 2023 22:10:09 +0000 Subject: [PATCH 02/10] audit delete licenses --- coderd/audit/diff.go | 3 +- coderd/audit/request.go | 7 +++- coderd/database/dbfake/databasefake.go | 12 +++++++ coderd/database/querier.go | 1 + coderd/database/queries.sql.go | 19 ++++++++++ coderd/database/queries/licenses.sql | 5 +++ codersdk/audit.go | 2 ++ enterprise/coderd/licenses.go | 48 ++++++++++++++++++++++---- 8 files changed, 89 insertions(+), 8 deletions(-) diff --git a/coderd/audit/diff.go b/coderd/audit/diff.go index df1f4b334ab03..1cc6702d1b06c 100644 --- a/coderd/audit/diff.go +++ b/coderd/audit/diff.go @@ -15,7 +15,8 @@ type Auditable interface { database.Workspace | database.GitSSHKey | database.WorkspaceBuild | - database.AuditableGroup + database.AuditableGroup | + database.License } // Map is a map of changed fields in an audited resource. It maps field names to diff --git a/coderd/audit/request.go b/coderd/audit/request.go index 633253b6821a1..f3198853e6c57 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -99,7 +99,7 @@ func ResourceID[T Auditable](tgt T) uuid.UUID { return typed.UserID case database.License: // this isn't right - return uuid.Nil + return uuid.New() default: panic(fmt.Sprintf("unknown resource %T", tgt)) } @@ -134,6 +134,7 @@ func ResourceType[T Auditable](tgt T) database.ResourceType { // that should be deferred, causing the audit log to be committed when the // handler returns. func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request[T], func()) { + fmt.Println("im in the init request") sw, ok := w.(*tracing.StatusWriter) if !ok { panic("dev error: http.ResponseWriter is not *tracing.StatusWriter") @@ -144,6 +145,8 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request } return req, func() { + fmt.Println("im in the init request callback") + ctx := context.Background() logCtx := p.Request.Context() @@ -155,6 +158,8 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request // TODO: introduce the concept of an anonymous user so we always have a userID even // when dealing with a mystery user. https://github.com/coder/coder/issues/6054 if req.params.Action != database.AuditActionLogin && req.params.Action != database.AuditActionLogout { + fmt.Println("im silently bailing") + return } } diff --git a/coderd/database/dbfake/databasefake.go b/coderd/database/dbfake/databasefake.go index 01ad6942d6b10..ab6b19800c436 100644 --- a/coderd/database/dbfake/databasefake.go +++ b/coderd/database/dbfake/databasefake.go @@ -3808,6 +3808,18 @@ func (q *fakeQuerier) InsertLicense( return l, nil } +func (q *fakeQuerier) GetLicense(_ context.Context, id int32) (database.License, error) { + q.mutex.RLock() + defer q.mutex.RUnlock() + + for _, l := range q.licenses { + if l.ID == id { + return l, nil + } + } + return database.License{}, sql.ErrNoRows +} + func (q *fakeQuerier) GetLicenses(_ context.Context) ([]database.License, error) { q.mutex.RLock() defer q.mutex.RUnlock() diff --git a/coderd/database/querier.go b/coderd/database/querier.go index a588b28076233..93f398d255c9b 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -56,6 +56,7 @@ type sqlcQuerier interface { GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (WorkspaceBuild, error) GetLatestWorkspaceBuilds(ctx context.Context) ([]WorkspaceBuild, error) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceBuild, error) + GetLicense(ctx context.Context, id int32) (License, error) GetLicenses(ctx context.Context) ([]License, error) GetLogoURL(ctx context.Context) (string, error) GetOrganizationByID(ctx context.Context, id uuid.UUID) (Organization, error) diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 9ed8530997320..f22a2fd569940 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -1343,6 +1343,25 @@ func (q *sqlQuerier) DeleteLicense(ctx context.Context, id int32) (int32, error) return id, err } +const getLicense = `-- name: GetLicense :one +SELECT id, uploaded_at, jwt, exp, uuid +FROM licenses +WHERE id = $1 +` + +func (q *sqlQuerier) GetLicense(ctx context.Context, id int32) (License, error) { + row := q.db.QueryRowContext(ctx, getLicense, id) + var i License + err := row.Scan( + &i.ID, + &i.UploadedAt, + &i.JWT, + &i.Exp, + &i.Uuid, + ) + return i, err +} + const getLicenses = `-- name: GetLicenses :many SELECT id, uploaded_at, jwt, exp, uuid FROM licenses diff --git a/coderd/database/queries/licenses.sql b/coderd/database/queries/licenses.sql index 1622151a477f1..ac312ba85ffff 100644 --- a/coderd/database/queries/licenses.sql +++ b/coderd/database/queries/licenses.sql @@ -9,6 +9,11 @@ INSERT INTO VALUES ($1, $2, $3, $4) RETURNING *; +-- name: GetLicense :one +SELECT * +FROM licenses +WHERE id = $1; + -- name: GetLicenses :many SELECT * FROM licenses diff --git a/codersdk/audit.go b/codersdk/audit.go index 13f6fd334e1ea..464d350fc5532 100644 --- a/codersdk/audit.go +++ b/codersdk/audit.go @@ -45,6 +45,8 @@ func (r ResourceType) FriendlyString() string { return "api key" case ResourceTypeGroup: return "group" + case ResourceTypeLicense: + return "license" default: return "unknown" } diff --git a/enterprise/coderd/licenses.go b/enterprise/coderd/licenses.go index ef3f6c9d44882..c4fcf11ae4ffd 100644 --- a/enterprise/coderd/licenses.go +++ b/enterprise/coderd/licenses.go @@ -8,6 +8,7 @@ import ( _ "embed" "encoding/base64" "encoding/json" + "fmt" "net/http" "strconv" "strings" @@ -20,6 +21,7 @@ import ( "cdr.dev/slog" "github.com/coder/coder/coderd" + "github.com/coder/coder/coderd/audit" "github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/rbac" @@ -59,7 +61,19 @@ var Keys = map[string]ed25519.PublicKey{"2022-08-12": ed25519.PublicKey(key20220 // @Success 201 {object} codersdk.License // @Router /licenses [post] func (api *API) postLicense(rw http.ResponseWriter, r *http.Request) { - ctx := r.Context() + fmt.Println("im in postLicense") + var ( + ctx = r.Context() + auditor = api.AGPL.Auditor.Load() + aReq, commitAudit = audit.InitRequest[database.License](rw, &audit.RequestParams{ + Audit: *auditor, + Log: api.Logger, + Request: r, + Action: database.AuditActionCreate, + }) + ) + defer commitAudit() + if !api.AGPL.Authorize(r, rbac.ActionCreate, rbac.ResourceLicense) { httpapi.Forbidden(rw) return @@ -114,6 +128,8 @@ func (api *API) postLicense(rw http.ResponseWriter, r *http.Request) { }) return } + aReq.New = dl + err = api.updateEntitlements(ctx) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ @@ -181,11 +197,10 @@ func (api *API) licenses(rw http.ResponseWriter, r *http.Request) { // @Success 200 // @Router /licenses/{id} [delete] func (api *API) deleteLicense(rw http.ResponseWriter, r *http.Request) { - ctx := r.Context() - if !api.AGPL.Authorize(r, rbac.ActionDelete, rbac.ResourceLicense) { - httpapi.Forbidden(rw) - return - } + var ( + ctx = r.Context() + auditor = api.AGPL.Auditor.Load() + ) idStr := chi.URLParam(r, "id") id, err := strconv.ParseInt(idStr, 10, 32) @@ -196,6 +211,27 @@ func (api *API) deleteLicense(rw http.ResponseWriter, r *http.Request) { return } + license, err := api.Database.GetLicense(ctx, int32(id)) + if err != nil { + httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{ + Message: "Could not retrieve license; cannot audit", + }) + } + + aReq, commitAudit := audit.InitRequest[database.License](rw, &audit.RequestParams{ + Audit: *auditor, + Log: api.Logger, + Request: r, + Action: database.AuditActionDelete, + }) + defer commitAudit() + aReq.Old = license + + if !api.AGPL.Authorize(r, rbac.ActionDelete, rbac.ResourceLicense) { + httpapi.Forbidden(rw) + return + } + _, err = api.Database.DeleteLicense(ctx, int32(id)) if xerrors.Is(err, sql.ErrNoRows) { httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{ From 7ca3ec5c21ce92baea53f2bb124bc4d1f2db1179 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 8 Feb 2023 22:15:14 +0000 Subject: [PATCH 03/10] added filtering --- coderd/audit.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/coderd/audit.go b/coderd/audit.go index 03392641681c2..8fc144ae0d148 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -456,6 +456,8 @@ func resourceTypeFromString(resourceTypeString string) string { return resourceTypeString case codersdk.ResourceTypeGroup: return resourceTypeString + case codersdk.ResourceTypeLicense: + return resourceTypeString } return "" } From 222ab40106cf4d889eda717bb06252aaba363fcc Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 8 Feb 2023 22:18:59 +0000 Subject: [PATCH 04/10] remove logs --- coderd/audit/request.go | 4 ---- enterprise/coderd/licenses.go | 2 -- 2 files changed, 6 deletions(-) diff --git a/coderd/audit/request.go b/coderd/audit/request.go index f3198853e6c57..96110cfe9ea12 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -134,7 +134,6 @@ func ResourceType[T Auditable](tgt T) database.ResourceType { // that should be deferred, causing the audit log to be committed when the // handler returns. func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request[T], func()) { - fmt.Println("im in the init request") sw, ok := w.(*tracing.StatusWriter) if !ok { panic("dev error: http.ResponseWriter is not *tracing.StatusWriter") @@ -145,7 +144,6 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request } return req, func() { - fmt.Println("im in the init request callback") ctx := context.Background() logCtx := p.Request.Context() @@ -158,8 +156,6 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request // TODO: introduce the concept of an anonymous user so we always have a userID even // when dealing with a mystery user. https://github.com/coder/coder/issues/6054 if req.params.Action != database.AuditActionLogin && req.params.Action != database.AuditActionLogout { - fmt.Println("im silently bailing") - return } } diff --git a/enterprise/coderd/licenses.go b/enterprise/coderd/licenses.go index c4fcf11ae4ffd..f1716b3f2701b 100644 --- a/enterprise/coderd/licenses.go +++ b/enterprise/coderd/licenses.go @@ -8,7 +8,6 @@ import ( _ "embed" "encoding/base64" "encoding/json" - "fmt" "net/http" "strconv" "strings" @@ -61,7 +60,6 @@ var Keys = map[string]ed25519.PublicKey{"2022-08-12": ed25519.PublicKey(key20220 // @Success 201 {object} codersdk.License // @Router /licenses [post] func (api *API) postLicense(rw http.ResponseWriter, r *http.Request) { - fmt.Println("im in postLicense") var ( ctx = r.Context() auditor = api.AGPL.Auditor.Load() From a96bffc3d3ff63676651dba394cb27d88c2b46a4 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Thu, 9 Feb 2023 16:54:14 +0000 Subject: [PATCH 05/10] making the best of the current UUID situation --- coderd/audit/request.go | 9 ++++++--- enterprise/audit/table.go | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/coderd/audit/request.go b/coderd/audit/request.go index 96110cfe9ea12..6e75109d42b31 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -7,7 +7,6 @@ import ( "fmt" "net" "net/http" - "strconv" "github.com/google/uuid" "github.com/tabbed/pqtype" @@ -73,7 +72,10 @@ func ResourceTarget[T Auditable](tgt T) string { // this isn't used return "" case database.License: - return strconv.FormatInt(int64(typed.ID), 10) + // this isn't used + // TODO: return an ID here when the below ticket is completed: + // https://github.com/coder/coder/pull/6012 + return "" default: panic(fmt.Sprintf("unknown resource %T", tgt)) } @@ -98,7 +100,8 @@ func ResourceID[T Auditable](tgt T) uuid.UUID { case database.APIKey: return typed.UserID case database.License: - // this isn't right + // TODO: return a valid ID here when the below ticket is completed: + // https://github.com/coder/coder/pull/6012 return uuid.New() default: panic(fmt.Sprintf("unknown resource %T", tgt)) diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index b5fe6f651942c..599178c606b77 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -146,8 +146,10 @@ var AuditableResources = auditMap(map[any]map[string]Action{ "ip_address": ActionIgnore, "scope": ActionIgnore, }, + // TODO: track an ID here when the below ticket is completed: + // https://github.com/coder/coder/pull/6012 &database.License{}: { - "id": ActionTrack, + "id": ActionIgnore, "uploaded_at": ActionIgnore, "jwt": ActionIgnore, "exp": ActionTrack, From c3f730ec344fb8ff9843a2e0c673d4b229884a20 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Thu, 9 Feb 2023 17:11:27 +0000 Subject: [PATCH 06/10] fixed lint --- coderd/audit/request.go | 1 - enterprise/coderd/licenses.go | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/coderd/audit/request.go b/coderd/audit/request.go index 6e75109d42b31..a7b73a7e11389 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -147,7 +147,6 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request } return req, func() { - ctx := context.Background() logCtx := p.Request.Context() diff --git a/enterprise/coderd/licenses.go b/enterprise/coderd/licenses.go index f1716b3f2701b..3d72730690ff3 100644 --- a/enterprise/coderd/licenses.go +++ b/enterprise/coderd/licenses.go @@ -209,11 +209,10 @@ func (api *API) deleteLicense(rw http.ResponseWriter, r *http.Request) { return } - license, err := api.Database.GetLicense(ctx, int32(id)) + dl, err := api.Database.GetLicense(ctx, int32(id)) if err != nil { - httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{ - Message: "Could not retrieve license; cannot audit", - }) + // don't fail the HTTP request simply because we cannot audit + api.Logger.Error(context.Background(), "could not retrieve license; cannot audit", slog.Error(err)) } aReq, commitAudit := audit.InitRequest[database.License](rw, &audit.RequestParams{ @@ -223,7 +222,7 @@ func (api *API) deleteLicense(rw http.ResponseWriter, r *http.Request) { Action: database.AuditActionDelete, }) defer commitAudit() - aReq.Old = license + aReq.Old = dl if !api.AGPL.Authorize(r, rbac.ActionDelete, rbac.ResourceLicense) { httpapi.Forbidden(rw) From 5ef23bb1bb7cfcf562ef7ea8af7cefe967708242 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Thu, 9 Feb 2023 18:07:01 +0000 Subject: [PATCH 07/10] fix tests --- enterprise/coderd/licenses.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise/coderd/licenses.go b/enterprise/coderd/licenses.go index 3d72730690ff3..b417aab8076bb 100644 --- a/enterprise/coderd/licenses.go +++ b/enterprise/coderd/licenses.go @@ -212,7 +212,7 @@ func (api *API) deleteLicense(rw http.ResponseWriter, r *http.Request) { dl, err := api.Database.GetLicense(ctx, int32(id)) if err != nil { // don't fail the HTTP request simply because we cannot audit - api.Logger.Error(context.Background(), "could not retrieve license; cannot audit", slog.Error(err)) + api.Logger.Warn(context.Background(), "could not retrieve license; cannot audit", slog.Error(err)) } aReq, commitAudit := audit.InitRequest[database.License](rw, &audit.RequestParams{ From 94aa363dd20c810d98c3fa01f1248694d648f159 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Thu, 9 Feb 2023 18:22:27 +0000 Subject: [PATCH 08/10] regen docs --- docs/admin/audit-logs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin/audit-logs.md b/docs/admin/audit-logs.md index 25c6d719c31df..c8119927caec9 100644 --- a/docs/admin/audit-logs.md +++ b/docs/admin/audit-logs.md @@ -14,7 +14,7 @@ We track the following resources: | APIKey
write |
FieldTracked
created_atfalse
expires_atfalse
hashed_secretfalse
idfalse
ip_addressfalse
last_usedfalse
lifetime_secondsfalse
login_typefalse
scopefalse
updated_atfalse
user_idfalse
| | Group
create, write, delete |
FieldTracked
avatar_urltrue
idtrue
memberstrue
nametrue
organization_idfalse
quota_allowancetrue
| | GitSSHKey
create |
FieldTracked
created_atfalse
private_keytrue
public_keytrue
updated_atfalse
user_idtrue
| -| License
create, delete |
FieldTracked
exptrue
idtrue
jwtfalse
uploaded_atfalse
uuidfalse
| +| License
create, delete |
FieldTracked
exptrue
idfalse
jwtfalse
uploaded_atfalse
uuidfalse
| | Template
write, delete |
FieldTracked
active_version_idtrue
allow_user_cancel_workspace_jobstrue
created_atfalse
created_bytrue
default_ttltrue
deletedfalse
descriptiontrue
display_nametrue
group_acltrue
icontrue
idtrue
is_privatetrue
min_autostart_intervaltrue
nametrue
organization_idfalse
provisionertrue
updated_atfalse
user_acltrue
| | TemplateVersion
create, write |
FieldTracked
created_atfalse
created_bytrue
idtrue
job_idfalse
nametrue
organization_idfalse
readmetrue
template_idtrue
updated_atfalse
| | User
create, write, delete |
FieldTracked
avatar_urlfalse
created_atfalse
deletedtrue
emailtrue
hashed_passwordtrue
idtrue
last_seen_atfalse
login_typefalse
rbac_rolestrue
statustrue
updated_atfalse
usernametrue
| From 5e29a73b092ef2f80892af9adfc500eb9d718566 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 14 Feb 2023 17:11:02 +0000 Subject: [PATCH 09/10] PR feedback --- coderd/audit/request.go | 9 ++------- ...own.sql => 000098_add_resource_type_license.down.sql} | 0 ...se.up.sql => 000098_add_resource_type_license.up.sql} | 0 docs/admin/audit-logs.md | 2 +- enterprise/audit/table.go | 4 ++-- 5 files changed, 5 insertions(+), 10 deletions(-) rename coderd/database/migrations/{000097_add_resource_type_license.down.sql => 000098_add_resource_type_license.down.sql} (100%) rename coderd/database/migrations/{000097_add_resource_type_license.up.sql => 000098_add_resource_type_license.up.sql} (100%) diff --git a/coderd/audit/request.go b/coderd/audit/request.go index a7b73a7e11389..178874baee461 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -72,10 +72,7 @@ func ResourceTarget[T Auditable](tgt T) string { // this isn't used return "" case database.License: - // this isn't used - // TODO: return an ID here when the below ticket is completed: - // https://github.com/coder/coder/pull/6012 - return "" + return typed.UUID.String() default: panic(fmt.Sprintf("unknown resource %T", tgt)) } @@ -100,9 +97,7 @@ func ResourceID[T Auditable](tgt T) uuid.UUID { case database.APIKey: return typed.UserID case database.License: - // TODO: return a valid ID here when the below ticket is completed: - // https://github.com/coder/coder/pull/6012 - return uuid.New() + return typed.UUID default: panic(fmt.Sprintf("unknown resource %T", tgt)) } diff --git a/coderd/database/migrations/000097_add_resource_type_license.down.sql b/coderd/database/migrations/000098_add_resource_type_license.down.sql similarity index 100% rename from coderd/database/migrations/000097_add_resource_type_license.down.sql rename to coderd/database/migrations/000098_add_resource_type_license.down.sql diff --git a/coderd/database/migrations/000097_add_resource_type_license.up.sql b/coderd/database/migrations/000098_add_resource_type_license.up.sql similarity index 100% rename from coderd/database/migrations/000097_add_resource_type_license.up.sql rename to coderd/database/migrations/000098_add_resource_type_license.up.sql diff --git a/docs/admin/audit-logs.md b/docs/admin/audit-logs.md index c8119927caec9..762b2f3762ca7 100644 --- a/docs/admin/audit-logs.md +++ b/docs/admin/audit-logs.md @@ -14,7 +14,7 @@ We track the following resources: | APIKey
write |
FieldTracked
created_atfalse
expires_atfalse
hashed_secretfalse
idfalse
ip_addressfalse
last_usedfalse
lifetime_secondsfalse
login_typefalse
scopefalse
updated_atfalse
user_idfalse
| | Group
create, write, delete |
FieldTracked
avatar_urltrue
idtrue
memberstrue
nametrue
organization_idfalse
quota_allowancetrue
| | GitSSHKey
create |
FieldTracked
created_atfalse
private_keytrue
public_keytrue
updated_atfalse
user_idtrue
| -| License
create, delete |
FieldTracked
exptrue
idfalse
jwtfalse
uploaded_atfalse
uuidfalse
| +| License
create, delete |
FieldTracked
exptrue
idfalse
jwtfalse
uploaded_attrue
uuidtrue
| | Template
write, delete |
FieldTracked
active_version_idtrue
allow_user_cancel_workspace_jobstrue
created_atfalse
created_bytrue
default_ttltrue
deletedfalse
descriptiontrue
display_nametrue
group_acltrue
icontrue
idtrue
is_privatetrue
min_autostart_intervaltrue
nametrue
organization_idfalse
provisionertrue
updated_atfalse
user_acltrue
| | TemplateVersion
create, write |
FieldTracked
created_atfalse
created_bytrue
idtrue
job_idfalse
nametrue
organization_idfalse
readmetrue
template_idtrue
updated_atfalse
| | User
create, write, delete |
FieldTracked
avatar_urlfalse
created_atfalse
deletedtrue
emailtrue
hashed_passwordtrue
idtrue
last_seen_atfalse
login_typefalse
rbac_rolestrue
statustrue
updated_atfalse
usernametrue
| diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index 599178c606b77..239aecfd3017e 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -150,10 +150,10 @@ var AuditableResources = auditMap(map[any]map[string]Action{ // https://github.com/coder/coder/pull/6012 &database.License{}: { "id": ActionIgnore, - "uploaded_at": ActionIgnore, + "uploaded_at": ActionTrack, "jwt": ActionIgnore, "exp": ActionTrack, - "uuid": ActionIgnore, + "uuid": ActionTrack, }, }) From e7264342286358e07add174cc712d2277bdfbbc2 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 14 Feb 2023 20:41:40 +0000 Subject: [PATCH 10/10] PR feedback --- coderd/audit/request.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/coderd/audit/request.go b/coderd/audit/request.go index 178874baee461..b9ec814568dc5 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "net/http" + "strconv" "github.com/google/uuid" "github.com/tabbed/pqtype" @@ -72,7 +73,7 @@ func ResourceTarget[T Auditable](tgt T) string { // this isn't used return "" case database.License: - return typed.UUID.String() + return strconv.Itoa(int(typed.ID)) default: panic(fmt.Sprintf("unknown resource %T", tgt)) }