feat(coderd/database): add AI Gateway key auth lookup and last-used queries (#26505)

Adds DB methods`GetAIGatewayKeyIDByHashedSecret` and `UpdateAIGatewayKeyLastUsedAt`.
`GetAIGatewayKeyIDByHashedSecret` - returns AI Gateway key ID by hashed secret value.
`UpdateAIGatewayKeyLastUsedAt` - updates last used timestamp for given AI Gateway key. 
Used by standalone AI Gateway for authentication and keeping track of currently used keys.
This commit is contained in:
Paweł Banaszewski
2026-06-26 18:16:01 +02:00
committed by GitHub
parent e71d4ca69b
commit 0f1e792f3f
24 changed files with 271 additions and 7 deletions
+1
View File
@@ -20,6 +20,7 @@ var (
// - "ActionCreate" :: create an AI Gateway key
// - "ActionDelete" :: delete an AI Gateway key
// - "ActionRead" :: read AI Gateway keys
// - "ActionUpdate" :: update an AI Gateway key
ResourceAIGatewayKey = Object{
Type: "ai_gateway_key",
}
+1
View File
@@ -434,6 +434,7 @@ var RBACPermissions = map[string]PermissionDefinition{
Actions: map[Action]ActionDefinition{
ActionCreate: "create an AI Gateway key",
ActionRead: "read AI Gateway keys",
ActionUpdate: "update an AI Gateway key",
ActionDelete: "delete an AI Gateway key",
},
},
+5 -1
View File
@@ -409,12 +409,16 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
// Workspace is specifically handled based on the opts.NoOwnerWorkspaceExec.
// Owners can inspect and delete personal skills for operability and
// abuse handling, but cannot create or edit user-authored instructions.
allPermsExcept(ResourceWorkspaceDormant, ResourcePrebuiltWorkspace, ResourceWorkspace, ResourceUserSecret, ResourceUserSkill, ResourceUsageEvent, ResourceBoundaryUsage, ResourceBoundaryLog, ResourceAiSeat),
allPermsExcept(ResourceWorkspaceDormant, ResourcePrebuiltWorkspace, ResourceWorkspace, ResourceUserSecret, ResourceUserSkill, ResourceUsageEvent, ResourceBoundaryUsage, ResourceBoundaryLog, ResourceAiSeat, ResourceAIGatewayKey),
// This adds back in the Workspace permissions.
Permissions(map[string][]policy.Action{
ResourceWorkspace.Type: ownerWorkspaceActions,
ResourceWorkspaceDormant.Type: {policy.ActionRead, policy.ActionDelete, policy.ActionCreate, policy.ActionUpdate, policy.ActionWorkspaceStop, policy.ActionCreateAgent, policy.ActionDeleteAgent, policy.ActionUpdateAgent},
ResourceUserSkill.Type: {policy.ActionRead, policy.ActionDelete},
// Owners manage AI Gateway keys but cannot update them. The
// update action records last-used liveness and is reserved
// for the system actor authenticating Gateway replicas.
ResourceAIGatewayKey.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionDelete},
// PrebuiltWorkspaces are a subset of Workspaces.
// Explicitly setting PrebuiltWorkspace permissions for clarity.
// Note: even without PrebuiltWorkspace permissions, access is still granted via Workspace permissions.
+19
View File
@@ -1311,6 +1311,25 @@ func TestRolePermissions(t *testing.T) {
},
},
},
{
// Updating an AI Gateway key records last-used liveness when a
// Gateway replica authenticates. It is reserved for the system
// actor, so no user-facing role, including owner, is authorized.
Name: "AIGatewayKeyUpdate",
Actions: []policy.Action{policy.ActionUpdate},
Resource: rbac.ResourceAIGatewayKey,
AuthorizeMap: map[bool][]hasAuthSubjects{
true: {},
false: {
owner,
orgWorkspaceAccessUser, memberMe, agentsAccessUser,
orgAdmin, otherOrgAdmin,
orgAuditor, otherOrgAuditor,
templateAdmin, orgTemplateAdmin, otherOrgTemplateAdmin,
userAdmin, orgUserAdmin, otherOrgUserAdmin,
},
},
},
{
Name: "BoundaryUsage",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
+3
View File
@@ -10,6 +10,7 @@ const (
ScopeAiGatewayKeyCreate ScopeName = "ai_gateway_key:create"
ScopeAiGatewayKeyDelete ScopeName = "ai_gateway_key:delete"
ScopeAiGatewayKeyRead ScopeName = "ai_gateway_key:read"
ScopeAiGatewayKeyUpdate ScopeName = "ai_gateway_key:update"
ScopeAiModelPriceRead ScopeName = "ai_model_price:read"
ScopeAiModelPriceUpdate ScopeName = "ai_model_price:update"
ScopeAiProviderCreate ScopeName = "ai_provider:create"
@@ -193,6 +194,7 @@ func (e ScopeName) Valid() bool {
ScopeAiGatewayKeyCreate,
ScopeAiGatewayKeyDelete,
ScopeAiGatewayKeyRead,
ScopeAiGatewayKeyUpdate,
ScopeAiModelPriceRead,
ScopeAiModelPriceUpdate,
ScopeAiProviderCreate,
@@ -377,6 +379,7 @@ func AllScopeNameValues() []ScopeName {
ScopeAiGatewayKeyCreate,
ScopeAiGatewayKeyDelete,
ScopeAiGatewayKeyRead,
ScopeAiGatewayKeyUpdate,
ScopeAiModelPriceRead,
ScopeAiModelPriceUpdate,
ScopeAiProviderCreate,