- Notifications
You must be signed in to change notification settings - Fork1k
feat: implement API key scopes database migration#19861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
…w listReplace the single `scope` column with `scopes` array and add `allow_list`column to API keys table. This enables fine-grained authorization controlusing low-level resource:action permissions while maintaining backwardcompatibility.- Add database migration extending api_key_scope enum with all RBAC permissions- Replace APIKey.Scope with APIKey.Scopes array and AllowList fields- Implement APIKeyScopes.Expand() method for multi-scope authorization- Add AllowList type with database serialization support- Update RBAC scope expansion to support resource:action format- Maintain response compatibility by deriving single scope from arrays- Add comprehensive test coverage for scope expansion logic
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
-- Recreate single-scope column and collapse arrays | ||
ALTER TABLE api_keys ADD COLUMN scope api_key_scope DEFAULT 'all'::api_key_scope NOT NULL; | ||
-- Collapse logic: prefer 'all', else 'application_connect', else 'all' | ||
UPDATE api_keys SET scope = | ||
CASE | ||
WHEN 'all'::api_key_scope = ANY(scopes) THEN 'all'::api_key_scope | ||
WHEN 'application_connect'::api_key_scope = ANY(scopes) THEN 'application_connect'::api_key_scope | ||
ELSE 'all'::api_key_scope | ||
END; | ||
-- Drop new columns | ||
ALTER TABLE api_keys DROP COLUMN allow_list; | ||
ALTER TABLE api_keys DROP COLUMN scopes; | ||
-- Note: We intentionally keep the expanded enum values to avoid dependency churn. | ||
-- If strict narrowing is required, create a new type with only ('all','application_connect'), | ||
-- cast column, drop the new type, and rename. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
-- Extend api_key_scope enum with low-level <resource>:<action> values derived from RBACPermissions | ||
-- Generated via: go run ./scripts/generate_api_key_scope_enum | ||
-- Begin enum extensions | ||
Emyrk marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'aibridge_interception:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'aibridge_interception:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'aibridge_interception:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'api_key:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'api_key:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'api_key:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'api_key:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_org_role:assign'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_org_role:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_org_role:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_org_role:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_org_role:unassign'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_org_role:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_role:assign'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_role:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'assign_role:unassign'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'audit_log:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'audit_log:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'connection_log:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'connection_log:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'crypto_key:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'crypto_key:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'crypto_key:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'crypto_key:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'debug_info:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'deployment_config:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'deployment_config:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'deployment_stats:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'file:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'file:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'group:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'group:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'group:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'group:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'group_member:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'idpsync_settings:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'idpsync_settings:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'inbox_notification:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'inbox_notification:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'inbox_notification:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'license:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'license:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'license:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'notification_message:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'notification_message:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'notification_message:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'notification_message:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'notification_preference:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'notification_preference:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'notification_template:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'notification_template:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app_code_token:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app_code_token:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app_code_token:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app_secret:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app_secret:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app_secret:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'oauth2_app_secret:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'organization:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'organization:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'organization:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'organization:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'organization_member:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'organization_member:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'organization_member:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'organization_member:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'prebuilt_workspace:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'prebuilt_workspace:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'provisioner_daemon:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'provisioner_daemon:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'provisioner_daemon:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'provisioner_daemon:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'provisioner_jobs:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'provisioner_jobs:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'provisioner_jobs:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'replicas:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'system:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'system:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'system:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'system:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'tailnet_coordinator:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'tailnet_coordinator:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'tailnet_coordinator:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'tailnet_coordinator:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'template:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'template:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'template:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'template:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'template:use'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'template:view_insights'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'usage_event:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'usage_event:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'usage_event:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user:read_personal'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user:update_personal'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user_secret:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user_secret:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user_secret:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'user_secret:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'webpush_subscription:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'webpush_subscription:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'webpush_subscription:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:application_connect'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:create_agent'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:delete_agent'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:ssh'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:start'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:stop'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_agent_devcontainers:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_agent_resource_monitor:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_agent_resource_monitor:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_agent_resource_monitor:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:application_connect'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:create_agent'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:delete_agent'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:ssh'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:start'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:stop'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_dormant:update'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_proxy:create'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_proxy:delete'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_proxy:read'; | ||
ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS 'workspace_proxy:update'; | ||
-- End enum extensions | ||
-- Add new columns without defaults; backfill; then enforce NOT NULL | ||
ALTER TABLE api_keys ADD COLUMN scopes api_key_scope[]; | ||
ALTER TABLE api_keys ADD COLUMN allow_list text[]; | ||
-- Backfill existing rows for compatibility | ||
UPDATE api_keys SET scopes = ARRAY[scope::api_key_scope]; | ||
UPDATE api_keys SET allow_list = ARRAY['*:*']; | ||
-- Enforce NOT NULL | ||
ALTER TABLE api_keys ALTER COLUMN scopes SET NOT NULL; | ||
ALTER TABLE api_keys ALTER COLUMN allow_list SET NOT NULL; | ||
-- Drop legacy single-scope column | ||
ALTER TABLE api_keys DROP COLUMN scope; |
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.