Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
181a97dad6
commit
3413404754
|
|
@ -136,7 +136,7 @@ export default {
|
|||
params: { id: filename },
|
||||
query: $route.query,
|
||||
}"
|
||||
class="gl-text-default hover:gl-text-default"
|
||||
class="gl-block gl-rounded-base gl-text-default hover:gl-text-default focus:gl-focus"
|
||||
>
|
||||
<gl-card
|
||||
class="js-design-list-item design-list-item gl-mb-0"
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ export default {
|
|||
class="gl-align-center gl-max-w-26 gl-rounded-none gl-rounded-br-base gl-rounded-tr-base"
|
||||
:value="value"
|
||||
:state="state"
|
||||
:aria-labelledby="label"
|
||||
@input="handleColorChange"
|
||||
>
|
||||
<template #prepend>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,11 @@ module OauthApplications
|
|||
|
||||
def load_scopes
|
||||
@scopes ||= Doorkeeper::OAuth::Scopes.from_array(
|
||||
Doorkeeper.configuration.scopes.to_a - [::Gitlab::Auth::AI_WORKFLOW.to_s] - [::Gitlab::Auth::DYNAMIC_USER.to_s]
|
||||
Doorkeeper.configuration.scopes.to_a - [
|
||||
::Gitlab::Auth::AI_WORKFLOW.to_s,
|
||||
::Gitlab::Auth::DYNAMIC_USER.to_s,
|
||||
::Gitlab::Auth::SELF_ROTATE_SCOPE.to_s
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ en:
|
|||
k8s_proxy: Grants permission to perform Kubernetes API calls using the agent for Kubernetes.
|
||||
ai_features: Access to API endpoints needed for GitLab Duo features
|
||||
read_service_ping: Grant access to download Service Ping payload via API when authenticated as an admin user
|
||||
self_rotate: Grants permission for token to rotate itself
|
||||
user:*: Grants access only if both the token owner and user:<id> has access to the resource.
|
||||
scope_desc:
|
||||
api: Grants complete read/write access to the API, including all groups and projects, the container registry, the dependency proxy, and the package registry.
|
||||
|
|
@ -102,6 +103,7 @@ en:
|
|||
manage_runner: Grants access to manage the runners.
|
||||
k8s_proxy: Grants permission to perform Kubernetes API calls using the agent for Kubernetes.
|
||||
read_service_ping: Grant access to download Service Ping payload via API when authenticated as an admin user
|
||||
self_rotate: Grants permission for token to rotate itself.
|
||||
group_access_token_scope_desc:
|
||||
api: Grants complete read and write access to the scoped group and related project API, including the container registry, the dependency proxy, and the package registry.
|
||||
read_api: Grants read access to the scoped group and related project API, including the package registry.
|
||||
|
|
@ -121,6 +123,7 @@ en:
|
|||
create_runner: Grants permission to create runners in a group.
|
||||
manage_runner: Grants access to manage the runners in a group.
|
||||
k8s_proxy: Grants permission to perform Kubernetes API calls using the agent for Kubernetes in a group.
|
||||
self_rotate: Grants permission for token to rotate itself.
|
||||
project_access_token_scope_desc:
|
||||
api: Grants complete read and write access to the scoped project API, including the container registry, the dependency proxy, and the package registry.
|
||||
read_api: Grants read access to the scoped project API, including the Package Registry.
|
||||
|
|
@ -134,6 +137,7 @@ en:
|
|||
manage_runner: Grants access to manage the runners.
|
||||
k8s_proxy: Grants permission to perform Kubernetes API calls using the agent for Kubernetes.
|
||||
ai_features: Grants access to GitLab Duo related API endpoints.
|
||||
self_rotate: Grants permission for token to rotate itself.
|
||||
flash:
|
||||
applications:
|
||||
create:
|
||||
|
|
|
|||
|
|
@ -146,14 +146,21 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
|||
|
||||
## Rotate a group access token
|
||||
|
||||
Rotate a group access token. Revokes the previous token and creates a new token that expires in one week.
|
||||
|
||||
You can either:
|
||||
|
||||
- Use the group access token ID.
|
||||
- In GitLab 17.9 and later, pass the group access token to the API in a request header.
|
||||
|
||||
### Use a group access token ID
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/403042) in GitLab 16.0
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have a [personal access token with the `api` scope](../user/profile/personal_access_tokens.md#personal-access-token-scopes).
|
||||
|
||||
Rotate a group access token. Revokes the previous token and creates a new token that expires in one week.
|
||||
|
||||
In GitLab 16.6 and later, you can use the `expires_at` parameter to set a different expiry date. This non-default expiry date can be up to a maximum of one year from the rotation date.
|
||||
|
||||
```plaintext
|
||||
|
|
@ -167,7 +174,8 @@ POST /groups/:id/access_tokens/:token_id/rotate
|
|||
| `expires_at` | date | no | Expiration date of the access token in ISO format (`YYYY-MM-DD`). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416795) in GitLab 16.6. If undefined, the token expires after one week. |
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/<group_id>/access_tokens/<token_id>/rotate"
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
"https://gitlab.example.com/api/v4/groups/<group_id>/access_tokens/<token_id>/rotate"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
|
@ -178,6 +186,7 @@ Example response:
|
|||
"name": "Rotated Token",
|
||||
"revoked": false,
|
||||
"created_at": "2023-08-01T15:00:00.000Z",
|
||||
"description": "Test group access token",
|
||||
"scopes": ["api"],
|
||||
"user_id": 1337,
|
||||
"last_used_at": null,
|
||||
|
|
@ -188,15 +197,69 @@ Example response:
|
|||
}
|
||||
```
|
||||
|
||||
### Responses
|
||||
#### Responses
|
||||
|
||||
- `200: OK` if existing token is successfully revoked and the new token is created.
|
||||
- `400: Bad Request` if not rotated successfully.
|
||||
- `401: Unauthorized` if either the:
|
||||
- User does not have access to the token with the specified ID.
|
||||
- Token with the specified ID does not exist.
|
||||
- `401: Unauthorized` if any of the following conditions are true:
|
||||
- You do not have access to the specified token.
|
||||
- The specified token does not exist.
|
||||
- You're authenticating with a group access token. Use [`/groups/:id/access_tokens/self/rotate`](#use-a-request-header). instead.
|
||||
- `404: Not Found` if the user is an administrator but the token with the specified ID does not exist.
|
||||
|
||||
### Use a request header
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178111) in GitLab 17.9
|
||||
|
||||
Requires:
|
||||
|
||||
- `api` or `self_rotate` scope.
|
||||
|
||||
In GitLab 16.6 and later, you can use the `expires_at` parameter to set a different expiry date. This non-default expiry date is subject to the [maximum allowable lifetime limits](../user/profile/personal_access_tokens.md#access-token-expiration).
|
||||
|
||||
```plaintext
|
||||
POST /groups/:id/access_tokens/self/rotate
|
||||
```
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_group_access_token>" \
|
||||
"https://gitlab.example.com/api/v4/groups/<group_id>/access_tokens/self/rotate"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 42,
|
||||
"name": "Rotated Token",
|
||||
"revoked": false,
|
||||
"created_at": "2025-01-19T15:00:00.000Z",
|
||||
"description": "Test group access token",
|
||||
"scopes": ["read_api","self_rotate"],
|
||||
"user_id": 1337,
|
||||
"last_used_at": null,
|
||||
"active": true,
|
||||
"expires_at": "2025-01-26",
|
||||
"access_level": 30,
|
||||
"token": "s3cr3t"
|
||||
}
|
||||
```
|
||||
|
||||
#### Responses
|
||||
|
||||
- `200: OK` if the existing group access token is successfully revoked and the new token successfully created.
|
||||
- `400: Bad Request` if not rotated successfully.
|
||||
- `401: Unauthorized` if any of the following conditions are true:
|
||||
- The token does not exist.
|
||||
- The token has expired.
|
||||
- The token was revoked.
|
||||
- The token is not a group access token associated with the specified group.
|
||||
- `403: Forbidden` if the token is not allowed to rotate itself.
|
||||
- `405: Method Not Allowed` if the token is not an access token.
|
||||
|
||||
### Automatic reuse detection
|
||||
|
||||
Refer to [automatic reuse detection for personal access tokens](personal_access_tokens.md#automatic-reuse-detection)
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ Example response:
|
|||
|
||||
Requires:
|
||||
|
||||
- `api` scope.
|
||||
- `api` or `self_rotate` scope.
|
||||
|
||||
In GitLab 16.6 and later, you can use the `expires_at` parameter to set a different expiry date. This non-default expiry date is subject to the [maximum allowable lifetime limits](../user/profile/personal_access_tokens.md#access-token-expiration).
|
||||
|
||||
|
|
@ -300,7 +300,7 @@ Example response:
|
|||
"user_id": 1337,
|
||||
"last_used_at": null,
|
||||
"active": true,
|
||||
"expires_at": "2023-08-15",
|
||||
"expires_at": "2023-08-08",
|
||||
"token": "s3cr3t"
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -152,14 +152,21 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
|||
|
||||
## Rotate a project access token
|
||||
|
||||
Rotate a project access token. Revokes the previous token and creates a new token that expires in one week.
|
||||
|
||||
You can either:
|
||||
|
||||
- Use a project access token ID.
|
||||
- In GitLab 17.9 and later, pass the project access token to the API in a request header.
|
||||
|
||||
### Use a project access token ID
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/403042) in GitLab 16.0
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have a [personal access token with the `api` scope](../user/profile/personal_access_tokens.md#personal-access-token-scopes).
|
||||
|
||||
Rotate a project access token. Revokes the previous token and creates a new token that expires in one week.
|
||||
|
||||
In GitLab 16.6 and later, you can use the `expires_at` parameter to set a different expiry date. This non-default expiry date can be up to a maximum of one year from the rotation date.
|
||||
|
||||
```plaintext
|
||||
|
|
@ -173,7 +180,8 @@ POST /projects/:id/access_tokens/:token_id/rotate
|
|||
| `expires_at` | date | no | Expiration date of the access token in ISO format (`YYYY-MM-DD`). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416795) in GitLab 16.6. If undefined, the token expires after one week. |
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>/rotate"
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
"https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>/rotate"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
|
@ -184,6 +192,7 @@ Example response:
|
|||
"name": "Rotated Token",
|
||||
"revoked": false,
|
||||
"created_at": "2023-08-01T15:00:00.000Z",
|
||||
"description": "Test project access token",
|
||||
"scopes": ["api"],
|
||||
"user_id": 1337,
|
||||
"last_used_at": null,
|
||||
|
|
@ -194,15 +203,69 @@ Example response:
|
|||
}
|
||||
```
|
||||
|
||||
### Responses
|
||||
#### Responses
|
||||
|
||||
- `200: OK` if the existing token is successfully revoked and the new token is successfully created.
|
||||
- `400: Bad Request` if not rotated successfully.
|
||||
- `401: Unauthorized` if either the:
|
||||
- User does not have access to the token with the specified ID.
|
||||
- Token with the specified ID does not exist.
|
||||
- `401: Unauthorized` if any of the following conditions are true:
|
||||
- You do not have access to the specified token.
|
||||
- The specified token does not exist.
|
||||
- You're authenticating with a project access token. Use [`/projects/:id/access_tokens/self/rotate`](#use-a-request-header). instead.
|
||||
- `404: Not Found` if the user is an administrator but the token with the specified ID does not exist.
|
||||
|
||||
### Use a request header
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178111) in GitLab 17.9
|
||||
|
||||
Requires:
|
||||
|
||||
- `api` or `self_rotate` scope.
|
||||
|
||||
In GitLab 16.6 and later, you can use the `expires_at` parameter to set a different expiry date. This non-default expiry date is subject to the [maximum allowable lifetime limits](../user/profile/personal_access_tokens.md#access-token-expiration).
|
||||
|
||||
```plaintext
|
||||
POST /projects/:id/access_tokens/self/rotate
|
||||
```
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_project_access_token>" \
|
||||
"https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/self/rotate"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 42,
|
||||
"name": "Rotated Token",
|
||||
"revoked": false,
|
||||
"created_at": "2025-01-19T15:00:00.000Z",
|
||||
"description": "Test project access token",
|
||||
"scopes": ["read_api","self_rotate"],
|
||||
"user_id": 1337,
|
||||
"last_used_at": null,
|
||||
"active": true,
|
||||
"expires_at": "2025-01-26",
|
||||
"access_level": 30,
|
||||
"token": "s3cr3t"
|
||||
}
|
||||
```
|
||||
|
||||
#### Responses
|
||||
|
||||
- `200: OK` if the existing project access token is successfully revoked and the new token successfully created.
|
||||
- `400: Bad Request` if not rotated successfully.
|
||||
- `401: Unauthorized` if any of the following conditions are true:
|
||||
- The token does not exist.
|
||||
- The token has expired.
|
||||
- The token was revoked.
|
||||
- The token is not a project access token associated with the specified project.
|
||||
- `403: Forbidden` if the token is not allowed to rotate itself.
|
||||
- `405: Method Not Allowed` if the token is not a project access token.
|
||||
|
||||
### Automatic reuse detection
|
||||
|
||||
Refer to [automatic reuse detection for personal access tokens](personal_access_tokens.md#automatic-reuse-detection)
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ To revoke or rotate a group access token:
|
|||
|
||||
> - `k8s_proxy` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/422408) in GitLab 16.4 [with a flag](../../../administration/feature_flags.md) named `k8s_proxy_pat`. Enabled by default.
|
||||
> - Feature flag `k8s_proxy_pat` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131518) in GitLab 16.5.
|
||||
> - `self_rotate` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178111) in GitLab 17.9. Enabled by default.
|
||||
|
||||
The scope determines the actions you can perform when you authenticate with a group access token.
|
||||
|
||||
|
|
@ -162,6 +163,7 @@ The scope determines the actions you can perform when you authenticate with a gr
|
|||
| `manage_runner` | Grants permission to manage runners in a group. |
|
||||
| `ai_features` | Grants permission to perform API actions for GitLab Duo. This scope is designed to work with the GitLab Duo Plugin for JetBrains. For all other extensions, see scope requirements. |
|
||||
| `k8s_proxy` | Grants permission to perform Kubernetes API calls using the agent for Kubernetes in a group. |
|
||||
| `self_rotate` | Grants permission to rotate this token using the [personal access token API](../../../api/personal_access_tokens.md#use-a-request-header). Does not allow rotation of other tokens. |
|
||||
|
||||
## Restrict the creation of group access tokens
|
||||
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ To view the last time a token was used, and the IP addresses from where the toke
|
|||
> - Feature flag `k8s_proxy_pat` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131518) in GitLab 16.5.
|
||||
> - `read_service_ping` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/42692#note_1222832412) in GitLab 17.1.
|
||||
> - `manage_runner` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460721) in GitLab 17.1.
|
||||
> - `self_rotate` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178111) in GitLab 17.9. Enabled by default.
|
||||
|
||||
A personal access token can perform actions based on the assigned scopes.
|
||||
|
||||
|
|
@ -205,6 +206,7 @@ A personal access token can perform actions based on the assigned scopes.
|
|||
| `manage_runner` | Grants permission to manage runners. |
|
||||
| `ai_features` | This scope:<br>- Grants permission to perform API actions for features like GitLab Duo, Code Suggestions API and Duo Chat API.<br>- Does not work for GitLab Self-Managed versions 16.5, 16.6, and 16.7.<br>For GitLab Duo plugin for JetBrains, this scope:<br>- Supports users with AI features enabled in the GitLab Duo plugin for JetBrains.<br>- Addresses a security vulnerability in JetBrains IDE plugins that could expose personal access tokens.<br>- Is designed to minimize potential risks for GitLab Duo plugin users by limiting the impact of compromised tokens.<br>For all other extensions, see the individual scope requirements in their documentation. |
|
||||
| `k8s_proxy` | Grants permission to perform Kubernetes API calls using the agent for Kubernetes. |
|
||||
| `self_rotate` | Grants permission to rotate this token using the [personal access token API](../../api/personal_access_tokens.md#use-a-request-header). Does not allow rotation of other tokens. |
|
||||
| `read_service_ping`| Grant access to download Service Ping payload through the API when authenticated as an admin use. |
|
||||
|
||||
WARNING:
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ To revoke or rotate a project access token:
|
|||
|
||||
> - `k8s_proxy` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/422408) in GitLab 16.4 [with a flag](../../../administration/feature_flags.md) named `k8s_proxy_pat`. Enabled by default.
|
||||
> - Feature flag `k8s_proxy_pat` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131518) in GitLab 16.5.
|
||||
> - `self_rotate` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178111) in GitLab 17.9. Enabled by default.
|
||||
|
||||
The scope determines the actions you can perform when you authenticate with a project access token.
|
||||
|
||||
|
|
@ -118,6 +119,7 @@ See the warning in [create a project access token](#create-a-project-access-toke
|
|||
| `manage_runner` | Grants permission to manage runners in the project. |
|
||||
| `ai_features` | Grants permission to perform API actions for GitLab Duo. This scope is designed to work with the GitLab Duo Plugin for JetBrains. For all other extensions, see scope requirements. |
|
||||
| `k8s_proxy` | Grants permission to perform Kubernetes API calls using the agent for Kubernetes in the project. |
|
||||
| `self_rotate` | Grants permission to rotate this token using the [personal access token API](../../../api/personal_access_tokens.md#use-a-request-header). Does not allow rotation of other tokens. |
|
||||
|
||||
## Restrict the creation of project access tokens
|
||||
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ module API
|
|||
mount ::API::Release::Links
|
||||
mount ::API::RemoteMirrors
|
||||
mount ::API::Repositories
|
||||
mount ::API::ResourceAccessTokens::SelfRotation
|
||||
mount ::API::ResourceAccessTokens
|
||||
mount ::API::ResourceMilestoneEvents
|
||||
mount ::API::RpmProjectPackages
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ module API
|
|||
helpers ::API::Helpers::PersonalAccessTokensHelpers
|
||||
|
||||
allow_access_with_scope :api
|
||||
allow_access_with_scope :self_rotate
|
||||
|
||||
before { authenticate! }
|
||||
|
||||
|
|
@ -33,7 +34,6 @@ module API
|
|||
end
|
||||
post 'self/rotate' do
|
||||
not_allowed! unless access_token.is_a? PersonalAccessToken
|
||||
forbidden! if current_user.project_bot?
|
||||
|
||||
new_token = rotate_token(access_token, declared_params)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
class ResourceAccessTokens
|
||||
class SelfRotation < ::API::Base
|
||||
include APIGuard
|
||||
|
||||
feature_category :system_access
|
||||
|
||||
helpers ::API::Helpers::PersonalAccessTokensHelpers
|
||||
helpers ::API::ResourceAccessTokens.helpers
|
||||
|
||||
allow_access_with_scope :api
|
||||
allow_access_with_scope :self_rotate
|
||||
|
||||
before { authenticate! }
|
||||
|
||||
%w[project group].each do |source_type|
|
||||
resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||
desc 'Rotate a resource access token' do
|
||||
detail 'Rotates a resource access token by passing it to the API in a header'
|
||||
success code: 200, model: Entities::ResourceAccessTokenWithToken
|
||||
failure [
|
||||
{ code: 400, message: 'Bad Request' },
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 405, message: 'Method not allowed' }
|
||||
]
|
||||
tags %w[personal_access_tokens]
|
||||
end
|
||||
params do
|
||||
requires :id, type: String, desc: "The #{source_type} ID"
|
||||
optional :expires_at,
|
||||
type: Date,
|
||||
desc: "The expiration date of the token",
|
||||
documentation: { example: '2021-01-31' }
|
||||
end
|
||||
post ':id/access_tokens/self/rotate' do
|
||||
not_allowed! unless access_token.is_a? PersonalAccessToken
|
||||
not_allowed! unless current_user.project_bot?
|
||||
|
||||
resource = find_source(source_type, params[:id])
|
||||
token = find_token(resource, access_token.id)
|
||||
|
||||
unauthorized! unless token
|
||||
|
||||
new_token = rotate_token(token, declared_params)
|
||||
|
||||
present new_token, with: Entities::ResourceAccessTokenWithToken, resource: resource
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -7,6 +7,9 @@ module Gitlab
|
|||
# Scopes used for GitLab internal API (Kubernetes cluster access)
|
||||
K8S_PROXY_SCOPE = :k8s_proxy
|
||||
|
||||
# Scopes used for token allowed to rotate themselves
|
||||
SELF_ROTATE_SCOPE = :self_rotate
|
||||
|
||||
# Scopes used for GitLab API access
|
||||
API_SCOPE = :api
|
||||
READ_API_SCOPE = :read_api
|
||||
|
|
@ -17,7 +20,8 @@ module Gitlab
|
|||
API_SCOPE, READ_API_SCOPE,
|
||||
READ_USER_SCOPE,
|
||||
CREATE_RUNNER_SCOPE, MANAGE_RUNNER_SCOPE,
|
||||
K8S_PROXY_SCOPE
|
||||
K8S_PROXY_SCOPE,
|
||||
SELF_ROTATE_SCOPE
|
||||
].freeze
|
||||
|
||||
# Scopes for Duo
|
||||
|
|
|
|||
|
|
@ -480,8 +480,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def access_token_rotation_request?
|
||||
current_request.path.match(%r{access_tokens/\d+/rotate$}) ||
|
||||
current_request.path.match(%r{/personal_access_tokens/self/rotate$})
|
||||
current_request.path.match(%r{access_tokens/(\d+|self)/rotate$})
|
||||
end
|
||||
|
||||
# To prevent Rack Attack from incorrectly rate limiting
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ exports[`Design management list item component when item appears in view after i
|
|||
|
||||
exports[`Design management list item component with notes renders item with multiple comments 1`] = `
|
||||
<a
|
||||
class="gl-text-default hover:gl-text-default"
|
||||
class="focus:gl-focus gl-block gl-rounded-base gl-text-default hover:gl-text-default"
|
||||
>
|
||||
<gl-card-stub
|
||||
bodyclass="gl-p-0 gl-flex gl-w-full gl-bg-default gl-py-3 gl-px-4 gl-rounded-base"
|
||||
|
|
@ -73,7 +73,7 @@ exports[`Design management list item component with notes renders item with mult
|
|||
|
||||
exports[`Design management list item component with notes renders item with single comment 1`] = `
|
||||
<a
|
||||
class="gl-text-default hover:gl-text-default"
|
||||
class="focus:gl-focus gl-block gl-rounded-base gl-text-default hover:gl-text-default"
|
||||
>
|
||||
<gl-card-stub
|
||||
bodyclass="gl-p-0 gl-flex gl-w-full gl-bg-default gl-py-3 gl-px-4 gl-rounded-base"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
|
||||
describe 'constants' do
|
||||
it 'API_SCOPES contains all scopes for API access' do
|
||||
expect(subject::API_SCOPES).to match_array %i[api read_user read_api create_runner manage_runner k8s_proxy]
|
||||
expect(subject::API_SCOPES).to match_array %i[api read_user read_api create_runner manage_runner k8s_proxy self_rotate]
|
||||
end
|
||||
|
||||
it 'ADMIN_SCOPES contains all scopes for ADMIN access' do
|
||||
|
|
@ -52,6 +52,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
expect(subject.all_available_scopes).to match_array %i[
|
||||
api read_user read_api read_repository read_service_ping write_repository read_registry write_registry
|
||||
sudo admin_mode read_observability write_observability create_runner manage_runner k8s_proxy ai_features
|
||||
self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
|
||||
expect(subject.available_scopes_for(user)).to match_array %i[
|
||||
api read_user read_api read_repository write_repository read_registry write_registry
|
||||
create_runner manage_runner k8s_proxy ai_features
|
||||
create_runner manage_runner k8s_proxy ai_features self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -69,7 +70,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
|
||||
expect(subject.available_scopes_for(user)).to match_array %i[
|
||||
api read_user read_api read_repository read_service_ping write_repository read_registry write_registry
|
||||
sudo admin_mode create_runner manage_runner k8s_proxy ai_features
|
||||
sudo admin_mode create_runner manage_runner k8s_proxy ai_features self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -77,6 +78,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
expect(subject.available_scopes_for(project)).to match_array %i[
|
||||
api read_api read_repository write_repository read_registry write_registry
|
||||
read_observability write_observability create_runner manage_runner k8s_proxy ai_features
|
||||
self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -86,6 +88,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
expect(subject.available_scopes_for(group)).to match_array %i[
|
||||
api read_api read_repository write_repository read_registry write_registry
|
||||
read_observability write_observability create_runner manage_runner k8s_proxy ai_features
|
||||
self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -110,6 +113,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
read_repository
|
||||
read_service_ping
|
||||
read_user
|
||||
self_rotate
|
||||
sudo
|
||||
user:*
|
||||
write_observability
|
||||
|
|
@ -131,7 +135,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
|
||||
expect(subject.available_scopes_for(group)).to match_array %i[
|
||||
api read_api read_repository write_repository read_registry write_registry create_runner manage_runner
|
||||
k8s_proxy ai_features
|
||||
k8s_proxy ai_features self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -143,7 +147,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
|
||||
expect(subject.available_scopes_for(project)).to match_array %i[
|
||||
api read_api read_repository write_repository read_registry write_registry create_runner manage_runner
|
||||
k8s_proxy ai_features
|
||||
k8s_proxy ai_features self_rotate
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
@ -164,6 +168,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
expect(subject.available_scopes_for(group)).to match_array %i[
|
||||
api read_api read_repository write_repository read_registry write_registry
|
||||
read_observability write_observability create_runner manage_runner k8s_proxy ai_features
|
||||
self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -172,7 +177,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
|
||||
expect(subject.available_scopes_for(user)).to match_array %i[
|
||||
api read_user read_api read_repository write_repository read_registry write_registry read_service_ping
|
||||
sudo admin_mode create_runner manage_runner k8s_proxy ai_features
|
||||
sudo admin_mode create_runner manage_runner k8s_proxy ai_features self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -180,6 +185,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
expect(subject.available_scopes_for(project)).to match_array %i[
|
||||
api read_api read_repository write_repository read_registry write_registry
|
||||
read_observability write_observability create_runner manage_runner k8s_proxy ai_features
|
||||
self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -192,6 +198,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
expect(subject.available_scopes_for(other_group)).to match_array %i[
|
||||
api read_api read_repository write_repository read_registry write_registry
|
||||
create_runner manage_runner k8s_proxy ai_features
|
||||
self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -204,7 +211,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
|
||||
expect(subject.available_scopes_for(other_project)).to match_array %i[
|
||||
api read_api read_repository write_repository read_registry write_registry
|
||||
create_runner manage_runner k8s_proxy ai_features
|
||||
create_runner manage_runner k8s_proxy ai_features self_rotate
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ RSpec.describe API::PersonalAccessTokens::SelfRotation, feature_category: :syste
|
|||
let(:current_user) { create(:admin) }
|
||||
let(:token) { create(:personal_access_token, scopes: [scope], user: current_user) }
|
||||
|
||||
if [Gitlab::Auth::API_SCOPE].include? scope
|
||||
if [Gitlab::Auth::API_SCOPE, Gitlab::Auth::SELF_ROTATE_SCOPE].include? scope
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
else
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
|
|
@ -87,12 +87,21 @@ RSpec.describe API::PersonalAccessTokens::SelfRotation, feature_category: :syste
|
|||
let(:current_user) { create(:user) }
|
||||
let(:token) { create(:personal_access_token, scopes: [scope], user: current_user) }
|
||||
|
||||
if [Gitlab::Auth::API_SCOPE].include? scope
|
||||
if [Gitlab::Auth::API_SCOPE, Gitlab::Auth::SELF_ROTATE_SCOPE].include? scope
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
else
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
context "with '#{scope}' and 'self_rotate' scoped token" do
|
||||
let(:current_user) { create(:user) }
|
||||
let(:token) do
|
||||
create(:personal_access_token, scopes: [scope, Gitlab::Auth::SELF_ROTATE_SCOPE], user: current_user)
|
||||
end
|
||||
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -141,7 +150,7 @@ RSpec.describe API::PersonalAccessTokens::SelfRotation, feature_category: :syste
|
|||
context "with a '#{scope}' scoped token" do
|
||||
let(:token) { create(:oauth_access_token, scopes: [scope]) }
|
||||
|
||||
if [Gitlab::Auth::API_SCOPE].include? scope
|
||||
if [Gitlab::Auth::API_SCOPE, Gitlab::Auth::SELF_ROTATE_SCOPE].include? scope
|
||||
it_behaves_like 'rotating token denied', :method_not_allowed
|
||||
else
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
|
|
@ -170,26 +179,38 @@ RSpec.describe API::PersonalAccessTokens::SelfRotation, feature_category: :syste
|
|||
context 'when current_user is a project bot' do
|
||||
let(:current_user) { create(:user, :project_bot) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
|
||||
context 'when expiry is defined' do
|
||||
let(:expiry_date) { Date.today + 1.month }
|
||||
let(:params) { { expires_at: expiry_date } }
|
||||
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
end
|
||||
|
||||
context 'with impersonated token' do
|
||||
let(:token) { create(:personal_access_token, :impersonation, user: current_user) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
end
|
||||
|
||||
Gitlab::Auth.resource_bot_scopes.each do |scope|
|
||||
context "with a '#{scope}' scoped token" do
|
||||
let(:token) { create(:personal_access_token, scopes: [scope], user: current_user) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
if [Gitlab::Auth::API_SCOPE, Gitlab::Auth::SELF_ROTATE_SCOPE].include? scope
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
else
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
context "with '#{scope}' and 'self_rotate' scoped token" do
|
||||
let(:token) do
|
||||
create(:personal_access_token, scopes: [scope, Gitlab::Auth::SELF_ROTATE_SCOPE], user: current_user)
|
||||
end
|
||||
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,189 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe API::ResourceAccessTokens::SelfRotation, feature_category: :system_access do
|
||||
let(:token) { create(:personal_access_token, user: current_user) }
|
||||
let(:expiry_date) { Time.zone.today + 1.week }
|
||||
let(:params) { {} }
|
||||
|
||||
let_it_be(:current_user) { create(:user, :project_bot) }
|
||||
let_it_be(:other_user) { create(:user, :project_bot) }
|
||||
|
||||
subject(:rotate_token) { post(api(path, personal_access_token: token), params: params) }
|
||||
|
||||
shared_examples 'rotating token succeeds' do
|
||||
it 'rotate token', :aggregate_failures do
|
||||
rotate_token
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response['token']).not_to eq(token.token)
|
||||
expect(json_response['expires_at']).to eq(expiry_date.to_s)
|
||||
expect(token.reload).to be_revoked
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'rotating token denied' do |status|
|
||||
it 'cannot rotate token' do
|
||||
rotate_token
|
||||
|
||||
expect(response).to have_gitlab_http_status(status)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'rotating resource access token' do |source_type|
|
||||
let(:resource_id) { resource.id }
|
||||
let(:path) { "/#{source_type}s/#{resource_id}/access_tokens/self/rotate" }
|
||||
|
||||
describe "POST #{source_type}s/:id/access_tokens/self/rotate" do
|
||||
context 'when token is not a valid resource token' do
|
||||
context 'when token is a personal access token' do
|
||||
before do
|
||||
resource.add_guest(current_user)
|
||||
end
|
||||
|
||||
context 'when current_user is an administrator', :enable_admin_mode do
|
||||
let_it_be(:current_user) { create(:admin) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :method_not_allowed
|
||||
end
|
||||
|
||||
context 'when current_user is not an administrator' do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :method_not_allowed
|
||||
end
|
||||
end
|
||||
|
||||
context 'when token is invalid' do
|
||||
let(:token) { instance_double(PersonalAccessToken, token: 'invalidtoken') }
|
||||
|
||||
it_behaves_like 'rotating token denied', :unauthorized
|
||||
end
|
||||
|
||||
context 'with a revoked token' do
|
||||
let(:token) { create(:personal_access_token, :revoked, user: current_user) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :unauthorized
|
||||
end
|
||||
|
||||
context 'with an expired token' do
|
||||
let(:token) { create(:personal_access_token, expires_at: 1.day.ago, user: current_user) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :unauthorized
|
||||
end
|
||||
|
||||
context 'with a rotated token' do
|
||||
let(:token) { create(:personal_access_token, :revoked, user: current_user) }
|
||||
let!(:child_token) { create(:personal_access_token, previous_personal_access_token_id: token.id) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :unauthorized
|
||||
|
||||
it 'revokes token family' do
|
||||
rotate_token
|
||||
|
||||
expect(child_token.reload).to be_revoked
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an OAuth token' do
|
||||
subject(:rotate_token) { post(api(path, oauth_access_token: token), params: params) }
|
||||
|
||||
context 'with default scope' do
|
||||
let(:token) { create(:oauth_access_token) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
end
|
||||
|
||||
context 'with api or self_rotate scope' do
|
||||
let(:token) do
|
||||
create(:oauth_access_token, scopes: [Gitlab::Auth::API_SCOPE, Gitlab::Auth::SELF_ROTATE_SCOPE])
|
||||
end
|
||||
|
||||
it_behaves_like 'rotating token denied', :method_not_allowed
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a deploy token' do
|
||||
let(:token) { create(:deploy_token) }
|
||||
let(:headers) { { Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => token.token } }
|
||||
|
||||
subject(:rotate_token) { post(api(path), params: params, headers: headers) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :unauthorized
|
||||
end
|
||||
|
||||
context 'with a job token' do
|
||||
let(:job) { create(:ci_build, :running, user: current_user) }
|
||||
|
||||
subject(:rotate_token) { post(api(path, job_token: job.token), params: params) }
|
||||
|
||||
it_behaves_like 'rotating token denied', :unauthorized
|
||||
end
|
||||
end
|
||||
|
||||
context "when token is a valid #{source_type} token" do
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
|
||||
context 'when expiry is defined' do
|
||||
let(:expiry_date) { Time.zone.today + 1.month }
|
||||
let(:params) { { expires_at: expiry_date } }
|
||||
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
end
|
||||
|
||||
Gitlab::Auth.resource_bot_scopes.each do |scope|
|
||||
context "with a '#{scope}' scoped token" do
|
||||
let(:token) { create(:personal_access_token, scopes: [scope], user: current_user) }
|
||||
|
||||
if [Gitlab::Auth::API_SCOPE, Gitlab::Auth::SELF_ROTATE_SCOPE].include? scope
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
else
|
||||
it_behaves_like 'rotating token denied', :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
context "with '#{scope}' and 'self_rotate' scoped token" do
|
||||
let(:token) do
|
||||
create(:personal_access_token, scopes: [scope, Gitlab::Auth::SELF_ROTATE_SCOPE], user: current_user)
|
||||
end
|
||||
|
||||
it_behaves_like 'rotating token succeeds'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when token does not belong to the resource" do
|
||||
Gitlab::VisibilityLevel.string_values.each do |visibility|
|
||||
context "when resource visibility is '#{visibility}'" do
|
||||
let_it_be(:resource) { create(source_type, visibility) }
|
||||
|
||||
let(:token) { create(:personal_access_token, user: other_user) }
|
||||
|
||||
if Gitlab::VisibilityLevel.level_value(visibility) != Gitlab::VisibilityLevel::PRIVATE
|
||||
it_behaves_like 'rotating token denied', :unauthorized
|
||||
else
|
||||
it_behaves_like 'rotating token denied', :not_found
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the resource is a project' do
|
||||
let_it_be(:resource) { create(:project) }
|
||||
|
||||
before_all { resource.add_guest(current_user) }
|
||||
|
||||
it_behaves_like 'rotating resource access token', 'project'
|
||||
end
|
||||
|
||||
context 'when the resource is a group' do
|
||||
let_it_be(:resource) { create(:group) }
|
||||
|
||||
before_all { resource.add_guest(current_user) }
|
||||
|
||||
it_behaves_like 'rotating resource access token', 'group'
|
||||
end
|
||||
end
|
||||
|
|
@ -120,6 +120,7 @@ RSpec.describe Groups::Settings::AccessTokensController, feature_category: :syst
|
|||
|
||||
it 'sets available scopes' do
|
||||
expect(assigns(:scopes)).to include(Gitlab::Auth::K8S_PROXY_SCOPE)
|
||||
expect(assigns(:scopes)).to include(Gitlab::Auth::SELF_ROTATE_SCOPE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -274,7 +274,8 @@ RSpec.describe 'OpenID Connect requests', feature_category: :system_access do
|
|||
let(:expected_scopes) do
|
||||
%w[
|
||||
admin_mode api read_user read_api read_repository write_repository sudo openid profile email
|
||||
read_observability write_observability create_runner manage_runner k8s_proxy ai_features read_service_ping ai_workflows user:*
|
||||
read_observability write_observability create_runner manage_runner k8s_proxy ai_features read_service_ping ai_workflows
|
||||
user:* self_rotate
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ RSpec.describe Projects::Settings::AccessTokensController, feature_category: :sy
|
|||
|
||||
it 'sets available scopes' do
|
||||
expect(assigns(:scopes)).to include(Gitlab::Auth::K8S_PROXY_SCOPE)
|
||||
expect(assigns(:scopes)).to include(Gitlab::Auth::SELF_ROTATE_SCOPE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue