mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
fix(coderd): add audit log on creating a new session key (#19672)
Fixes https://github.com/coder/coder/issues/19671 (re-?)Adds an audit log entry when an API key is created via `coder login`. NOTE: This does _not_ backfill audit logs. <img width="1354" height="207" alt="Screenshot 2025-09-02 at 14 16 24" src="https://github.com/user-attachments/assets/921e85c1-eced-4a19-9d37-8f84f4af1e73" />
This commit is contained in:
+15
-3
@@ -131,8 +131,19 @@ func (api *API) postToken(rw http.ResponseWriter, r *http.Request) {
|
||||
// @Success 201 {object} codersdk.GenerateAPIKeyResponse
|
||||
// @Router /users/{user}/keys [post]
|
||||
func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
user := httpmw.UserParam(r)
|
||||
var (
|
||||
ctx = r.Context()
|
||||
user = httpmw.UserParam(r)
|
||||
auditor = api.Auditor.Load()
|
||||
aReq, commitAudit = audit.InitRequest[database.APIKey](rw, &audit.RequestParams{
|
||||
Audit: *auditor,
|
||||
Log: api.Logger,
|
||||
Request: r,
|
||||
Action: database.AuditActionCreate,
|
||||
})
|
||||
)
|
||||
aReq.Old = database.APIKey{}
|
||||
defer commitAudit()
|
||||
|
||||
// TODO(Cian): System users technically just have the 'member' role
|
||||
// and we don't want to disallow all members from creating API keys.
|
||||
@@ -142,7 +153,7 @@ func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
cookie, _, err := api.createAPIKey(ctx, apikey.CreateParams{
|
||||
cookie, key, err := api.createAPIKey(ctx, apikey.CreateParams{
|
||||
UserID: user.ID,
|
||||
DefaultLifetime: api.DeploymentValues.Sessions.DefaultTokenDuration.Value(),
|
||||
LoginType: database.LoginTypePassword,
|
||||
@@ -156,6 +167,7 @@ func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
aReq.New = *key
|
||||
// We intentionally do not set the cookie on the response here.
|
||||
// Setting the cookie will couple the browser session to the API
|
||||
// key we return here, meaning logging out of the website would
|
||||
|
||||
+21
-2
@@ -2,6 +2,7 @@ package coderd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -303,14 +304,32 @@ func TestSessionExpiry(t *testing.T) {
|
||||
|
||||
func TestAPIKey_OK(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Given: a deployment with auditing enabled
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
auditor := audit.NewMock()
|
||||
client := coderdtest.New(t, &coderdtest.Options{Auditor: auditor})
|
||||
owner := coderdtest.CreateFirstUser(t, client)
|
||||
auditor.ResetLogs()
|
||||
|
||||
// When: an API key is created
|
||||
res, err := client.CreateAPIKey(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
require.Greater(t, len(res.Key), 2)
|
||||
|
||||
// Then: an audit log is generated
|
||||
als := auditor.AuditLogs()
|
||||
require.Len(t, als, 1)
|
||||
al := als[0]
|
||||
assert.Equal(t, owner.UserID, al.UserID)
|
||||
assert.Equal(t, database.AuditActionCreate, al.Action)
|
||||
assert.Equal(t, database.ResourceTypeApiKey, al.ResourceType)
|
||||
|
||||
// Then: the diff MUST NOT contain the generated key.
|
||||
raw, err := json.Marshal(al)
|
||||
require.NoError(t, err)
|
||||
require.NotContains(t, res.Key, string(raw))
|
||||
}
|
||||
|
||||
func TestAPIKey_Deleted(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user