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
+43
View File
@@ -0,0 +1,43 @@
package keys
import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/apikey"
"github.com/coder/coder/v2/coderd/database"
)
const (
privateSuffixLength = 32
// KeyPrefixLength is the total length of the visible key prefix.
KeyPrefixLength = 11
// KeyLength is the total length of the plaintext key returned to
// the user on Create.
KeyLength = KeyPrefixLength + privateSuffixLength
)
// New generates an AI Gateway key used for authenticating standalone replicas.
// Returns InsertParams ready for the database query.
func New(name string) (database.InsertAIGatewayKeyParams, string, error) {
secret, hashed, err := apikey.GenerateSecret(KeyLength)
if err != nil {
return database.InsertAIGatewayKeyParams{}, "", xerrors.Errorf("generate secret: %w", err)
}
if len(secret) != KeyLength {
return database.InsertAIGatewayKeyParams{}, "", xerrors.Errorf("generated secret has unexpected length: got %d, want %d", len(secret), KeyLength)
}
if KeyLength < KeyPrefixLength {
return database.InsertAIGatewayKeyParams{}, "", xerrors.Errorf("KeyLength (%d) must be >= KeyPrefixLength (%d)", KeyLength, KeyPrefixLength)
}
visiblePrefix := secret[:KeyPrefixLength]
return database.InsertAIGatewayKeyParams{
ID: uuid.New(),
Name: name,
SecretPrefix: visiblePrefix,
HashedSecret: hashed,
}, secret, nil
}
+22
View File
@@ -0,0 +1,22 @@
package keys_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/coderd/aibridge/keys"
"github.com/coder/coder/v2/coderd/apikey"
)
func TestNew(t *testing.T) {
t.Parallel()
params, key, err := keys.New("test-key")
require.NoError(t, err)
require.Len(t, key, keys.KeyLength)
require.Len(t, params.SecretPrefix, keys.KeyPrefixLength)
require.Equal(t, key[:keys.KeyPrefixLength], params.SecretPrefix)
require.True(t, apikey.ValidateHash(params.HashedSecret, key))
require.False(t, apikey.ValidateHash(params.HashedSecret, key[keys.KeyPrefixLength:]))
}