Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-09-29 09:11:43 +00:00
parent cba55463a0
commit c724e639a9
33 changed files with 708 additions and 217 deletions

View File

@ -277,7 +277,8 @@
"type": "string",
"format": "uri-reference",
"pattern": "\\.ya?ml$"
}
},
"rules": { "$ref": "#/definitions/rules" }
},
"required": ["local"]
},
@ -491,7 +492,7 @@
},
"rules": {
"type": "array",
"description": "rules allows for an array of individual rule objects to be evaluated in order, until one matches and dynamically provides attributes to the job.",
"description": "Rules allows for an array of individual rule objects to be evaluated in order, until one matches and dynamically provides attributes to the job.",
"items": {
"type": "object",
"additionalProperties": false,
@ -625,17 +626,26 @@
]
},
"cache": {
"oneOf": [
{
"$ref": "#/definitions/cache_entry"
},
{
"type": "array",
"items": {
"$ref": "#/definitions/cache_entry"
}
"properties": {
"when": {
"description": "Defines when to save the cache, based on the status of the job.",
"default": "on_success",
"oneOf": [
{
"enum": ["on_success"],
"description": "Save the cache only when the job succeeds."
},
{
"enum": ["on_failure"],
"description": "Save the cache only when the job fails. "
},
{
"enum": ["always"],
"description": "Always save the cache. "
}
]
}
]
}
},
"cache_entry": {
"type": "object",
@ -1320,6 +1330,29 @@
}
},
"required": ["artifact", "job"]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"project": {
"description": "Path to another private project under the same GitLab instance, like `group/project` or `group/sub-group/project`.",
"type": "string",
"pattern": "\\S/\\S"
},
"ref": {
"description": "Branch/Tag/Commit hash for the target project.",
"minLength": 1,
"type": "string"
},
"file": {
"description": "Relative path from repository root (`/`) to the pipeline configuration YAML file.",
"type": "string",
"format": "uri-reference",
"pattern": "\\.ya?ml$"
}
},
"required": ["project", "file"]
}
]
}

View File

@ -82,6 +82,7 @@ import searchLabelsQuery from '../queries/search_labels.query.graphql';
import searchMilestonesQuery from '../queries/search_milestones.query.graphql';
import searchUsersQuery from '../queries/search_users.query.graphql';
import IssueCardTimeInfo from './issue_card_time_info.vue';
import NewIssueDropdown from './new_issue_dropdown.vue';
export default {
i18n,
@ -96,6 +97,7 @@ export default {
IssuableByEmail,
IssuableList,
IssueCardTimeInfo,
NewIssueDropdown,
BlockingIssuesCount: () => import('ee_component/issues/components/blocking_issues_count.vue'),
},
directives: {
@ -126,6 +128,9 @@ export default {
hasAnyIssues: {
default: false,
},
hasAnyProjects: {
default: false,
},
hasBlockedIssuesFeature: {
default: false,
},
@ -253,6 +258,9 @@ export default {
showCsvButtons() {
return this.isProject && this.isSignedIn;
},
showNewIssueDropdown() {
return !this.isProject && this.hasAnyProjects;
},
apiFilterParams() {
return convertToApiParams(this.filterTokens);
},
@ -662,6 +670,7 @@ export default {
<gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
{{ $options.i18n.newIssueLabel }}
</gl-button>
<new-issue-dropdown v-if="showNewIssueDropdown" />
</template>
<template #timeframe="{ issuable = {} }">
@ -765,6 +774,7 @@ export default {
:export-csv-path="exportCsvPathWithQuery"
:issuable-count="currentTabCount"
/>
<new-issue-dropdown v-if="showNewIssueDropdown" />
</template>
</gl-empty-state>
<hr />

View File

@ -0,0 +1,124 @@
<script>
import {
GlDropdown,
GlDropdownItem,
GlDropdownText,
GlLoadingIcon,
GlSearchBoxByType,
} from '@gitlab/ui';
import createFlash from '~/flash';
import searchProjectsQuery from '~/issues_list/queries/search_projects.query.graphql';
import { DASH_SCOPE, joinPaths } from '~/lib/utils/url_utility';
import { __, sprintf } from '~/locale';
import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
export default {
i18n: {
defaultDropdownText: __('Select project to create issue'),
noMatchesFound: __('No matches found'),
toggleButtonLabel: __('Toggle project select'),
},
components: {
GlDropdown,
GlDropdownItem,
GlDropdownText,
GlLoadingIcon,
GlSearchBoxByType,
},
inject: ['fullPath'],
data() {
return {
projects: [],
search: '',
selectedProject: {},
shouldSkipQuery: true,
};
},
apollo: {
projects: {
query: searchProjectsQuery,
variables() {
return {
fullPath: this.fullPath,
search: this.search,
};
},
update: ({ group }) => group.projects.nodes ?? [],
error(error) {
createFlash({
message: __('An error occurred while loading projects.'),
captureError: true,
error,
});
},
skip() {
return this.shouldSkipQuery;
},
debounce: DEBOUNCE_DELAY,
},
},
computed: {
dropdownHref() {
return this.hasSelectedProject
? joinPaths(this.selectedProject.webUrl, DASH_SCOPE, 'issues/new')
: undefined;
},
dropdownText() {
return this.hasSelectedProject
? sprintf(__('New issue in %{project}'), { project: this.selectedProject.name })
: this.$options.i18n.defaultDropdownText;
},
hasSelectedProject() {
return this.selectedProject.id;
},
showNoSearchResultsText() {
return !this.projects.length && this.search;
},
},
methods: {
handleDropdownClick() {
if (!this.dropdownHref) {
this.$refs.dropdown.show();
}
},
handleDropdownShown() {
if (this.shouldSkipQuery) {
this.shouldSkipQuery = false;
}
this.$refs.search.focusInput();
},
selectProject(project) {
this.selectedProject = project;
},
},
};
</script>
<template>
<gl-dropdown
ref="dropdown"
right
split
:split-href="dropdownHref"
:text="dropdownText"
:toggle-text="$options.i18n.toggleButtonLabel"
variant="confirm"
@click="handleDropdownClick"
@shown="handleDropdownShown"
>
<gl-search-box-by-type ref="search" v-model.trim="search" />
<gl-loading-icon v-if="$apollo.queries.projects.loading" />
<template v-else>
<gl-dropdown-item
v-for="project of projects"
:key="project.id"
@click="selectProject(project)"
>
{{ project.nameWithNamespace }}
</gl-dropdown-item>
<gl-dropdown-text v-if="showNoSearchResultsText">
{{ $options.i18n.noMatchesFound }}
</gl-dropdown-text>
</template>
</gl-dropdown>
</template>

View File

@ -121,6 +121,7 @@ export function mountIssuesListApp() {
fullPath,
groupEpicsPath,
hasAnyIssues,
hasAnyProjects,
hasBlockedIssuesFeature,
hasIssuableHealthStatusFeature,
hasIssueWeightsFeature,
@ -153,6 +154,7 @@ export function mountIssuesListApp() {
fullPath,
groupEpicsPath,
hasAnyIssues: parseBoolean(hasAnyIssues),
hasAnyProjects: parseBoolean(hasAnyProjects),
hasBlockedIssuesFeature: parseBoolean(hasBlockedIssuesFeature),
hasIssuableHealthStatusFeature: parseBoolean(hasIssuableHealthStatusFeature),
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),

View File

@ -0,0 +1,12 @@
query searchProjects($fullPath: ID!, $search: String) {
group(fullPath: $fullPath) {
projects(search: $search, includeSubgroups: true) {
nodes {
id
name
nameWithNamespace
webUrl
}
}
}
}

View File

@ -1,3 +1,5 @@
export const DASH_SCOPE = '-';
const PATH_SEPARATOR = '/';
const PATH_SEPARATOR_LEADING_REGEX = new RegExp(`^${PATH_SEPARATOR}+`);
const PATH_SEPARATOR_ENDING_REGEX = new RegExp(`${PATH_SEPARATOR}+$`);

View File

@ -322,7 +322,7 @@
display: inline-block;
}
.btn {
.btn:not(.split-content-button):not(.dropdown-toggle-split) {
margin: $gl-padding-8 $gl-padding-4;
@include media-breakpoint-down(xs) {

View File

@ -315,6 +315,9 @@ h1 {
padding-left: 0.6em;
border-radius: 10rem;
}
.bg-transparent {
background-color: transparent !important;
}
.rounded-circle {
border-radius: 50% !important;
}
@ -359,6 +362,20 @@ h1 {
.m-auto {
margin: auto !important;
}
.gl-badge {
display: inline-flex;
align-items: center;
font-size: 0.75rem;
font-weight: 400;
line-height: 1rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.gl-button .gl-badge {
top: 0;
}
.gl-form-input,
.gl-form-input.form-control {
background-color: #333;
@ -856,6 +873,12 @@ input {
.navbar-nav .badge.badge-pill:not(.merge-request-badge).todos-count {
background-color: var(--blue-400, #1f75cb);
}
.title-container .canary-badge .badge,
.navbar-nav .canary-badge .badge {
font-size: 12px;
line-height: 16px;
padding: 0 0.5rem;
}
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid {
font-size: 18px;
@ -1822,9 +1845,18 @@ body.gl-dark {
white-space: nowrap;
width: 1px;
}
.gl-bg-green-500 {
background-color: #2da160;
}
.gl-border-none\! {
border-style: none !important;
}
.gl-rounded-pill {
border-radius: 0.75rem;
}
.gl-text-white {
color: #333;
}
.gl-display-none {
display: none;
}
@ -1843,6 +1875,10 @@ body.gl-dark {
.gl-pr-2 {
padding-right: 0.25rem;
}
.gl-py-1 {
padding-top: 0.125rem;
padding-bottom: 0.125rem;
}
.gl-ml-3 {
margin-left: 0.5rem;
}

View File

@ -295,6 +295,9 @@ h1 {
padding-left: 0.6em;
border-radius: 10rem;
}
.bg-transparent {
background-color: transparent !important;
}
.rounded-circle {
border-radius: 50% !important;
}
@ -339,6 +342,20 @@ h1 {
.m-auto {
margin: auto !important;
}
.gl-badge {
display: inline-flex;
align-items: center;
font-size: 0.75rem;
font-weight: 400;
line-height: 1rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.gl-button .gl-badge {
top: 0;
}
.gl-form-input,
.gl-form-input.form-control {
background-color: #fff;
@ -836,6 +853,12 @@ input {
.navbar-nav .badge.badge-pill:not(.merge-request-badge).todos-count {
background-color: var(--blue-400, #428fdc);
}
.title-container .canary-badge .badge,
.navbar-nav .canary-badge .badge {
font-size: 12px;
line-height: 16px;
padding: 0 0.5rem;
}
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid {
font-size: 18px;
@ -1591,9 +1614,18 @@ svg.s16 {
white-space: nowrap;
width: 1px;
}
.gl-bg-green-500 {
background-color: #108548;
}
.gl-border-none\! {
border-style: none !important;
}
.gl-rounded-pill {
border-radius: 0.75rem;
}
.gl-text-white {
color: #fff;
}
.gl-display-none {
display: none;
}
@ -1612,6 +1644,10 @@ svg.s16 {
.gl-pr-2 {
padding-right: 0.25rem;
}
.gl-py-1 {
padding-top: 0.125rem;
padding-bottom: 0.125rem;
}
.gl-ml-3 {
margin-left: 0.5rem;
}

View File

@ -238,9 +238,10 @@ module IssuesHelper
)
end
def group_issues_list_data(group, current_user, issues)
def group_issues_list_data(group, current_user, issues, projects)
common_issues_list_data(group, current_user).merge(
has_any_issues: issues.to_a.any?.to_s
has_any_issues: issues.to_a.any?.to_s,
has_any_projects: any_projects?(projects).to_s
)
end

View File

@ -28,7 +28,7 @@ module Routing
when 'groups'
"/namespace:#{group.id}"
when 'projects'
"/namespace:#{project.namespace.id}/project:#{project.id}"
"/namespace:#{project.namespace_id}/project:#{project.id}"
when 'root'
''
else
@ -44,7 +44,7 @@ module Routing
masked_url = "#{request.protocol}#{request.host_with_port}"
if request_params.has_key?(:project_id)
masked_url += "/namespace:#{project.namespace.id}/project:#{project.id}/-/#{namespace_type}"
masked_url += "/namespace:#{project.namespace_id}/project:#{project.id}/-/#{namespace_type}"
end
if request_params.has_key?(:id)

View File

@ -73,7 +73,6 @@ module TabHelper
# :action - One or more action names to check (optional).
# :path - A shorthand path, such as 'dashboard#index', to check (optional).
# :html_options - Extra options to be passed to the list element (optional).
# :unless - Callable object to skip rendering the 'active' class on `li` element (optional).
# block - An optional block that will become the contents of the returned
# `li` element.
#
@ -118,11 +117,6 @@ module TabHelper
# nav_link(path: 'admin/appearances#show') { "Hello"}
# # => '<li class="active">Hello</li>'
#
# # Shorthand path + unless
# # Add `active` class when TreeController is requested, except the `index` action.
# nav_link(controller: 'tree', unless: -> { action_name?('index') }) { "Hello" }
# # => '<li class="active">Hello</li>'
#
# # When `TreeController#index` is requested
# # => '<li>Hello</li>'
#
@ -151,8 +145,6 @@ module TabHelper
end
def active_nav_link?(options)
return false if options[:unless]&.call
controller = options.delete(:controller)
action = options.delete(:action)

View File

@ -12,6 +12,13 @@ module Ci
if Gitlab::Database.has_config?(:ci)
connects_to database: { writing: :ci, reading: :ci }
# TODO: Load Balancing messes with `CiDatabaseRecord`
# returning wrong connection. To be removed once merged:
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67773
def self.connection
retrieve_connection
end
end
end
end

View File

@ -3,7 +3,7 @@
module Projects
class OverwriteProjectService < BaseService
def execute(source_project)
return unless source_project && source_project.namespace == @project.namespace
return unless source_project && source_project.namespace_id == @project.namespace_id
start_time = ::Gitlab::Metrics::System.monotonic_time
@ -40,7 +40,7 @@ module Projects
duration = ::Gitlab::Metrics::System.monotonic_time - start_time
Gitlab::AppJsonLogger.info(class: self.class.name,
namespace_id: source_project.namespace.id,
namespace_id: source_project.namespace_id,
project_id: source_project.id,
duration_s: duration.to_f,
error: exception.class.name)

View File

@ -6,13 +6,9 @@
= link_to _("New group"), new_group_path, class: "gl-button btn btn-confirm", data: { testid: "new-group-button" }
.top-area
%ul.nav-links.mobile-separator.nav.nav-tabs
= nav_link(page: dashboard_groups_path) do
= link_to dashboard_groups_path, title: _("Your groups") do
Your groups
= nav_link(page: explore_groups_path) do
= link_to explore_groups_path, title: _("Explore public groups") do
Explore public groups
= gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
= gl_tab_link_to _("Your groups"), dashboard_groups_path
= gl_tab_link_to _("Explore public groups"), explore_groups_path
.nav-controls
= render 'shared/groups/search_form'
= render 'shared/groups/dropdown'

View File

@ -5,17 +5,19 @@
.group-home-panel
.row.mb-3
.home-panel-title-row.col-md-12.col-lg-6.d-flex
.avatar-container.rect-avatar.s64.home-panel-avatar.gl-mr-3.float-none
.avatar-container.rect-avatar.s64.home-panel-avatar.gl-flex-shrink-0.float-none{ class: 'gl-mr-3!' }
= group_icon(@group, class: 'avatar avatar-tile s64', width: 64, height: 64, itemprop: 'logo')
.d-flex.flex-column.flex-wrap.align-items-baseline
.d-inline-flex.align-items-baseline
%h1.home-panel-title.gl-mt-3.gl-mb-2{ itemprop: 'name' }
%h1.home-panel-title.gl-mt-3.gl-mb-2.gl-ml-3{ itemprop: 'name' }
= @group.name
%span.visibility-icon.text-secondary.gl-ml-2.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
= visibility_level_icon(@group.visibility_level, options: {class: 'icon'})
.home-panel-metadata.text-secondary
%span
= _("Group ID: %{group_id}") % { group_id: @group.id }
.home-panel-metadata.text-secondary.gl-font-base.gl-font-weight-normal.gl-line-height-normal
- if can?(current_user, :read_group, @group)
- button_class = "btn gl-button btn-sm btn-tertiary btn-default-tertiary home-panel-metadata"
- button_text = s_('GroupPage|Group ID: %{group_id}') % { group_id: @group.id }
= clipboard_button(title: s_('GroupPage|Copy group ID'), text: @group.id, hide_button_icon: true, button_text: button_text, class: button_class, qa_selector: 'group_id_content', itemprop: 'identifier')
- if current_user
%span.gl-ml-3
= render 'shared/members/access_request_links', source: @group

View File

@ -6,7 +6,7 @@
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@group.name} issues")
- if Feature.enabled?(:vue_issues_list, @group, default_enabled: :yaml)
.js-issues-list{ data: group_issues_list_data(@group, current_user, @issues) }
.js-issues-list{ data: group_issues_list_data(@group, current_user, @issues, @projects) }
- if @can_bulk_update
= render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
- else

View File

@ -12,8 +12,7 @@ When a pipeline job is about to run, GitLab generates a unique token and injects
You can use a GitLab CI/CD job token to authenticate with specific API endpoints:
- Packages:
- [Package Registry](../../user/packages/package_registry/index.md#use-gitlab-cicd-to-build-packages). To push to the
Package Registry, you can use [deploy tokens](../../user/project/deploy_tokens/index.md).
- [Package Registry](../../user/packages/package_registry/index.md#use-gitlab-cicd-to-build-packages).
- [Container Registry](../../user/packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd)
(the `$CI_REGISTRY_PASSWORD` is `$CI_JOB_TOKEN`).
- [Container Registry API](../../api/container_registry.md)

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
# Vault Authentication with GitLab OpenID Connect
# Vault Authentication with GitLab OpenID Connect **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22323) in GitLab 9.0

View File

@ -12,14 +12,14 @@ View and resolve abuse reports from GitLab users.
GitLab administrators can view and [resolve](#resolving-abuse-reports) abuse
reports in the Admin Area.
## Receiving notifications of abuse reports
## Receive notification of abuse reports by email
To receive notifications of new abuse reports by email, follow these steps:
To receive notifications of new abuse reports by email:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Reporting**.
1. Expand the **Abuse reports** section.
1. Provide an email address.
1. Provide an email address and select **Save changes**.
The notification email address can also be set and retrieved
[using the API](../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls).

View File

@ -20,7 +20,7 @@ A DAST job has two executing processes:
Enable the `DAST_DEBUG` CI/CD variable to debug scripts. This can help when troubleshooting the job,
and outputs statements indicating what percentage of the scan is complete.
For details on using variables, see [Overriding the DAST template](index.md#customizing-the-dast-settings).
For details on using variables, see [Overriding the DAST template](index.md#customize-dast-settings).
Debug mode of the ZAP server can be enabled using the `DAST_ZAP_LOG_CONFIGURATION` variable.
The following table outlines examples of values that can be set and the effect that they have on the output that is logged.

View File

@ -483,6 +483,13 @@ When using `DAST_PATHS` and `DAST_PATHS_FILE`, note the following:
To perform a [full scan](#full-scan) on the listed paths, use the `DAST_FULL_SCAN_ENABLED` CI/CD variable.
### List URLs scanned
When DAST completes scanning, the merge request page states the number of URLs scanned.
Click **View details** to view the web console output which includes the list of scanned URLs.
![DAST Widget](img/dast_urls_scanned_v12_10.png)
### View details of a vulnerability detected by DAST
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36332) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1.
@ -515,15 +522,20 @@ To view details of vulnerabilities detected by DAST:
| Links | Links to further details of the detected vulnerability. |
| Solution | Details of a recommended solution to the vulnerability (optional). |
### Customizing the DAST settings
## Customize DAST settings
You can customize the behavior of DAST using both CI/CD variables and command-line options. Use of CI/CD
variables overrides the values contained in the DAST template.
### Customize DAST using CI/CD variables
WARNING:
Beginning in GitLab 13.0, the use of [`only` and `except`](../../../ci/yaml/index.md#only--except)
is no longer supported. When overriding the template, you must use [`rules`](../../../ci/yaml/index.md#rules) instead.
is no longer supported. You must use [`rules`](../../../ci/yaml/index.md#rules) instead.
The DAST settings can be changed through CI/CD variables by using the
[`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`.
These variables are documented in [available variables](#available-cicd-variables).
[`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`. For details of
all DAST CI/CD variables, read [Available CI/CD variables](#available-cicd-variables).
For example:
@ -539,10 +551,10 @@ variables:
Because the template is [evaluated before](../../../ci/yaml/index.md#include) the pipeline
configuration, the last mention of the variable takes precedence.
#### Enabling and disabling rules
#### Enable or disable rules
A complete list of the rules that DAST uses to scan for vulnerabilities can be
found in the [ZAP docs](https://www.zaproxy.org/docs/alerts/).
found in the [ZAP documentation](https://www.zaproxy.org/docs/alerts/).
`DAST_EXCLUDE_RULES` disables the rules with the given IDs.
@ -559,7 +571,7 @@ can be found in [exclude_rules.yml](https://gitlab.com/gitlab-org/security-produ
The lists for `DAST_EXCLUDE_RULES` and `DAST_ONLY_INCLUDE_RULES` **must** be enclosed in double
quotes (`"`), otherwise they are interpreted as numeric values.
### Hide sensitive information
#### Hide sensitive information
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36332) in GitLab 13.1.
@ -573,7 +585,105 @@ authorization credentials. By default, the following headers are masked:
Using the [`DAST_MASK_HTTP_HEADERS` CI/CD variable](#available-cicd-variables), you can list the
headers whose values you want masked. For details on how to mask headers, see
[Customizing the DAST settings](#customizing-the-dast-settings).
[Customizing the DAST settings](#customize-dast-settings).
#### Available CI/CD variables
These CI/CD variables are specific to DAST. They can be used to customize the behavior of DAST to your requirements.
| CI/CD variable | Type | Description |
|:-------------------------------------------------|:--------------|:------------------------------|
| `DAST_ADVERTISE_SCAN` | boolean | Set to `true` to add a `Via` header to every request sent, advertising that the request was sent as part of a GitLab DAST scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334947) in GitLab 14.1. |
| `DAST_AGGREGATE_VULNERABILITIES` | boolean | Vulnerability aggregation is set to `true` by default. To disable this feature and see each vulnerability individually set to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254043) in GitLab 14.0. |
| `DAST_API_HOST_OVERRIDE` <sup>1</sup> | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080`. |
| `DAST_API_OPENAPI` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. The variable `DAST_WEBSITE` must be specified if this is omitted. |
| `DAST_API_SPECIFICATION` <sup>1</sup> | URL or string | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/290241) in GitLab 13.12 and replaced by `DAST_API_OPENAPI`. To be removed in GitLab 15.0. The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. The variable `DAST_WEBSITE` must be specified if this is omitted. |
| `DAST_AUTH_REPORT` <sup>2</sup> | boolean | Used in combination with exporting the `gl-dast-debug-auth-report.html` artifact to aid in debugging authentication issues. |
| `DAST_AUTH_EXCLUDE_URLS` <sup>2</sup> | URLs | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289959)** in GitLab 14.0. Replaced by `DAST_EXCLUDE_URLS`. The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
| `DAST_AUTH_URL` <sup>1,2</sup> | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. Example: `https://login.example.com`. |
| `DAST_AUTH_VERIFICATION_LOGIN_FORM` <sup>2</sup> | boolean | Verifies successful authentication by checking for the lack of a login form once the login form has been submitted. |
| `DAST_AUTH_VERIFICATION_SELECTOR` <sup>2</sup> | selector | Verifies successful authentication by checking for presence of a selector once the login form has been submitted. Example: `css:.user-photo`. |
| `DAST_AUTH_VERIFICATION_URL` <sup>1,2</sup> | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST exits if it cannot access the URL. Example: `"http://example.com/loggedin_page"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8. |
| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false`. |
| `DAST_BROWSER_PATH_TO_LOGIN_FORM` <sup>1,2</sup> | selector | Comma-separated list of selectors that will be clicked on prior to attempting to enter `DAST_USERNAME` and `DAST_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326633) in GitLab 14.1. |
| `DAST_DEBUG` <sup>1</sup> | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). For example, `HTTP Parameter Override` has a rule ID of `10026`. Cannot be used when `DAST_ONLY_INCLUDE_RULES` is set. **Note:** In earlier versions of GitLab the excluded rules were executed but vulnerabilities they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
| `DAST_EXCLUDE_URLS` <sup>1,2</sup> | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. Example, `http://example.com/sign-out`. |
| `DAST_FIRST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when clicked submits the username form of a multi-page login process. For example, `css:button[type='user-submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/293595)** in GitLab 14.0. Set to `true` to require domain validation when running DAST full scans. Not supported for API scans. Default: `false` |
| `DAST_FULL_SCAN_ENABLED` <sup>1</sup> | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_MARKDOWN_REPORT` | string | The filename of the Markdown report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_MASK_HTTP_HEADERS` | string | Comma-separated list of request and response headers to be masked (GitLab 13.1). Must contain **all** headers to be masked. Refer to [list of headers that are masked by default](#hide-sensitive-information). |
| `DAST_MAX_URLS_PER_VULNERABILITY` | number | The maximum number of URLs reported for a single vulnerability. `DAST_MAX_URLS_PER_VULNERABILITY` is set to `50` by default. To list all the URLs set to `0`. [Introduced](https://gitlab.com/gitlab-org/security-products/dast/-/merge_requests/433) in GitLab 13.12. |
| `DAST_ONLY_INCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to configure the scan to run only them. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). Cannot be used when `DAST_EXCLUDE_RULES` is set. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250651) in GitLab 13.12. |
| `DAST_PASSWORD` <sup>1,2</sup> | string | The password to authenticate to in the website. Example: `P@55w0rd!` |
| `DAST_PASSWORD_FIELD` <sup>1,2</sup> | string | The selector of password field at the sign-in HTML form. Example: `id:password` |
| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
| `DAST_REQUEST_HEADERS` <sup>1</sup> | string | Set to a comma-separated list of request header names and values. Headers are added to every request made by DAST. For example, `Cache-control: no-cache,User-Agent: DAST/1.0` |
| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. |
| `DAST_SPIDER_MINS` <sup>1</sup> | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` is reset to `http://test.site` before scan. Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. |
| `DAST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when clicked submits the login form or the password form of a multi-page login process. For example, `css:button[type='submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_TARGET_AVAILABILITY_TIMEOUT` <sup>1</sup> | number | Time limit in seconds to wait for target availability. |
| `DAST_USE_AJAX_SPIDER` <sup>1</sup> | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_USERNAME` <sup>1,2</sup> | string | The username to authenticate to in the website. Example: `admin` |
| `DAST_USERNAME_FIELD` <sup>1,2</sup> | string | The selector of username field at the sign-in HTML form. Example: `name:username` |
| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_WEBSITE` <sup>1</sup> | URL | The URL of the website to scan. The variable `DAST_API_OPENAPI` must be specified if this is omitted. |
| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. Example: `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
| `SECURE_ANALYZERS_PREFIX` | URL | Set the Docker registry base address from which to download the analyzer. |
1. Available to an on-demand DAST scan.
1. Used for authentication.
### Customize DAST using command-line options
Not all DAST configuration is available via CI/CD variables. To find out all
possible options, run the following configuration.
Available command-line options are printed to the job log:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- /analyze --help
```
You must then overwrite the `script` command to pass in the appropriate
argument. For example, vulnerability definitions in alpha can be included with
`-a`. The following configuration includes those definitions:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- /analyze -a -t $DAST_WEBSITE
```
### Custom ZAProxy configuration
The ZAProxy server contains many [useful configurable values](https://gitlab.com/gitlab-org/gitlab/-/issues/36437#note_245801885).
Many key/values for `-config` remain undocumented, but there is an untested list of
[possible keys](https://gitlab.com/gitlab-org/gitlab/-/issues/36437#note_244981023).
Note that these options are not supported by DAST, and may break the DAST scan
when used. An example of how to rewrite the Authorization header value with `TOKEN` follows:
```yaml
include:
template: DAST.gitlab-ci.yml
variables:
DAST_ZAP_CLI_OPTIONS: "-config replacer.full_list(0).description=auth -config replacer.full_list(0).enabled=true -config replacer.full_list(0).matchtype=REQ_HEADER -config replacer.full_list(0).matchstr=Authorization -config replacer.full_list(0).regex=false -config replacer.full_list(0).replacement=TOKEN"
```
## Authentication
@ -747,59 +857,6 @@ dast:
when: always
```
## Available CI/CD variables
These CI/CD variables are specific to DAST. They can be used to customize the behavior of DAST to your requirements.
| CI/CD variable | Type | Description |
|:-------------------------------------------------|:--------------|:------------------------------|
| `DAST_ADVERTISE_SCAN` | boolean | Set to `true` to add a `Via` header to every request sent, advertising that the request was sent as part of a GitLab DAST scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334947) in GitLab 14.1. |
| `DAST_AGGREGATE_VULNERABILITIES` | boolean | Vulnerability aggregation is set to `true` by default. To disable this feature and see each vulnerability individually set to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254043) in GitLab 14.0. |
| `DAST_API_HOST_OVERRIDE` <sup>1</sup> | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080`. |
| `DAST_API_OPENAPI` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. The variable `DAST_WEBSITE` must be specified if this is omitted. |
| `DAST_API_SPECIFICATION` <sup>1</sup> | URL or string | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/290241) in GitLab 13.12 and replaced by `DAST_API_OPENAPI`. To be removed in GitLab 15.0. The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. The variable `DAST_WEBSITE` must be specified if this is omitted. |
| `DAST_AUTH_REPORT` <sup>2</sup> | boolean | Used in combination with exporting the `gl-dast-debug-auth-report.html` artifact to aid in debugging authentication issues. |
| `DAST_AUTH_EXCLUDE_URLS` <sup>2</sup> | URLs | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289959)** in GitLab 14.0. Replaced by `DAST_EXCLUDE_URLS`. The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
| `DAST_AUTH_URL` <sup>1,2</sup> | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. Example: `https://login.example.com`. |
| `DAST_AUTH_VERIFICATION_LOGIN_FORM` <sup>2</sup> | boolean | Verifies successful authentication by checking for the lack of a login form once the login form has been submitted. |
| `DAST_AUTH_VERIFICATION_SELECTOR` <sup>2</sup> | selector | Verifies successful authentication by checking for presence of a selector once the login form has been submitted. Example: `css:.user-photo`. |
| `DAST_AUTH_VERIFICATION_URL` <sup>1,2</sup> | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST exits if it cannot access the URL. Example: `"http://example.com/loggedin_page"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8. |
| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false`. |
| `DAST_BROWSER_PATH_TO_LOGIN_FORM` <sup>1,2</sup> | selector | Comma-separated list of selectors that will be clicked on prior to attempting to enter `DAST_USERNAME` and `DAST_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326633) in GitLab 14.1. |
| `DAST_DEBUG` <sup>1</sup> | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. The whole list **must** be enclosed in double quotes (`"`). Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). For example, `HTTP Parameter Override` has a rule ID of `10026`. Cannot be used when `DAST_ONLY_INCLUDE_RULES` is set. **Note:** In earlier versions of GitLab the excluded rules were executed but vulnerabilities they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
| `DAST_EXCLUDE_URLS` <sup>1,2</sup> | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. Example, `http://example.com/sign-out`. |
| `DAST_FIRST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when clicked submits the username form of a multi-page login process. For example, `css:button[type='user-submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/293595)** in GitLab 14.0. Set to `true` to require domain validation when running DAST full scans. Not supported for API scans. Default: `false` |
| `DAST_FULL_SCAN_ENABLED` <sup>1</sup> | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_MARKDOWN_REPORT` | string | The filename of the Markdown report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_MASK_HTTP_HEADERS` | string | Comma-separated list of request and response headers to be masked (GitLab 13.1). Must contain **all** headers to be masked. Refer to [list of headers that are masked by default](#hide-sensitive-information). |
| `DAST_MAX_URLS_PER_VULNERABILITY` | number | The maximum number of URLs reported for a single vulnerability. `DAST_MAX_URLS_PER_VULNERABILITY` is set to `50` by default. To list all the URLs set to `0`. [Introduced](https://gitlab.com/gitlab-org/security-products/dast/-/merge_requests/433) in GitLab 13.12. |
| `DAST_ONLY_INCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to configure the scan to run only them. The whole list **must** be enclosed in double quotes (`"`). Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). Cannot be used when `DAST_EXCLUDE_RULES` is set. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250651) in GitLab 13.12. |
| `DAST_PASSWORD` <sup>1,2</sup> | string | The password to authenticate to in the website. Example: `P@55w0rd!` |
| `DAST_PASSWORD_FIELD` <sup>1,2</sup> | string | The selector of password field at the sign-in HTML form. Example: `id:password` |
| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
| `DAST_REQUEST_HEADERS` <sup>1</sup> | string | Set to a comma-separated list of request header names and values. Headers are added to every request made by DAST. For example, `Cache-control: no-cache,User-Agent: DAST/1.0` |
| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. |
| `DAST_SPIDER_MINS` <sup>1</sup> | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` is reset to `http://test.site` before scan. Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. |
| `DAST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when clicked submits the login form or the password form of a multi-page login process. For example, `css:button[type='submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_TARGET_AVAILABILITY_TIMEOUT` <sup>1</sup> | number | Time limit in seconds to wait for target availability. |
| `DAST_USE_AJAX_SPIDER` <sup>1</sup> | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_USERNAME` <sup>1,2</sup> | string | The username to authenticate to in the website. Example: `admin` |
| `DAST_USERNAME_FIELD` <sup>1,2</sup> | string | The selector of username field at the sign-in HTML form. Example: `name:username` |
| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_WEBSITE` <sup>1</sup> | URL | The URL of the website to scan. The variable `DAST_API_OPENAPI` must be specified if this is omitted. |
| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. Example: `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
| `SECURE_ANALYZERS_PREFIX` | URL | Set the Docker registry base address from which to download the analyzer. |
1. Available to an on-demand DAST scan.
1. Used for authentication.
### Selectors
Selectors are used by CI/CD variables to specify the location of an element displayed on a page in a browser.
@ -848,51 +905,6 @@ When using selectors to locate specific fields we recommend you avoid searching
- XPath searches as they are less performant than other selector searches.
- Unscoped searches, such as those beginning with `css:*` and `xpath://*`.
### DAST command-line options
Not all DAST configuration is available via CI/CD variables. To find out all
possible options, run the following configuration.
Available command-line options are printed to the job log:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- /analyze --help
```
You must then overwrite the `script` command to pass in the appropriate
argument. For example, vulnerability definitions in alpha can be included with
`-a`. The following configuration includes those definitions:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- /analyze -a -t $DAST_WEBSITE
```
### Custom ZAProxy configuration
The ZAProxy server contains many [useful configurable values](https://gitlab.com/gitlab-org/gitlab/-/issues/36437#note_245801885).
Many key/values for `-config` remain undocumented, but there is an untested list of
[possible keys](https://gitlab.com/gitlab-org/gitlab/-/issues/36437#note_244981023).
Note that these options are not supported by DAST, and may break the DAST scan
when used. An example of how to rewrite the Authorization header value with `TOKEN` follows:
```yaml
include:
template: DAST.gitlab-ci.yml
variables:
DAST_ZAP_CLI_OPTIONS: "-config replacer.full_list(0).description=auth -config replacer.full_list(0).enabled=true -config replacer.full_list(0).matchtype=REQ_HEADER -config replacer.full_list(0).matchstr=Authorization -config replacer.full_list(0).regex=false -config replacer.full_list(0).replacement=TOKEN"
```
### Bleeding-edge vulnerability definitions
ZAP first creates rules in the `alpha` class. After a testing period with
@ -1306,7 +1318,7 @@ If a scanner profile is linked to a security policy, a user cannot delete the pr
page. See [Scan Execution Policies](../policies/index.md#scan-execution-policy-editor)
for more information.
### Auditing
## Auditing
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217872) in GitLab 14.1.
@ -1318,13 +1330,6 @@ and DAST site profiles are included in the [audit log](../../../administration/a
The DAST tool outputs a report file in JSON format by default. However, this tool can also generate reports in
Markdown, HTML, and XML. For more information, see the [schema for DAST reports](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dast-report-format.json).
### List of URLs scanned
When DAST completes scanning, the merge request page states the number of URLs scanned.
Click **View details** to view the web console output which includes the list of scanned URLs.
![DAST Widget](img/dast_urls_scanned_v12_10.png)
### JSON
WARNING:

View File

@ -7,7 +7,7 @@ module Gitlab
grouped_items = issuables.group_by do |issuable|
if issuable.project.id == project.id
:project_ref
elsif issuable.project.namespace.id == project.namespace.id
elsif issuable.project.namespace_id == project.namespace_id
:namespace_ref
else
:full_ref

View File

@ -3710,6 +3710,9 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
msgid "An error occurred while loading projects."
msgstr ""
msgid "An error occurred while loading the Needs tab."
msgstr ""
@ -15922,9 +15925,6 @@ msgstr ""
msgid "Group ID"
msgstr ""
msgid "Group ID: %{group_id}"
msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
@ -16099,6 +16099,12 @@ msgstr ""
msgid "GroupImport|Unable to process group import file"
msgstr ""
msgid "GroupPage|Copy group ID"
msgstr ""
msgid "GroupPage|Group ID: %{group_id}"
msgstr ""
msgid "GroupRoadmap|%{dateWord} No end date"
msgstr ""
@ -22705,6 +22711,9 @@ msgstr ""
msgid "New issue"
msgstr ""
msgid "New issue in %{project}"
msgstr ""
msgid "New issue title"
msgstr ""
@ -30553,6 +30562,9 @@ msgstr ""
msgid "Select project to choose zone"
msgstr ""
msgid "Select project to create issue"
msgstr ""
msgid "Select projects"
msgstr ""

View File

@ -18,6 +18,10 @@ RSpec.describe 'Startup CSS fixtures', type: :controller do
let(:project) { create(:project, :public, :repository, description: 'Code and stuff', creator: user) }
before do
# We want vNext badge to be included and com/canary don't remove/hide any other elements.
# This is why we're turning com and canary on by default for now.
allow(Gitlab).to receive(:com?).and_return(true)
allow(Gitlab).to receive(:canary?).and_return(true)
sign_in(user)
end

View File

@ -24,6 +24,7 @@ import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
import IssuableList from '~/issuable_list/components/issuable_list_root.vue';
import { IssuableListTabs, IssuableStates } from '~/issuable_list/constants';
import IssuesListApp from '~/issues_list/components/issues_list_app.vue';
import NewIssueDropdown from '~/issues_list/components/new_issue_dropdown.vue';
import {
CREATED_DESC,
DUE_DATE_OVERDUE,
@ -65,6 +66,7 @@ describe('IssuesListApp component', () => {
exportCsvPath: 'export/csv/path',
fullPath: 'path/to/project',
hasAnyIssues: true,
hasAnyProjects: true,
hasBlockedIssuesFeature: true,
hasIssueWeightsFeature: true,
hasIterationsFeature: true,
@ -93,6 +95,7 @@ describe('IssuesListApp component', () => {
const findGlEmptyState = () => wrapper.findComponent(GlEmptyState);
const findGlLink = () => wrapper.findComponent(GlLink);
const findIssuableList = () => wrapper.findComponent(IssuableList);
const findNewIssueDropdown = () => wrapper.findComponent(NewIssueDropdown);
const mountComponent = ({
provide = {},
@ -190,10 +193,7 @@ describe('IssuesListApp component', () => {
beforeEach(() => {
setWindowLocation(search);
wrapper = mountComponent({
provide: { isSignedIn: true },
mountFn: mount,
});
wrapper = mountComponent({ provide: { isSignedIn: true }, mountFn: mount });
jest.runOnlyPendingTimers();
});
@ -208,7 +208,7 @@ describe('IssuesListApp component', () => {
describe('when user is not signed in', () => {
it('does not render', () => {
wrapper = mountComponent({ provide: { isSignedIn: false } });
wrapper = mountComponent({ provide: { isSignedIn: false }, mountFn: mount });
expect(findCsvImportExportButtons().exists()).toBe(false);
});
@ -216,7 +216,7 @@ describe('IssuesListApp component', () => {
describe('when in a group context', () => {
it('does not render', () => {
wrapper = mountComponent({ provide: { isProject: false } });
wrapper = mountComponent({ provide: { isProject: false }, mountFn: mount });
expect(findCsvImportExportButtons().exists()).toBe(false);
});
@ -231,7 +231,7 @@ describe('IssuesListApp component', () => {
});
it('does not render when user does not have permissions', () => {
wrapper = mountComponent({ provide: { canBulkUpdate: false } });
wrapper = mountComponent({ provide: { canBulkUpdate: false }, mountFn: mount });
expect(findGlButtons().filter((button) => button.text() === 'Edit issues')).toHaveLength(0);
});
@ -258,11 +258,25 @@ describe('IssuesListApp component', () => {
});
it('does not render when user does not have permissions', () => {
wrapper = mountComponent({ provide: { showNewIssueLink: false } });
wrapper = mountComponent({ provide: { showNewIssueLink: false }, mountFn: mount });
expect(findGlButtons().filter((button) => button.text() === 'New issue')).toHaveLength(0);
});
});
describe('new issue split dropdown', () => {
it('does not render in a project context', () => {
wrapper = mountComponent({ provide: { isProject: true }, mountFn: mount });
expect(findNewIssueDropdown().exists()).toBe(false);
});
it('renders in a group context', () => {
wrapper = mountComponent({ provide: { isProject: false }, mountFn: mount });
expect(findNewIssueDropdown().exists()).toBe(true);
});
});
});
describe('initial url params', () => {

View File

@ -0,0 +1,131 @@
import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import NewIssueDropdown from '~/issues_list/components/new_issue_dropdown.vue';
import searchProjectsQuery from '~/issues_list/queries/search_projects.query.graphql';
import { DASH_SCOPE, joinPaths } from '~/lib/utils/url_utility';
import {
emptySearchProjectsQueryResponse,
project1,
project2,
searchProjectsQueryResponse,
} from '../mock_data';
describe('NewIssueDropdown component', () => {
let wrapper;
const localVue = createLocalVue();
localVue.use(VueApollo);
const mountComponent = ({
search = '',
queryResponse = searchProjectsQueryResponse,
mountFn = shallowMount,
} = {}) => {
const requestHandlers = [[searchProjectsQuery, jest.fn().mockResolvedValue(queryResponse)]];
const apolloProvider = createMockApollo(requestHandlers);
return mountFn(NewIssueDropdown, {
localVue,
apolloProvider,
provide: {
fullPath: 'mushroom-kingdom',
},
data() {
return { search };
},
});
};
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findInput = () => wrapper.findComponent(GlSearchBoxByType);
const showDropdown = async () => {
findDropdown().vm.$emit('shown');
await wrapper.vm.$apollo.queries.projects.refetch();
jest.runOnlyPendingTimers();
};
afterEach(() => {
wrapper.destroy();
});
it('renders a split dropdown', () => {
wrapper = mountComponent();
expect(findDropdown().props('split')).toBe(true);
});
it('renders a label for the dropdown toggle button', () => {
wrapper = mountComponent();
expect(findDropdown().attributes('toggle-text')).toBe(NewIssueDropdown.i18n.toggleButtonLabel);
});
it('focuses on input when dropdown is shown', async () => {
wrapper = mountComponent({ mountFn: mount });
const inputSpy = jest.spyOn(findInput().vm, 'focusInput');
await showDropdown();
expect(inputSpy).toHaveBeenCalledTimes(1);
});
it('renders expected dropdown items', async () => {
wrapper = mountComponent({ mountFn: mount });
await showDropdown();
const listItems = wrapper.findAll('li');
expect(listItems.at(0).text()).toBe(project1.nameWithNamespace);
expect(listItems.at(1).text()).toBe(project2.nameWithNamespace);
});
it('renders `No matches found` when there are no matches', async () => {
wrapper = mountComponent({
search: 'no matches',
queryResponse: emptySearchProjectsQueryResponse,
mountFn: mount,
});
await showDropdown();
expect(wrapper.find('li').text()).toBe(NewIssueDropdown.i18n.noMatchesFound);
});
describe('when no project is selected', () => {
beforeEach(() => {
wrapper = mountComponent();
});
it('dropdown button is not a link', () => {
expect(findDropdown().attributes('split-href')).toBeUndefined();
});
it('displays default text on the dropdown button', () => {
expect(findDropdown().props('text')).toBe(NewIssueDropdown.i18n.defaultDropdownText);
});
});
describe('when a project is selected', () => {
beforeEach(async () => {
wrapper = mountComponent({ mountFn: mount });
await showDropdown();
wrapper.findComponent(GlDropdownItem).vm.$emit('click', project1);
});
it('dropdown button is a link', () => {
const href = joinPaths(project1.webUrl, DASH_SCOPE, 'issues/new');
expect(findDropdown().attributes('split-href')).toBe(href);
});
it('displays project name on the dropdown button', () => {
expect(findDropdown().props('text')).toBe(`New issue in ${project1.name}`);
});
});
});

View File

@ -221,3 +221,37 @@ export const urlParamsWithSpecialValues = {
epic_id: 'None',
weight: 'None',
};
export const project1 = {
id: 'gid://gitlab/Group/26',
name: 'Super Mario Project',
nameWithNamespace: 'Mushroom Kingdom / Super Mario Project',
webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/super-mario-project',
};
export const project2 = {
id: 'gid://gitlab/Group/59',
name: 'Mario Kart Project',
nameWithNamespace: 'Mushroom Kingdom / Mario Kart Project',
webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/mario-kart-project',
};
export const searchProjectsQueryResponse = {
data: {
group: {
projects: {
nodes: [project1, project2],
},
},
},
};
export const emptySearchProjectsQueryResponse = {
data: {
group: {
projects: {
nodes: [],
},
},
},
};

View File

@ -354,6 +354,7 @@ RSpec.describe IssuesHelper do
let(:group) { create(:group) }
let(:current_user) { double.as_null_object }
let(:issues) { [] }
let(:projects) { [] }
it 'returns expected result' do
allow(helper).to receive(:current_user).and_return(current_user)
@ -367,13 +368,14 @@ RSpec.describe IssuesHelper do
empty_state_svg_path: '#',
full_path: group.full_path,
has_any_issues: issues.to_a.any?.to_s,
has_any_projects: any_projects?(projects).to_s,
is_signed_in: current_user.present?.to_s,
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
rss_path: '#',
sign_in_path: new_user_session_path
}
expect(helper.group_issues_list_data(group, current_user, issues)).to include(expected)
expect(helper.group_issues_list_data(group, current_user, issues, projects)).to include(expected)
end
end

View File

@ -6,6 +6,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
let_it_be(:group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:subproject) { create(:project, group: subgroup) }
let_it_be(:issue) { create(:issue, project: project) }
let(:merge_request) { create(:merge_request, source_project: project) }
@ -56,16 +57,16 @@ RSpec.describe ::Routing::PseudonymizationHelper do
end
context 'with controller for groups with subgroups and project' do
let(:masked_url) { "http://test.host/namespace:#{subgroup.id}/project:#{project.id}"}
let(:masked_url) { "http://test.host/namespace:#{subgroup.id}/project:#{subproject.id}"}
before do
allow(helper).to receive(:group).and_return(subgroup)
allow(helper.project).to receive(:namespace).and_return(subgroup)
allow(helper).to receive(:project).and_return(subproject)
allow(Rails.application.routes).to receive(:recognize_path).and_return({
controller: 'projects',
action: 'show',
namespace_id: subgroup.name,
id: project.name
id: subproject.name
})
end

View File

@ -24,16 +24,6 @@ RSpec.describe Gitlab::Database::SchemaMigrations::Context do
end
context 'multiple databases', :reestablished_active_record_base do
let(:connection_class) do
Class.new(::ApplicationRecord) do
self.abstract_class = true
def self.name
'Gitlab::Database::SchemaMigrations::Context::TestConnection'
end
end
end
before do
connection_class.establish_connection(
ActiveRecord::Base
@ -44,10 +34,6 @@ RSpec.describe Gitlab::Database::SchemaMigrations::Context do
)
end
after do
connection_class.remove_connection
end
context 'when `schema_migrations_path` is configured as string' do
let(:configuration_overrides) do
{ "schema_migrations_path" => "db/ci_schema_migrations" }

View File

@ -17,32 +17,9 @@ RSpec.configure do |config|
delete_from_all_tables!(except: ['work_item_types'])
# Postgres maximum number of columns in a table is 1600 (https://github.com/postgres/postgres/blob/de41869b64d57160f58852eab20a27f248188135/src/include/access/htup_details.h#L23-L47).
# And since:
# "The DROP COLUMN form does not physically remove the column, but simply makes
# it invisible to SQL operations. Subsequent insert and update operations in the
# table will store a null value for the column. Thus, dropping a column is quick
# but it will not immediately reduce the on-disk size of your table, as the space
# occupied by the dropped column is not reclaimed.
# The space will be reclaimed over time as existing rows are updated."
# according to https://www.postgresql.org/docs/current/sql-altertable.html.
# We drop and recreate the database if any table has more than 1200 columns, just to be safe.
max_allowed_columns = 1200
tables_with_more_than_allowed_columns =
ApplicationRecord.connection.execute("SELECT attrelid::regclass::text AS table, COUNT(*) AS column_count FROM pg_attribute GROUP BY attrelid HAVING COUNT(*) > #{max_allowed_columns}")
if tables_with_more_than_allowed_columns.any?
tables_with_more_than_allowed_columns.each do |result|
puts "The #{result['table']} table has #{result['column_count']} columns."
end
puts "Recreating the database"
start = Gitlab::Metrics::System.monotonic_time
ActiveRecord::Tasks::DatabaseTasks.drop_current
ActiveRecord::Tasks::DatabaseTasks.create_current
ActiveRecord::Tasks::DatabaseTasks.load_schema_current
ActiveRecord::Tasks::DatabaseTasks.migrate
puts "Database re-creation done in #{Gitlab::Metrics::System.monotonic_time - start}"
if any_connection_class_with_more_than_allowed_columns?
recreate_all_databases!
end
end

View File

@ -2,7 +2,7 @@
module DbCleaner
def all_connection_classes
::ActiveRecord::Base.connection_handler.connection_pool_names.map(&:constantize)
::BeforeAllAdapter.all_connection_classes
end
def delete_from_all_tables!(except: [])
@ -20,6 +20,79 @@ module DbCleaner
DatabaseCleaner[:active_record, { connection: connection_class }]
end
end
def any_connection_class_with_more_than_allowed_columns?
all_connection_classes.any? do |connection_class|
more_than_allowed_columns?(connection_class)
end
end
def more_than_allowed_columns?(connection_class)
# Postgres maximum number of columns in a table is 1600 (https://github.com/postgres/postgres/blob/de41869b64d57160f58852eab20a27f248188135/src/include/access/htup_details.h#L23-L47).
# And since:
# "The DROP COLUMN form does not physically remove the column, but simply makes
# it invisible to SQL operations. Subsequent insert and update operations in the
# table will store a null value for the column. Thus, dropping a column is quick
# but it will not immediately reduce the on-disk size of your table, as the space
# occupied by the dropped column is not reclaimed.
# The space will be reclaimed over time as existing rows are updated."
# according to https://www.postgresql.org/docs/current/sql-altertable.html.
# We drop and recreate the database if any table has more than 1200 columns, just to be safe.
max_allowed_columns = 1200
tables_with_more_than_allowed_columns = connection_class.connection.execute(<<-SQL)
SELECT attrelid::regclass::text AS table, COUNT(*) AS column_count
FROM pg_attribute
GROUP BY attrelid
HAVING COUNT(*) > #{max_allowed_columns}
SQL
tables_with_more_than_allowed_columns.each do |result|
puts "The #{result['table']} (#{connection_class.connection_db_config.name}) table has #{result['column_count']} columns."
end
tables_with_more_than_allowed_columns.any?
end
def recreate_all_databases!
start = Gitlab::Metrics::System.monotonic_time
puts "Recreating the database"
force_disconnect_all_connections!
ActiveRecord::Tasks::DatabaseTasks.drop_current
ActiveRecord::Tasks::DatabaseTasks.create_current
ActiveRecord::Tasks::DatabaseTasks.load_schema_current
# Migrate each database individually
with_reestablished_active_record_base do
all_connection_classes.each do |connection_class|
ActiveRecord::Base.establish_connection(connection_class.connection_db_config)
ActiveRecord::Tasks::DatabaseTasks.migrate
end
end
puts "Databases re-creation done in #{Gitlab::Metrics::System.monotonic_time - start}"
end
def force_disconnect_all_connections!
all_connection_classes.each do |connection_class|
# We use `connection_pool` to avoid going through
# Load Balancer since it does retry ops
pool = connection_class.connection_pool
# Force disconnect https://www.cybertec-postgresql.com/en/terminating-database-connections-in-postgresql/
pool.connection.execute(<<-SQL)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = #{pool.connection.quote(pool.db_config.database)}
AND pid != pg_backend_pid();
SQL
connection_class.connection_pool.disconnect!
end
end
end
DbCleaner.prepend_mod_with('DbCleaner')