feat: add AI Gateway coderd key CRUD endpoints (#25565)

Adds create, list and delete endpoints for AI Gateway keys.
Those keys are used to authenticate into Coderd.
All endpoints require Owner permission.
This commit is contained in:
Paweł Banaszewski
2026-06-03 13:50:33 +02:00
committed by GitHub
parent 6ef687cdfb
commit 96e3a64b12
12 changed files with 1281 additions and 19 deletions
+19 -19
View File
@@ -14740,13 +14740,13 @@ func TestAIGatewayKeysTableConstraints(t *testing.T) {
db, _ := dbtestutil.NewDB(t)
ctx := testutil.Context(t, testutil.WaitMedium)
preExsiting := database.InsertAIGatewayKeyParams{
preExisting := database.InsertAIGatewayKeyParams{
ID: uuid.New(),
Name: "name",
SecretPrefix: "cgw_test__1",
SecretPrefix: "key_test__1",
HashedSecret: []byte("first-secret"),
}
_, err := db.InsertAIGatewayKey(ctx, preExsiting)
_, err := db.InsertAIGatewayKey(ctx, preExisting)
require.NoError(t, err)
tests := []struct {
@@ -14757,67 +14757,67 @@ func TestAIGatewayKeysTableConstraints(t *testing.T) {
}{
{
name: "duplicate name",
params: aiGatewayKeyParams(preExsiting.Name, "cgw_test002"),
params: aiGatewayKeyParams(preExisting.Name, "key_test002"),
expectUniqueErr: database.UniqueAiGatewayKeysNameIndex,
},
{
name: "duplicate secret prefix",
params: aiGatewayKeyParams("different-key", preExsiting.SecretPrefix),
params: aiGatewayKeyParams("different-key", preExisting.SecretPrefix),
expectUniqueErr: database.UniqueAiGatewayKeysSecretPrefixIndex,
},
{
name: "duplicate hashed secret",
params: database.InsertAIGatewayKeyParams{ID: uuid.New(), Name: "other-name", SecretPrefix: "cgw_1234567", HashedSecret: preExsiting.HashedSecret},
params: database.InsertAIGatewayKeyParams{ID: uuid.New(), Name: "other-name", SecretPrefix: "key_1234567", HashedSecret: preExisting.HashedSecret},
expectUniqueErr: database.UniqueAiGatewayKeysHashedSecretIndex,
},
{
name: "empty name",
params: aiGatewayKeyParams("", "cgw_1234567"),
params: aiGatewayKeyParams("", "key_empty__"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with trailing dash",
params: aiGatewayKeyParams("other-name-", "cgw_1234567"),
params: aiGatewayKeyParams("other-name-", "key_trail__"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with consecutive dashes",
params: aiGatewayKeyParams("other--name", "cgw_1234567"),
params: aiGatewayKeyParams("other--name", "key_consec_"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with underscore",
params: aiGatewayKeyParams("other_name", "cgw_1234567"),
params: aiGatewayKeyParams("other_name", "key_undersc"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with space",
params: aiGatewayKeyParams("other name", "cgw_1234567"),
params: aiGatewayKeyParams("other name", "key_spacen_"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with leading dash",
params: aiGatewayKeyParams("-other-name", "cgw_1234567"),
params: aiGatewayKeyParams("-other-name", "key_leadng_"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name longer than 64 characters",
params: aiGatewayKeyParams(strings.Repeat("a", 65), "cgw_1234567"),
params: aiGatewayKeyParams(strings.Repeat("a", 65), "key_longna_"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "empty secret prefix",
params: aiGatewayKeyParams("other-name", ""),
params: aiGatewayKeyParams("check-empty-pfx", ""),
expectCheckErr: database.CheckAiGatewayKeysSecretPrefixCheck,
},
{
name: "invalid secret prefix length",
params: aiGatewayKeyParams("other-name", "cgw_short"),
params: aiGatewayKeyParams("check-short-pfx", "key_short"),
expectCheckErr: database.CheckAiGatewayKeysSecretPrefixCheck,
},
{
name: "empty hashed secret",
params: database.InsertAIGatewayKeyParams{ID: uuid.New(), Name: "other-name", SecretPrefix: "cgw_1234567"},
params: database.InsertAIGatewayKeyParams{ID: uuid.New(), Name: "check-empty-hash", SecretPrefix: "key_ehash__", HashedSecret: []byte{}},
expectCheckErr: database.CheckAiGatewayKeysHashedSecretCheck,
},
}
@@ -14841,8 +14841,8 @@ func TestAIGatewayKeysQueries(t *testing.T) {
db, _ := dbtestutil.NewDB(t)
ctx := testutil.Context(t, testutil.WaitLong)
first := aiGatewayKeyParams("first-key", "cgw_first__")
second := aiGatewayKeyParams("second-key", "cgw_second_")
first := aiGatewayKeyParams("first-key", "key_first__")
second := aiGatewayKeyParams("second-key", "key_second_")
second.HashedSecret = []byte("second-secret")
firstRow, err := db.InsertAIGatewayKey(ctx, first)
@@ -14889,7 +14889,7 @@ func aiGatewayKeyParams(name string, secretPrefix string) database.InsertAIGatew
ID: uuid.New(),
Name: name,
SecretPrefix: secretPrefix,
HashedSecret: []byte("secret"),
HashedSecret: []byte("secret-" + name + "-" + secretPrefix),
}
}