feat: add ai_gateway_keys table and related RBAC (#25563)

Adds table to store keys that AI Gateway standalone replicas will use
to authenticate into Coderd.
Also adds RBAC and audit boilerplate.
This commit is contained in:
Paweł Banaszewski
2026-06-02 09:28:43 +02:00
committed by GitHub
parent 49c2142d2d
commit f22d4e2cbb
26 changed files with 264 additions and 38 deletions
+10
View File
@@ -15,6 +15,15 @@ var (
Type: "*",
}
// ResourceAIGatewayKey
// Valid Actions
// - "ActionCreate" :: create an AI Gateway key
// - "ActionDelete" :: delete an AI Gateway key
// - "ActionRead" :: read AI Gateway keys
ResourceAIGatewayKey = Object{
Type: "ai_gateway_key",
}
// ResourceAiModelPrice
// Valid Actions
// - "ActionRead" :: read AI model prices
@@ -479,6 +488,7 @@ var (
func AllResources() []Objecter {
return []Objecter{
ResourceWildcard,
ResourceAIGatewayKey,
ResourceAiModelPrice,
ResourceAIProvider,
ResourceAiSeat,
+8
View File
@@ -429,6 +429,14 @@ var RBACPermissions = map[string]PermissionDefinition{
ActionDelete: "delete boundary logs",
},
},
"ai_gateway_key": {
Name: "AIGatewayKey",
Actions: map[Action]ActionDefinition{
ActionCreate: "create an AI Gateway key",
ActionRead: "read AI Gateway keys",
ActionDelete: "delete an AI Gateway key",
},
},
"boundary_usage": {
Actions: map[Action]ActionDefinition{
ActionRead: "read boundary usage statistics",
+18
View File
@@ -1204,6 +1204,24 @@ func TestRolePermissions(t *testing.T) {
},
},
},
{
// Only owners can manage AI Gateway keys. They hold
// a hashed bearer secret used to authenticate Gateway
// replicas to coderd. Keys are deployment-wide.
Name: "AIGatewayKey",
Actions: []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionDelete},
Resource: rbac.ResourceAIGatewayKey,
AuthorizeMap: map[bool][]hasAuthSubjects{
true: {owner},
false: {
memberMe, agentsAccessUser,
orgAdmin, otherOrgAdmin,
orgAuditor, otherOrgAuditor,
templateAdmin, orgTemplateAdmin, otherOrgTemplateAdmin,
userAdmin, orgUserAdmin, otherOrgUserAdmin,
},
},
},
{
Name: "BoundaryUsage",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
+9
View File
@@ -7,6 +7,9 @@ package rbac
// declared in code, not here, to avoid duplication.
const (
ScopeAiGatewayKeyCreate ScopeName = "ai_gateway_key:create"
ScopeAiGatewayKeyDelete ScopeName = "ai_gateway_key:delete"
ScopeAiGatewayKeyRead ScopeName = "ai_gateway_key:read"
ScopeAiModelPriceRead ScopeName = "ai_model_price:read"
ScopeAiModelPriceUpdate ScopeName = "ai_model_price:update"
ScopeAiProviderCreate ScopeName = "ai_provider:create"
@@ -187,6 +190,9 @@ func (e ScopeName) Valid() bool {
case ScopeName("coder:all"),
ScopeName("coder:application_connect"),
ScopeName("no_user_data"),
ScopeAiGatewayKeyCreate,
ScopeAiGatewayKeyDelete,
ScopeAiGatewayKeyRead,
ScopeAiModelPriceRead,
ScopeAiModelPriceUpdate,
ScopeAiProviderCreate,
@@ -368,6 +374,9 @@ func AllScopeNameValues() []ScopeName {
ScopeName("coder:all"),
ScopeName("coder:application_connect"),
ScopeName("no_user_data"),
ScopeAiGatewayKeyCreate,
ScopeAiGatewayKeyDelete,
ScopeAiGatewayKeyRead,
ScopeAiModelPriceRead,
ScopeAiModelPriceUpdate,
ScopeAiProviderCreate,