Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-01-27 15:39:12 +00:00
parent 181a97dad6
commit 3413404754
22 changed files with 453 additions and 33 deletions

View File

@ -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"

View File

@ -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>

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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"
}
```

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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