Skip to content

Commit 7ec88bf

Browse files
authored
feat: audit git ssh key regeneration (#4544)
1 parent dd8ebf1 commit 7ec88bf

File tree

8 files changed

+63
-22
lines changed

8 files changed

+63
-22
lines changed

coderd/audit.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,18 @@ func convertAuditLog(dblog database.GetAuditLogsOffsetRow) codersdk.AuditLog {
221221
}
222222

223223
func auditLogDescription(alog database.GetAuditLogsOffsetRow) string {
224-
return fmt.Sprintf("{user} %s %s {target}",
224+
str := fmt.Sprintf("{user} %s %s",
225225
codersdk.AuditAction(alog.Action).FriendlyString(),
226226
codersdk.ResourceType(alog.ResourceType).FriendlyString(),
227227
)
228+
229+
// We don't display the name for git ssh keys. It's fairly long and doesn't
230+
// make too much sense to display.
231+
if alog.ResourceType != database.ResourceTypeGitSshKey {
232+
str += " {target}"
233+
}
234+
235+
return str
228236
}
229237

230238
// auditSearchQuery takes a query string and returns the auditLog filter.

coderd/database/databasefake/databasefake.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -2676,7 +2676,7 @@ func (q *fakeQuerier) GetGitSSHKey(_ context.Context, userID uuid.UUID) (databas
26762676
return database.GitSSHKey{}, sql.ErrNoRows
26772677
}
26782678

2679-
func (q *fakeQuerier) UpdateGitSSHKey(_ context.Context, arg database.UpdateGitSSHKeyParams) error {
2679+
func (q *fakeQuerier) UpdateGitSSHKey(_ context.Context, arg database.UpdateGitSSHKeyParams) (database.GitSSHKey, error) {
26802680
q.mutex.Lock()
26812681
defer q.mutex.Unlock()
26822682

@@ -2688,9 +2688,9 @@ func (q *fakeQuerier) UpdateGitSSHKey(_ context.Context, arg database.UpdateGitS
26882688
key.PrivateKey = arg.PrivateKey
26892689
key.PublicKey = arg.PublicKey
26902690
q.gitSSHKey[index] = key
2691-
return nil
2691+
return key, nil
26922692
}
2693-
return sql.ErrNoRows
2693+
return database.GitSSHKey{}, sql.ErrNoRows
26942694
}
26952695

26962696
func (q *fakeQuerier) InsertGroupMember(_ context.Context, arg database.InsertGroupMemberParams) error {

coderd/database/querier.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

+14-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/gitsshkeys.sql

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@ FROM
1818
WHERE
1919
user_id = $1;
2020

21-
-- name: UpdateGitSSHKey :exec
21+
-- name: UpdateGitSSHKey :one
2222
UPDATE
2323
gitsshkeys
2424
SET
2525
updated_at = $2,
2626
private_key = $3,
2727
public_key = $4
2828
WHERE
29-
user_id = $1;
29+
user_id = $1
30+
RETURNING
31+
*;
3032

3133
-- name: DeleteGitSSHKey :exec
3234
DELETE FROM

coderd/gitsshkey.go

+23-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package coderd
33
import (
44
"net/http"
55

6+
"github.com/coder/coder/coderd/audit"
67
"github.com/coder/coder/coderd/database"
78
"github.com/coder/coder/coderd/gitsshkey"
89
"github.com/coder/coder/coderd/httpapi"
@@ -12,14 +13,32 @@ import (
1213
)
1314

1415
func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
15-
ctx := r.Context()
16-
user := httpmw.UserParam(r)
16+
var (
17+
ctx = r.Context()
18+
user = httpmw.UserParam(r)
19+
auditor = api.Auditor.Load()
20+
aReq, commitAudit = audit.InitRequest[database.GitSSHKey](rw, &audit.RequestParams{
21+
Audit: *auditor,
22+
Log: api.Logger,
23+
Request: r,
24+
Action: database.AuditActionWrite,
25+
})
26+
)
27+
defer commitAudit()
1728

1829
if !api.Authorize(r, rbac.ActionUpdate, rbac.ResourceUserData.WithOwner(user.ID.String())) {
1930
httpapi.ResourceNotFound(rw)
2031
return
2132
}
2233

34+
oldKey, err := api.Database.GetGitSSHKey(ctx, user.ID)
35+
if err != nil {
36+
httpapi.InternalServerError(rw, err)
37+
return
38+
}
39+
40+
aReq.Old = oldKey
41+
2342
privateKey, publicKey, err := gitsshkey.Generate(api.SSHKeygenAlgorithm)
2443
if err != nil {
2544
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
@@ -29,7 +48,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
2948
return
3049
}
3150

32-
err = api.Database.UpdateGitSSHKey(ctx, database.UpdateGitSSHKeyParams{
51+
newKey, err := api.Database.UpdateGitSSHKey(ctx, database.UpdateGitSSHKeyParams{
3352
UserID: user.ID,
3453
UpdatedAt: database.Now(),
3554
PrivateKey: privateKey,
@@ -43,14 +62,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
4362
return
4463
}
4564

46-
newKey, err := api.Database.GetGitSSHKey(ctx, user.ID)
47-
if err != nil {
48-
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
49-
Message: "Internal error fetching user's git SSH key.",
50-
Detail: err.Error(),
51-
})
52-
return
53-
}
65+
aReq.New = newKey
5466

5567
httpapi.Write(ctx, rw, http.StatusOK, codersdk.GitSSHKey{
5668
UserID: newKey.UserID,

coderd/gitsshkey_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import (
55
"testing"
66

77
"github.com/google/uuid"
8+
"github.com/stretchr/testify/assert"
89
"github.com/stretchr/testify/require"
910

11+
"github.com/coder/coder/coderd/audit"
1012
"github.com/coder/coder/coderd/coderdtest"
13+
"github.com/coder/coder/coderd/database"
1114
"github.com/coder/coder/coderd/gitsshkey"
1215
"github.com/coder/coder/codersdk"
1316
"github.com/coder/coder/provisioner/echo"
@@ -73,8 +76,10 @@ func TestGitSSHKey(t *testing.T) {
7376
})
7477
t.Run("Regenerate", func(t *testing.T) {
7578
t.Parallel()
79+
auditor := audit.NewMock()
7680
client := coderdtest.New(t, &coderdtest.Options{
7781
SSHKeygenAlgorithm: gitsshkey.AlgorithmEd25519,
82+
Auditor: auditor,
7883
})
7984
res := coderdtest.CreateFirstUser(t, client)
8085

@@ -89,6 +94,9 @@ func TestGitSSHKey(t *testing.T) {
8994
require.GreaterOrEqual(t, key2.UpdatedAt, key1.UpdatedAt)
9095
require.NotEmpty(t, key2.PublicKey)
9196
require.NotEqual(t, key2.PublicKey, key1.PublicKey)
97+
98+
require.Len(t, auditor.AuditLogs, 1)
99+
assert.Equal(t, database.AuditActionWrite, auditor.AuditLogs[0].Action)
92100
})
93101
}
94102

docs/admin/audit-logs.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ their deployment.
77

88
We track **create, update and delete** events for the following resources:
99

10+
- GitSSHKey
1011
- Template
1112
- TemplateVersion
1213
- Workspace

0 commit comments

Comments
 (0)