Commit 141902c0 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 209bd8cf
<script> <script>
import getJiraProjects from '../queries/getJiraProjects.query.graphql'; import getJiraProjects from '../queries/getJiraProjects.query.graphql';
import JiraImportSetup from './jira_import_setup.vue';
export default { export default {
name: 'JiraImportApp', name: 'JiraImportApp',
components: {
JiraImportSetup,
},
props: { props: {
isJiraConfigured: {
type: Boolean,
required: true,
},
projectPath: { projectPath: {
type: String, type: String,
required: true, required: true,
}, },
setupIllustration: {
type: String,
required: true,
},
}, },
apollo: { apollo: {
getJiraImports: { getJiraImports: {
...@@ -18,11 +30,17 @@ export default { ...@@ -18,11 +30,17 @@ export default {
}; };
}, },
update: data => data.project.jiraImports, update: data => data.project.jiraImports,
skip() {
return !this.isJiraConfigured;
},
}, },
}, },
}; };
</script> </script>
<template> <template>
<div></div> <div>
<jira-import-setup v-if="!isJiraConfigured" :illustration="setupIllustration" />
<div v-else></div>
</div>
</template> </template>
<script>
export default {
name: 'JiraImportSetup',
props: {
illustration: {
type: String,
required: true,
},
},
};
</script>
<template>
<div class="empty-state">
<div class="svg-content">
<img :src="illustration" :alt="__('Set up Jira Integration illustration')" />
</div>
<div class="text-content d-flex flex-column align-items-center">
<p>{{ __('You will first need to set up Jira Integration to use this feature.') }}</p>
<a class="btn btn-success" href="../services/jira/edit">
{{ __('Set up Jira Integration') }}
</a>
</div>
</div>
</template>
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import App from './components/jira_import_app.vue'; import App from './components/jira_import_app.vue';
Vue.use(VueApollo); Vue.use(VueApollo);
...@@ -23,7 +24,9 @@ export default function mountJiraImportApp() { ...@@ -23,7 +24,9 @@ export default function mountJiraImportApp() {
render(createComponent) { render(createComponent) {
return createComponent(App, { return createComponent(App, {
props: { props: {
isJiraConfigured: parseBoolean(el.dataset.isJiraConfigured),
projectPath: el.dataset.projectPath, projectPath: el.dataset.projectPath,
setupIllustration: el.dataset.setupIllustration,
}, },
}); });
}, },
......
import customMetrics from '~/custom_metrics';
document.addEventListener('DOMContentLoaded', customMetrics);
import customMetrics from '~/custom_metrics';
document.addEventListener('DOMContentLoaded', customMetrics);
...@@ -63,15 +63,6 @@ ...@@ -63,15 +63,6 @@
list-style: none; list-style: none;
padding: 0 1px; padding: 0 1px;
margin: 0; margin: 0;
.license-item {
line-height: $gl-padding-32;
.license-packages {
font-size: $label-font-size;
}
}
} }
.report-block-list-icon { .report-block-list-icon {
......
...@@ -7,6 +7,7 @@ module Projects ...@@ -7,6 +7,7 @@ module Projects
before_action :jira_integration_configured? before_action :jira_integration_configured?
def show def show
@is_jira_configured = @project.jira_service.present?
return if Feature.enabled?(:jira_issue_import_vue, @project) return if Feature.enabled?(:jira_issue_import_vue, @project)
unless @project.latest_jira_import&.in_progress? unless @project.latest_jira_import&.in_progress?
...@@ -39,12 +40,13 @@ module Projects ...@@ -39,12 +40,13 @@ module Projects
private private
def jira_import_enabled? def jira_import_enabled?
return if Feature.enabled?(:jira_issue_import, @project) return if @project.jira_issues_import_feature_flag_enabled?
redirect_to project_issues_path(@project) redirect_to project_issues_path(@project)
end end
def jira_integration_configured? def jira_integration_configured?
return if Feature.enabled?(:jira_issue_import_vue, @project)
return if @project.jira_service return if @project.jira_service
flash[:notice] = _("Configure the Jira integration first on your project's %{strong_start} Settings > Integrations > Jira%{strong_end} page." % flash[:notice] = _("Configure the Jira integration first on your project's %{strong_start} Settings > Integrations > Jira%{strong_end} page." %
......
...@@ -14,7 +14,7 @@ module Resolvers ...@@ -14,7 +14,7 @@ module Resolvers
end end
def authorized_resource?(project) def authorized_resource?(project)
return false unless Feature.enabled?(:jira_issue_import, project) return false unless project.jira_issues_import_feature_flag_enabled?
Ability.allowed?(context[:current_user], :admin_project, project) Ability.allowed?(context[:current_user], :admin_project, project)
end end
......
...@@ -123,6 +123,7 @@ module Clusters ...@@ -123,6 +123,7 @@ module Clusters
scope :managed, -> { where(managed: true) } scope :managed, -> { where(managed: true) }
scope :with_persisted_applications, -> { eager_load(*APPLICATIONS_ASSOCIATIONS) } scope :with_persisted_applications, -> { eager_load(*APPLICATIONS_ASSOCIATIONS) }
scope :default_environment, -> { where(environment_scope: DEFAULT_ENVIRONMENT) } scope :default_environment, -> { where(environment_scope: DEFAULT_ENVIRONMENT) }
scope :with_management_project, -> { where.not(management_project: nil) }
scope :for_project_namespace, -> (namespace_id) { joins(:projects).where(projects: { namespace_id: namespace_id }) } scope :for_project_namespace, -> (namespace_id) { joins(:projects).where(projects: { namespace_id: namespace_id }) }
......
...@@ -13,6 +13,8 @@ class GroupGroupLink < ApplicationRecord ...@@ -13,6 +13,8 @@ class GroupGroupLink < ApplicationRecord
validates :group_access, inclusion: { in: Gitlab::Access.all_values }, validates :group_access, inclusion: { in: Gitlab::Access.all_values },
presence: true presence: true
scope :non_guests, -> { where('group_access > ?', Gitlab::Access::GUEST) }
def self.access_options def self.access_options
Gitlab::Access.options_with_owner Gitlab::Access.options_with_owner
end end
......
...@@ -786,6 +786,10 @@ class Project < ApplicationRecord ...@@ -786,6 +786,10 @@ class Project < ApplicationRecord
Feature.enabled?(:context_commits, default_enabled: true) Feature.enabled?(:context_commits, default_enabled: true)
end end
def jira_issues_import_feature_flag_enabled?
Feature.enabled?(:jira_issue_import, self)
end
def team def team
@team ||= ProjectTeam.new(self) @team ||= ProjectTeam.new(self)
end end
...@@ -968,7 +972,7 @@ class Project < ApplicationRecord ...@@ -968,7 +972,7 @@ class Project < ApplicationRecord
end end
def jira_import? def jira_import?
import_type == 'jira' && latest_jira_import.present? && Feature.enabled?(:jira_issue_import, self) import_type == 'jira' && latest_jira_import.present? && jira_issues_import_feature_flag_enabled?
end end
def gitlab_project_import? def gitlab_project_import?
......
...@@ -3,11 +3,6 @@ ...@@ -3,11 +3,6 @@
class ProjectGroupLink < ApplicationRecord class ProjectGroupLink < ApplicationRecord
include Expirable include Expirable
GUEST = 10
REPORTER = 20
DEVELOPER = 30
MAINTAINER = 40
belongs_to :project belongs_to :project
belongs_to :group belongs_to :group
...@@ -18,6 +13,8 @@ class ProjectGroupLink < ApplicationRecord ...@@ -18,6 +13,8 @@ class ProjectGroupLink < ApplicationRecord
validates :group_access, inclusion: { in: Gitlab::Access.values }, presence: true validates :group_access, inclusion: { in: Gitlab::Access.values }, presence: true
validate :different_group validate :different_group
scope :non_guests, -> { where('group_access > ?', Gitlab::Access::GUEST) }
after_commit :refresh_group_members_authorized_projects after_commit :refresh_group_members_authorized_projects
alias_method :shared_with_group, :group alias_method :shared_with_group, :group
...@@ -27,7 +24,7 @@ class ProjectGroupLink < ApplicationRecord ...@@ -27,7 +24,7 @@ class ProjectGroupLink < ApplicationRecord
end end
def self.default_access def self.default_access
DEVELOPER Gitlab::Access::DEVELOPER
end end
def self.search(query) def self.search(query)
......
...@@ -44,7 +44,7 @@ module JiraImport ...@@ -44,7 +44,7 @@ module JiraImport
end end
def validate def validate
return build_error_response(_('Jira import feature is disabled.')) unless Feature.enabled?(:jira_issue_import, project) return build_error_response(_('Jira import feature is disabled.')) unless project.jira_issues_import_feature_flag_enabled?
return build_error_response(_('You do not have permissions to run the import.')) unless user.can?(:admin_project, project) return build_error_response(_('You do not have permissions to run the import.')) unless user.can?(:admin_project, project)
return build_error_response(_('Jira integration not configured.')) unless project.jira_service&.active? return build_error_response(_('Jira integration not configured.')) unless project.jira_service&.active?
return build_error_response(_('Unable to find Jira project to import data from.')) if jira_project_key.blank? return build_error_response(_('Unable to find Jira project to import data from.')) if jira_project_key.blank?
......
- if Feature.enabled?(:jira_issue_import_vue, @project) - if Feature.enabled?(:jira_issue_import_vue, @project)
.js-jira-import-root{ data: { project_path: @project.full_path } } .js-jira-import-root{ data: { project_path: @project.full_path,
is_jira_configured: @is_jira_configured.to_s,
setup_illustration: image_path('illustrations/manual_action.svg') } }
- else - else
- title = _('Jira Issue Import') - title = _('Jira Issue Import')
- page_title title - page_title title
......
- type = local_assigns.fetch(:type, :icon) - type = local_assigns.fetch(:type, :icon)
- if Feature.enabled?(:jira_issue_import, @project) - if @project.jira_issues_import_feature_flag_enabled?
.dropdown.btn-group .dropdown.btn-group
%button.btn.rounded-right.text-center{ class: ('has-tooltip' if type == :icon), title: (_('Import issues') if type == :icon), %button.btn.rounded-right.text-center{ class: ('has-tooltip' if type == :icon), title: (_('Import issues') if type == :icon),
data: { toggle: 'dropdown' }, 'aria-label' => _('Import issues'), 'aria-haspopup' => 'true', 'aria-expanded' => 'false' } data: { toggle: 'dropdown' }, 'aria-label' => _('Import issues'), 'aria-haspopup' => 'true', 'aria-expanded' => 'false' }
......
...@@ -26,7 +26,7 @@ module Gitlab ...@@ -26,7 +26,7 @@ module Gitlab
def can_import?(project) def can_import?(project)
return false unless project return false unless project
return false if Feature.disabled?(:jira_issue_import, project) return false unless project.jira_issues_import_feature_flag_enabled?
project.latest_jira_import&.started? project.latest_jira_import&.started?
end end
......
...@@ -25,7 +25,7 @@ module Gitlab ...@@ -25,7 +25,7 @@ module Gitlab
def start_import def start_import
return false unless project return false unless project
return false if Feature.disabled?(:jira_issue_import, project) return false unless project.jira_issues_import_feature_flag_enabled?
return true if start(project.latest_jira_import) return true if start(project.latest_jira_import)
Gitlab::Import::Logger.info( Gitlab::Import::Logger.info(
......
---
title: Add usage data metrics for instance level clusters and clusters with management projects
merge_request: 28510
author:
type: added
...@@ -199,7 +199,7 @@ Few notes on the service itself: ...@@ -199,7 +199,7 @@ Few notes on the service itself:
- Passwords will be stored in the following locations: - Passwords will be stored in the following locations:
- `/etc/gitlab/gitlab.rb`: hashed - `/etc/gitlab/gitlab.rb`: hashed
- `/var/opt/gitlab/pgbouncer/pg_auth`: hashed - `/var/opt/gitlab/pgbouncer/pg_auth`: hashed
- `/var/opt/gitlab/gitlab-consul/.pgpass`: plaintext - `/var/opt/gitlab/consul/.pgpass`: plaintext
##### PostgreSQL information ##### PostgreSQL information
......
...@@ -71,8 +71,10 @@ The following API resources are available in the project context: ...@@ -71,8 +71,10 @@ The following API resources are available in the project context:
| [Services](services.md) | `/projects/:id/services` | | [Services](services.md) | `/projects/:id/services` |
| [Tags](tags.md) | `/projects/:id/repository/tags` | | [Tags](tags.md) | `/projects/:id/repository/tags` |
| [Visual Review discussions](visual_review_discussions.md) **(STARTER**) | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` | | [Visual Review discussions](visual_review_discussions.md) **(STARTER**) | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` |
| [Vulnerabilities](vulnerabilities.md) **(ULTIMATE)** | `/projects/:id/vulnerabilities` | | [Vulnerabilities](vulnerabilities.md) **(ULTIMATE)** | `/vulnerabilities/:id` |
| [Vulnerability Findings](vulnerability_findings.md) **(ULTIMATE)** | `/projects/:id/vulnerability_findings` | | [Vulnerability exports](vulnerability_exports.md) **(ULTIMATE)** | `/projects/:id/vulnerability_exports` |
| [Project vulnerabilities](project_vulnerabilities.md) **(ULTIMATE)** | `/projects/:id/vulnerabilities` |
| [Vulnerability findings](vulnerability_findings.md) **(ULTIMATE)** | `/projects/:id/vulnerability_findings` |
| [Wikis](wikis.md) | `/projects/:id/wikis` | | [Wikis](wikis.md) | `/projects/:id/wikis` |
## Group resources ## Group resources
......
# Project Vulnerabilities API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/10242) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6.
CAUTION: **Caution:**
This API is currently in development and is protected by a **disabled**
[feature flag](../development/feature_flags/index.md).
On a self-managed GitLab instance, an administrator can enable it by starting the Rails console
(`sudo gitlab-rails console`) and then running the following command: `Feature.enable(:first_class_vulnerabilities)`.
To test if the Vulnerabilities API was successfully enabled, run the following command:
`Feature.enabled?(:first_class_vulnerabilities)`.
CAUTION: **Caution:**
This API is in an alpha stage and considered unstable.
The response payload may be subject to change or breakage
across GitLab releases.
Every API call to vulnerabilities must be [authenticated](README.md#authentication).
Vulnerability permissions inherit permissions from their project. If a project is
private, and a user isn't a member of the project to which the vulnerability
belongs, requests to that project will return a `404 Not Found` status code.
## Vulnerabilities pagination
API results are paginated, and `GET` requests return 20 results at a time by default.
Read more on [pagination](README.md#pagination).
## List project vulnerabilities
List all of a project's vulnerabilities.
If an authenticated user does not have permission to
[use the Project Security Dashboard](../user/permissions.md#project-members-permissions),
`GET` requests for vulnerabilities of this project will result in a `403` status code.
```plaintext
GET /projects/:id/vulnerabilities
```
| Attribute | Type | Required | Description |
| ------------- | -------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/vulnerabilities
```
Example response:
```json
[
{
"author_id": 1,
"confidence": "medium",
"created_at": "2020-04-07T14:01:04.655Z",
"description": null,
"dismissed_at": null,
"dismissed_by_id": null,
"due_date": null,
"finding": {
"confidence": "medium",
"created_at": "2020-04-07T14:01:04.630Z",
"id": 103,
"location_fingerprint": "228998b5db51d86d3b091939e2f5873ada0a14a1",
"metadata_version": "2.0",
"name": "Regular Expression Denial of Service in debug",
"primary_identifier_id": 135,
"project_fingerprint": "05e7cc9978ca495cf739a9f707ed34811e41c615",
"project_id": 24,
"raw_metadata": "{\"category\":\"dependency_scanning\",\"name\":\"Regular Expression Denial of Service\",\"message\":\"Regular Expression Denial of Service in debug\",\"description\":\"The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.\",\"cve\":\"yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a\",\"severity\":\"Unknown\",\"solution\":\"Upgrade to latest versions.\",\"scanner\":{\"id\":\"gemnasium\",\"name\":\"Gemnasium\"},\"location\":{\"file\":\"yarn.lock\",\"dependency\":{\"package\":{\"name\":\"debug\"},\"version\":\"1.0.5\"}},\"identifiers\":[{\"type\":\"gemnasium\",\"name\":\"Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a\",\"value\":\"37283ed4-0380-40d7-ada7-2d994afcc62a\",\"url\":\"https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories\"}],\"links\":[{\"url\":\"https://nodesecurity.io/advisories/534\"},{\"url\":\"https://github.com/visionmedia/debug/issues/501\"},{\"url\":\"https://github.com/visionmedia/debug/pull/504\"}],\"remediations\":[null]}",
"report_type": "dependency_scanning",
"scanner_id": 63,
"severity": "low",
"updated_at": "2020-04-07T14:01:04.664Z",
"uuid": "f1d528ae-d0cc-47f6-a72f-936cec846ae7",
"vulnerability_id": 103
},
"id": 103,
"last_edited_at": null,
"last_edited_by_id": null,
"project": {
"created_at": "2020-04-07T13:54:25.634Z",
"description": "",
"id": 24,
"name": "security-reports",
"name_with_namespace": "gitlab-org / security-reports",
"path": "security-reports",
"path_with_namespace": "gitlab-org/security-reports"
},
"project_default_branch": "master",
"report_type": "dependency_scanning",
"resolved_at": null,
"resolved_by_id": null,
"resolved_on_default_branch": false,
"severity": "low",
"start_date": null,
"state": "detected",
"title": "Regular Expression Denial of Service in debug",
"updated_at": "2020-04-07T14:01:04.655Z",
"updated_by_id": null
}
]
```
## New vulnerability
Creates a new vulnerability.
If an authenticated user does not have a permission to
[create a new vulnerability](../user/permissions.md#project-members-permissions),
this request will result in a `403` status code.
```plaintext
POST /projects/:id/vulnerabilities?finding_id=<your_finding_id>
```
| Attribute | Type | Required | Description |
| ------------------- | ----------------- | ---------- | -----------------------------------------------------------------------------------------------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) which the authenticated user is a member of |
| `finding_id` | integer or string | yes | The ID of a Vulnerability Finding from which the new Vulnerability will be created |
The other attributes of a newly created Vulnerability are populated from
its source Vulnerability Finding, or with these default values:
| Attribute | Value |
|--------------|-------------------------------------------------------|
| `author` | The authenticated user |
| `title` | The `name` attribute of a Vulnerability Finding |
| `state` | `opened` |
| `severity` | The `severity` attribute of a Vulnerability Finding |
| `confidence` | The `confidence` attribute of a Vulnerability Finding |
```shell
curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/vulnerabilities?finding_id=1
```
Example response:
```json
{
"author_id": 1,
"confidence": "medium",
"created_at": "2020-04-07T14:01:04.655Z",
"description": null,
"dismissed_at": null,
"dismissed_by_id": null,
"due_date": null,
"finding": {
"confidence": "medium",
"created_at": "2020-04-07T14:01:04.630Z",
"id": 103,
"location_fingerprint": "228998b5db51d86d3b091939e2f5873ada0a14a1",
"metadata_version": "2.0",
"name": "Regular Expression Denial of Service in debug",
"primary_identifier_id": 135,
"project_fingerprint": "05e7cc9978ca495cf739a9f707ed34811e41c615",
"project_id": 24,
"raw_metadata": "{\"category\":\"dependency_scanning\",\"name\":\"Regular Expression Denial of Service\",\"message\":\"Regular Expression Denial of Service in debug\",\"description\":\"The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.\",\"cve\":\"yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a\",\"severity\":\"Unknown\",\"solution\":\"Upgrade to latest versions.\",\"scanner\":{\"id\":\"gemnasium\",\"name\":\"Gemnasium\"},\"location\":{\"file\":\"yarn.lock\",\"dependency\":{\"package\":{\"name\":\"debug\"},\"version\":\"1.0.5\"}},\"identifiers\":[{\"type\":\"gemnasium\",\"name\":\"Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a\",\"value\":\"37283ed4-0380-40d7-ada7-2d994afcc62a\",\"url\":\"https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories\"}],\"links\":[{\"url\":\"https://nodesecurity.io/advisories/534\"},{\"url\":\"https://github.com/visionmedia/debug/issues/501\"},{\"url\":\"https://github.com/visionmedia/debug/pull/504\"}],\"remediations\":[null]}",
"report_type": "dependency_scanning",
"scanner_id": 63,
"severity": "low",
"updated_at": "2020-04-07T14:01:04.664Z",
"uuid": "f1d528ae-d0cc-47f6-a72f-936cec846ae7",
"vulnerability_id": 103
},
"id": 103,
"last_edited_at": null,
"last_edited_by_id": null,
"project": {
"created_at": "2020-04-07T13:54:25.634Z",
"description": "",
"id": 24,
"name": "security-reports",
"name_with_namespace": "gitlab-org / security-reports",
"path": "security-reports",
"path_with_namespace": "gitlab-org/security-reports"
},
"project_default_branch": "master",
"report_type": "dependency_scanning",
"resolved_at": null,
"resolved_by_id": null,
"resolved_on_default_branch": false,
"severity": "low",
"start_date": null,
"state": "detected",
"title": "Regular Expression Denial of Service in debug",
"updated_at": "2020-04-07T14:01:04.655Z",
"updated_by_id": null
}
```
### Errors
This error occurs when a Finding chosen to create a Vulnerability from is not found, or
is already associated with a different Vulnerability:
```plaintext
A Vulnerability Finding is not found or already attached to a different Vulnerability
```
Status code: `400`
Example response:
```json
{
"message": {
"base": [
"finding is not found or is already attached to a vulnerability"
]
}
}
```
# Vulnerabilities API **(ULTIMATE)** # Vulnerabilities API **(ULTIMATE)**
This document was moved to [another location](vulnerability_findings.md). > [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/10242) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6.
NOTE: **Note:**
The former Vulnerabilities API was renamed to Vulnerability Findings API
and its documentation was moved to [a different location](vulnerability_findings.md).
This document now describes the new Vulnerabilities API that provides access to
[Standalone Vulnerabilities](https://gitlab.com/groups/gitlab-org/-/epics/634).
CAUTION: **Caution:**
This API is currently in development and is protected by a **disabled**
[feature flag](../development/feature_flags/index.md).
On a self-managed GitLab instance, an administrator can enable it by starting the Rails console
(`sudo gitlab-rails console`) and then running the following command: `Feature.enable(:first_class_vulnerabilities)`.
To test if the Vulnerabilities API was successfully enabled, run the following command:
`Feature.enabled?(:first_class_vulnerabilities)`.
CAUTION: **Caution:**
This API is in an alpha stage and considered unstable.
The response payload may be subject to change or breakage
across GitLab releases.
Every API call to vulnerabilities must be [authenticated](README.md#authentication).
Vulnerability permissions inherit permissions from their project. If a project is
private, and a user isn't a member of the project to which the vulnerability
belongs, requests to that project will return a `404 Not Found` status code.
## Single vulnerability
Gets a single vulnerability
```plaintext
GET /vulnerabilities/:id
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer or string | yes | The ID of a Vulnerability to get |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/vulnerabilities/1
```
Example response:
```json
{
"id": 1,
"title": "Predictable pseudorandom number generator",
"description": null,
"state": "opened",
"severity": "medium",
"confidence": "medium",
"report_type": "sast",
"project": {
"id": 32,
"name": "security-reports",
"full_path": "/gitlab-examples/security/security-reports",
"full_name": "gitlab-examples / security / security-reports"
},
"author_id": 1,
"updated_by_id": null,
"last_edited_by_id": null,
"closed_by_id": null,
"start_date": null,
"due_date": null,
"created_at": "2019-10-13T15:08:40.219Z",
"updated_at": "2019-10-13T15:09:40.382Z",
"last_edited_at": null,
"closed_at": null
}
```
## Confirm vulnerability
Confirms a given vulnerability. Returns status code `304` if the vulnerability is already confirmed.
If an authenticated user does not have permission to
[confirm vulnerabilities](../user/permissions.md#project-members-permissions),
this request will result in a `403` status code.
```plaintext
POST /vulnerabilities/:id/confirm
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer or string | yes | The ID of a vulnerability to confirm |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/vulnerabilities/5/confirm"
```
Example response:
```json
{
"id": 2,
"title": "Predictable pseudorandom number generator",
"description": null,
"state": "confirmed",
"severity": "medium",
"confidence": "medium",
"report_type": "sast",
"project": {
"id": 32,
"name": "security-reports",
"full_path": "/gitlab-examples/security/security-reports",
"full_name": "gitlab-examples / security / security-reports"
},
"author_id": 1,
"updated_by_id": null,
"last_edited_by_id": null,
"closed_by_id": null,
"start_date": null,
"due_date": null,
"created_at": "2019-10-13T15:08:40.219Z",
"updated_at": "2019-10-13T15:09:40.382Z",
"last_edited_at": null,
"closed_at": null
}
```
## Resolve vulnerability
Resolves a given vulnerability. Returns status code `304` if the vulnerability is already resolved.
If an authenticated user does not have permission to
[resolve vulnerabilities](../user/permissions.md#project-members-permissions),
this request will result in a `403` status code.
```plaintext
POST /vulnerabilities/:id/resolve
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer or string | yes | The ID of a Vulnerability to resolve |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/vulnerabilities/5/resolve"
```
Example response:
```json
{
"id": 2,
"title": "Predictable pseudorandom number generator",
"description": null,
"state": "resolved",
"severity": "medium",
"confidence": "medium",
"report_type": "sast",
"project": {
"id": 32,
"name": "security-reports",
"full_path": "/gitlab-examples/security/security-reports",
"full_name": "gitlab-examples / security / security-reports"
},
"author_id": 1,
"updated_by_id": null,
"last_edited_by_id": null,
"closed_by_id": null,
"start_date": null,
"due_date": null,
"created_at": "2019-10-13T15:08:40.219Z",
"updated_at": "2019-10-13T15:09:40.382Z",
"last_edited_at": null,
"closed_at": null
}
```
## Dismiss vulnerability
Dismisses a given vulnerability. Returns status code `304` if the vulnerability is already dismissed.
If an authenticated user does not have permission to
[dismiss vulnerabilities](../user/permissions.md#project-members-permissions),
this request will result in a `403` status code.
```plaintext
POST /vulnerabilities/:id/dismiss
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer or string | yes | The ID of a vulnerability to dismiss |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/vulnerabilities/5/dismiss"
```
Example response:
```json
{
"id": 2,
"title": "Predictable pseudorandom number generator",
"description": null,
"state": "closed",
"severity": "medium",
"confidence": "medium",
"report_type": "sast",
"project": {
"id": 32,
"name": "security-reports",
"full_path": "/gitlab-examples/security/security-reports",
"full_name": "gitlab-examples / security / security-reports"
},
"author_id": 1,
"updated_by_id": null,
"last_edited_by_id": null,
"closed_by_id": null,
"start_date": null,
"due_date": null,
"created_at": "2019-10-13T15:08:40.219Z",
"updated_at": "2019-10-13T15:09:40.382Z",
"last_edited_at": null,
"closed_at": null
}
```
# Project Vulnerabilities API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/197494) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
CAUTION: **Caution:**
This API is currently in development and is protected by a **disabled**
[feature flag](../development/feature_flags/index.md).
On a self-managed GitLab instance, an administrator can enable it by starting the Rails console
(`sudo gitlab-rails console`) and then running the following command: `Feature.enable(:first_class_vulnerabilities)`.
To test if the Vulnerability Exports API was successfully enabled, run the following command:
`Feature.enabled?(:first_class_vulnerabilities)`.
CAUTION: **Caution:**
This API is in an alpha stage and considered unstable.
The response payload may be subject to change or breakage
across GitLab releases.
Every API call to vulnerability exports must be [authenticated](README.md#authentication).
Vulnerability export permissions inherit permissions from their project. If a project is
private and a user isn't a member of the project to which the vulnerability
belongs, requests to that project return a `404 Not Found` status code.
Vulnerability exports can be only accessed by the export's author.
## Create vulnerability export
Creates a new vulnerability export.
If an authenticated user doesn't have permission to
[create a new vulnerability](../user/permissions.md#project-members-permissions),
this request results in a `403` status code.
```plaintext
POST /projects/:id/vulnerability_exports
```
| Attribute | Type | Required | Description |
| ------------------- | ----------------- | ---------- | -----------------------------------------------------------------------------------------------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path](README.md#namespaced-path-encoding) of the project which the authenticated user is a member of |
```shell
curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/vulnerability_exports
```
The created vulnerability export will be automatically deleted after 1 hour.
Example response:
```json
{
"id": 2,
"created_at": "2020-03-30T09:35:38.746Z",
"project_id": 1,
"format": "csv",
"status": "created",
"started_at": null,
"finished_at": null,
"_links": {
"self": "https://gitlab.example.com/api/v4/projects/1/vulnerability_exports/2",
"download": "https://gitlab.example.com/api/v4/projects/1/vulnerability_exports/2/download"
}
}
```
## Get single vulnerability export
Gets a single vulnerability export.
```plaintext
POST /projects/:id/vulnerability_exports/:vulnerability_export_id
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer or string | yes | The vulnerability's ID |
| `vulnerability_export_id` | integer or string | yes | The vulnerability export's ID |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/vulnerability_exports/2
```
If the vulnerability export isn't finished, the response is `202 Accepted`.
Example response:
```json
{
"id": 2,
"created_at": "2020-03-30T09:35:38.746Z",
"project_id": 1,
"format": "csv",
"status": "finished",
"started_at": "2020-03-30T09:36:54.469Z",
"finished_at": "2020-03-30T09:36:55.008Z",
"_links": {
"self": "https://gitlab.example.com/api/v4/projects/1/vulnerability_exports/2",
"download": "https://gitlab.example.com/api/v4/projects/1/vulnerability_exports/2/download"
}
}
```
## Download vulnerability export
Downloads a single vulnerability export.
```plaintext
POST /projects/:id/vulnerability_exports/:vulnerability_export_id/download
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer or string | yes | The vulnerability's ID |
| `vulnerability_export_id` | integer or string | yes | The vulnerability export's ID |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/vulnerability_exports/2/download
```
The response will be `404 Not Found` if the vulnerability export is not finished yet or was not found.
Example response:
```csv
Scanner Type,Scanner Name,Status,Vulnerability,Details,Additional Info,Severity,CVE
container_scanning,Clair,confirmed,CVE-2017-16997 in glibc,,CVE-2017-16997 in glibc,critical,CVE-2017-16997
container_scanning,Clair,detected,CVE-2017-18269 in glibc,,CVE-2017-18269 in glibc,critical,CVE-2017-18269
container_scanning,Clair,detected,CVE-2018-1000001 in glibc,,CVE-2018-1000001 in glibc,high,CVE-2018-1000001
container_scanning,Clair,detected,CVE-2016-10228 in glibc,,CVE-2016-10228 in glibc,medium,CVE-2016-10228
container_scanning,Clair,confirmed,CVE-2010-4052 in glibc,,CVE-2010-4052 in glibc,low,CVE-2010-4052
container_scanning,Clair,detected,CVE-2018-18520 in elfutils,,CVE-2018-18520 in elfutils,low,CVE-2018-18520
container_scanning,Clair,detected,CVE-2018-16869 in nettle,,CVE-2018-16869 in nettle,unknown,CVE-2018-16869
dependency_scanning,Gemnasium,detected,Regular Expression Denial of Service in debug,,Regular Expression Denial of Service in debug,unknown,yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a
dependency_scanning,Gemnasium,detected,Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js,,Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js,unknown,yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98
sast,Find Security Bugs,detected,Predictable pseudorandom number generator,,Predictable pseudorandom number generator,medium,818bf5dacb291e15d9e6dc3c5ac32178:PREDICTABLE_RANDOM:src/main/java/com/gitlab/security_products/tests/App.java:47
sast,Find Security Bugs,detected,Cipher with no integrity,,Cipher with no integrity,medium,e6449b89335daf53c0db4c0219bc1634:CIPHER_INTEGRITY:src/main/java/com/gitlab/security_products/tests/App.java:29
sast,Find Security Bugs,detected,Predictable pseudorandom number generator,,Predictable pseudorandom number generator,medium,e8ff1d01f74cd372f78da8f5247d3e73:PREDICTABLE_RANDOM:src/main/java/com/gitlab/security_products/tests/App.java:41
sast,Find Security Bugs,confirmed,ECB mode is insecure 2,,ECB mode is insecure,medium,ea0f905fc76f2739d5f10a1fd1e37a10:ECB_MODE:src/main/java/com/gitlab/security_products/tests/App.java:29
```
# Vulnerability Issue links API **(ULTIMATE)**
CAUTION: **Caution:**
This API is in an alpha stage and considered unstable.
The response payload may be subject to change or breakage
across GitLab releases.
## List related issues
Get a list of related issues of a given issue, sorted by the relationship creation datetime (ascending).
Issues will be filtered according to the user authorizations.
```plaintext
GET /projects/:id/issues/:issue_iid/links
```
Parameters:
| Attribute | Type | Required | Description |
|-------------|---------|----------|--------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```json
[
{
"id" : 84,
"iid" : 14,
"issue_link_id": 1
"project_id" : 4,
"created_at" : "2016-01-07T12:44:33.959Z",
"title" : "Issues with auth",
"state" : "opened",
"assignees" : [],
"assignee" : null,
"labels" : [
"bug"
],
"author" : {
"name" : "Alexandra Bashirian",
"avatar_url" : null,
"state" : "active",
"web_url" : "https://gitlab.example.com/eileen.lowe",
"id" : 18,
"username" : "eileen.lowe"
},
"description" : null,
"updated_at" : "2016-01-07T12:44:33.959Z",
"milestone" : null,
"subscribed" : true,
"user_notes_count": 0,
"due_date": null,
"web_url": "http://example.com/example/example/issues/14",
"confidential": false,
"weight": null,
}
]
```
## Create an issue link
Creates a two-way relation between two issues. User must be allowed to update both issues in order to succeed.
```plaintext
POST /projects/:id/issues/:issue_iid/links
```
| Attribute | Type | Required | Description |
|-------------|---------|----------|--------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `issue_iid` | integer | yes | The internal ID of a project's issue |
| `target_project_id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) of a target project |
| `target_issue_iid` | integer or string | yes | The internal ID of a target project's issue |
```json
{
"source_issue" : {
"id" : 83,
"iid" : 11,
"project_id" : 4,
"created_at" : "2016-01-07T12:44:33.959Z",
"title" : "Issues with auth",
"state" : "opened",
"assignees" : [],
"assignee" : null,
"labels" : [
"bug"
],
"author" : {
"name" : "Alexandra Bashirian",
"avatar_url" : null,
"state" : "active",
"web_url" : "https://gitlab.example.com/eileen.lowe",
"id" : 18,
"username" : "eileen.lowe"
},
"description" : null,
"updated_at" : "2016-01-07T12:44:33.959Z",
"milestone" : null,
"subscribed" : true,
"user_notes_count": 0,
"due_date": null,
"web_url": "http://example.com/example/example/issues/11",
"confidential": false,
"weight": null,
},
"target_issue" : {
"id" : 84,
"iid" : 14,
"project_id" : 4,
"created_at" : "2016-01-07T12:44:33.959Z",
"title" : "Issues with auth",
"state" : "opened",
"assignees" : [],
"assignee" : null,
"labels" : [
"bug"
],
"author" : {
"name" : "Alexandra Bashirian",
"avatar_url" : null,
"state" : "active",
"web_url" : "https://gitlab.example.com/eileen.lowe",
"id" : 18,
"username" : "eileen.lowe"
},
"description" : null,
"updated_at" : "2016-01-07T12:44:33.959Z",
"milestone" : null,
"subscribed" : true,
"user_notes_count": 0,
"due_date": null,
"web_url": "http://example.com/example/example/issues/14",
"confidential": false,
"weight": null,
}
}
```
## Delete an issue link
Deletes an issue link, removing the two-way relationship.
```plaintext
DELETE /projects/:id/issues/:issue_iid/links/:issue_link_id
```
| Attribute | Type | Required | Description |
|-------------|---------|----------|--------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `issue_iid` | integer | yes | The internal ID of a project's issue |
| `issue_link_id` | integer or string | yes | The ID of an issue relationship |
```json
{
"source_issue" : {
"id" : 83,
"iid" : 11,
"project_id" : 4,
"created_at" : "2016-01-07T12:44:33.959Z",
"title" : "Issues with auth",
"state" : "opened",
"assignees" : [],
"assignee" : null,
"labels" : [
"bug"
],
"author" : {
"name" : "Alexandra Bashirian",
"avatar_url" : null,
"state" : "active",
"web_url" : "https://gitlab.example.com/eileen.lowe",
"id" : 18,
"username" : "eileen.lowe"
},
"description" : null,
"updated_at" : "2016-01-07T12:44:33.959Z",
"milestone" : null,
"subscribed" : true,
"user_notes_count": 0,
"due_date": null,
"web_url": "http://example.com/example/example/issues/11",
"confidential": false,
"weight": null,
},
"target_issue" : {
"id" : 84,
"iid" : 14,
"project_id" : 4,
"created_at" : "2016-01-07T12:44:33.959Z",
"title" : "Issues with auth",
"state" : "opened",
"assignees" : [],
"assignee" : null,
"labels" : [
"bug"
],
"author" : {
"name" : "Alexandra Bashirian",
"avatar_url" : null,
"state" : "active",
"web_url" : "https://gitlab.example.com/eileen.lowe",
"id" : 18,
"username" : "eileen.lowe"
},
"description" : null,
"updated_at" : "2016-01-07T12:44:33.959Z",
"milestone" : null,
"subscribed" : true,
"user_notes_count": 0,
"due_date": null,
"web_url": "http://example.com/example/example/issues/14",
"confidential": false,
"weight": null,
}
}
```
...@@ -63,6 +63,8 @@ The current state of existing package registries availability is: ...@@ -63,6 +63,8 @@ The current state of existing package registries availability is:
| Maven | Yes | Yes | Yes | | Maven | Yes | Yes | Yes |
| Conan | No - [open issue](https://gitlab.com/gitlab-org/gitlab/issues/11679) | No - [open issue](https://gitlab.com/gitlab-org/gitlab/issues/11679) | Yes | | Conan | No - [open issue](https://gitlab.com/gitlab-org/gitlab/issues/11679) | No - [open issue](https://gitlab.com/gitlab-org/gitlab/issues/11679) | Yes |
| NPM | No - [open issue](https://gitlab.com/gitlab-org/gitlab/issues/36853) | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/issues/36853) | | NPM | No - [open issue](https://gitlab.com/gitlab-org/gitlab/issues/36853) | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/issues/36853) |
| NuGet | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36423) | No |
| PyPI | Yes | No | No |
NOTE: **Note:** NPM is currently a hybrid of the instance level and group level. NOTE: **Note:** NPM is currently a hybrid of the instance level and group level.
It is using the top-level group or namespace as the defining portion of the name It is using the top-level group or namespace as the defining portion of the name
......
...@@ -197,9 +197,11 @@ but commented out to help encourage others to add to it in the future. --> ...@@ -197,9 +197,11 @@ but commented out to help encourage others to add to it in the future. -->
|clusters_enabled|counts|| |clusters_enabled|counts||
|project_clusters_enabled|counts|| |project_clusters_enabled|counts||
|group_clusters_enabled|counts|| |group_clusters_enabled|counts||
|instance_clusters_enabled|counts||
|clusters_disabled|counts|| |clusters_disabled|counts||
|project_clusters_disabled|counts|| |project_clusters_disabled|counts||
|group_clusters_disabled|counts|| |group_clusters_disabled|counts||
|instance_clusters_disabled|counts||
|clusters_platforms_eks|counts|| |clusters_platforms_eks|counts||
|clusters_platforms_gke|counts|| |clusters_platforms_gke|counts||
|clusters_platforms_user|counts|| |clusters_platforms_user|counts||
...@@ -211,6 +213,7 @@ but commented out to help encourage others to add to it in the future. --> ...@@ -211,6 +213,7 @@ but commented out to help encourage others to add to it in the future. -->
|clusters_applications_runner|counts|| |clusters_applications_runner|counts||
|clusters_applications_knative|counts|| |clusters_applications_knative|counts||
|clusters_applications_elastic_stack|counts|| |clusters_applications_elastic_stack|counts||
|clusters_management_project|counts||
|in_review_folder|counts|| |in_review_folder|counts||
|grafana_integrated_projects|counts|| |grafana_integrated_projects|counts||
|groups|counts|| |groups|counts||
...@@ -382,11 +385,14 @@ but commented out to help encourage others to add to it in the future. --> ...@@ -382,11 +385,14 @@ but commented out to help encourage others to add to it in the future. -->
|clusters_applications_helm|usage_activity_by_stage|configure| |clusters_applications_helm|usage_activity_by_stage|configure|
|clusters_applications_ingress|usage_activity_by_stage|configure| |clusters_applications_ingress|usage_activity_by_stage|configure|
|clusters_applications_knative|usage_activity_by_stage|configure| |clusters_applications_knative|usage_activity_by_stage|configure|
|clusters_management_project|usage_activity_by_stage|configure|
|clusters_disabled|usage_activity_by_stage|configure| |clusters_disabled|usage_activity_by_stage|configure|
|clusters_enabled|usage_activity_by_stage|configure| |clusters_enabled|usage_activity_by_stage|configure|
|clusters_platforms_gke|usage_activity_by_stage|configure| |clusters_platforms_gke|usage_activity_by_stage|configure|
|clusters_platforms_eks|usage_activity_by_stage|configure| |clusters_platforms_eks|usage_activity_by_stage|configure|
|clusters_platforms_user|usage_activity_by_stage|configure| |clusters_platforms_user|usage_activity_by_stage|configure|
|instance_clusters_disabled|usage_activity_by_stage|configure|
|instance_clusters_enabled|usage_activity_by_stage|configure|
|group_clusters_disabled|usage_activity_by_stage|configure| |group_clusters_disabled|usage_activity_by_stage|configure|
|group_clusters_enabled|usage_activity_by_stage|configure| |group_clusters_enabled|usage_activity_by_stage|configure|
|project_clusters_disabled|usage_activity_by_stage|configure| |project_clusters_disabled|usage_activity_by_stage|configure|
......
...@@ -78,3 +78,4 @@ above. You can find more information at each of the pages below: ...@@ -78,3 +78,4 @@ above. You can find more information at each of the pages below:
- [Container scanning offline directions](../container_scanning/index.md#running-container-scanning-in-an-offline-environment) - [Container scanning offline directions](../container_scanning/index.md#running-container-scanning-in-an-offline-environment)
- [SAST offline directions](../sast/index.md#gitlab-sast-in-an-offline-environment) - [SAST offline directions](../sast/index.md#gitlab-sast-in-an-offline-environment)
- [DAST offline directions](../dast/index.md#running-dast-in-an-offline-environment) - [DAST offline directions](../dast/index.md#running-dast-in-an-offline-environment)
- [License Compliance offline directions](../../compliance/license_compliance/index.md#running-license-compliance-in-an-offline-environment)
---
type: reference, howto
---
# Standalone Vulnerability pages
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/13561) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
CAUTION: **Warning:**
This feature is currently [Alpha](https://about.gitlab.com/handbook/product/#alpha-beta-ga).
You can begin using it, but it may receive important changes in the future.
Each security vulnerability in the [Vulnerability List](../dependency_list/index.md) has its own standalone
page.
![Standalone vulnerability page](img/standalone_vulnerability_page_v12_10.png)
On the standalone vulnerability page, you can interact with the vulnerability in
several different ways:
- [Change the Vulnerability Status](#changing-vulnerability-status) - You can change the
status of a vulnerability to **Detected**, **Confirmed**, **Dismissed**, or **Resolved**.
- [Create issue](#creating-an-issue-for-a-vulnerability) - Create a new issue with the
title and description prepopulated with information from the vulnerability report.
By default, such issues are [confidential](../../project/issues/confidential_issues.md).
- [Solution](#automatic-remediation-solutions-for-vulnerabilities) - For some vulnerabilities,
a solution is provided for how to fix the vulnerability.
## Changing vulnerability status
You can switch the status of a vulnerability using the **Status** dropdown to one of
the following values:
| State | Description |
|-----------|-------------------------------------------------------------------|
| Detected | The default state for a newly discovered vulnerability |
| Confirmed | A user has seen this vulnerability and confirmed it to be real |
| Dismissed | A user has seen this vulnerability and dismissed it |
| Resolved | The vulnerability has been fixed and is no longer in the codebase |
## Creating an issue for a vulnerability
You can create an issue for a vulnerability by selecting the **Create issue** button.
This creates a [confidential issue](../../project/issues/confidential_issues.md) in the
project the vulnerability came from, and prepopulates it with useful information from
the vulnerability report. After the issue is created, GitLab redirects you to the
issue page so you can edit, assign, or comment on the issue.
## Automatic remediation solutions for vulnerabilities
You can fix some vulnerabilities by applying the solution that GitLab automatically
generates for you. GitLab supports the following scanners:
- [Dependency Scanning](../dependency_scanning/index.md): Automatic Patch creation
is only available for Node.js projects managed with `yarn`.
- [Container Scanning](../container_scanning/index.md).
### Manually applying a suggested patch
To apply a patch automatically generated by GitLab to fix a vulnerability:
1. Open the issue created in [Create issue](#creating-an-issue-for-a-vulnerability).
1. In the **Issue description**, scroll to **Solution** and download the linked patch file.
1. Ensure your local project has the same commit checked out that was used to generate the patch.
1. Run `git apply remediation.patch` to apply the patch.
1. Verify and commit the changes to your branch.
![Apply patch for dependency scanning](../img/vulnerability_solution.png)
...@@ -198,6 +198,22 @@ you can use the `MAVEN_CLI_OPTS` environment variable. ...@@ -198,6 +198,22 @@ you can use the `MAVEN_CLI_OPTS` environment variable.
Read more on [how to use private Maven repos](../../application_security/index.md#using-private-maven-repos). Read more on [how to use private Maven repos](../../application_security/index.md#using-private-maven-repos).
You can also use `MAVEN_CLI_OPTS` to connect to a trusted Maven repository that uses a self-signed
or internally trusted certificate. For example:
```yaml
include:
- template: License-Scanning.gitlab-ci.yml
license_scanning:
variables:
MAVEN_CLI_OPTS: -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true -Dmaven.wagon.http.ssl.insecure=true
```
Alternatively, you can use a Java key store to verify the TLS connection. For instructions on how to
generate a key store file, see the
[Maven Guide to Remote repository access through authenticated HTTPS](http://maven.apache.org/guides/mini/guide-repository-ssl.html).
### Selecting the version of Python ### Selecting the version of Python
> - [Introduced](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/36) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. > - [Introduced](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/36) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
...@@ -305,6 +321,9 @@ process: ...@@ -305,6 +321,9 @@ process:
1. Ensure the package registry is reachable from within the GitLab environment and that the package 1. Ensure the package registry is reachable from within the GitLab environment and that the package
manager is configured to use your preferred package registry. manager is configured to use your preferred package registry.
Additional [configuration](#using-private-maven-repos) may be needed for connecting to private Maven
repositories.
## Project policies for License Compliance ## Project policies for License Compliance
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/5940) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4. > [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/5940) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4.
......
...@@ -57,7 +57,7 @@ The following table depicts the various user permission levels in a project. ...@@ -57,7 +57,7 @@ The following table depicts the various user permission levels in a project.
| View Dependency list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | | View Dependency list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| View License list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | | View License list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| View licenses in Dependency list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | | View licenses in Dependency list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ | | View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
| View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | | View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | | Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| View GitLab Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control-core) | ✓ | ✓ | ✓ | ✓ | ✓ | | View GitLab Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control-core) | ✓ | ✓ | ✓ | ✓ | ✓ |
...@@ -84,15 +84,15 @@ The following table depicts the various user permission levels in a project. ...@@ -84,15 +84,15 @@ The following table depicts the various user permission levels in a project.
| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ | | See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| View project statistics | | ✓ | ✓ | ✓ | ✓ | | View project statistics | | ✓ | ✓ | ✓ | ✓ |
| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ | | View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
| Create/edit/delete [Releases](project/releases/index.md)| | | ✓ | ✓ | ✓ | | Create new merge request | | ✓ | ✓ | ✓ | ✓ |
| Pull from [Conan repository](packages/conan_repository/index.md), [Maven repository](packages/maven_repository/index.md), or [NPM registry](packages/npm_registry/index.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ | | Pull from [Conan repository](packages/conan_repository/index.md), [Maven repository](packages/maven_repository/index.md), or [NPM registry](packages/npm_registry/index.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
| Publish to [Conan repository](packages/conan_repository/index.md), [Maven repository](packages/maven_repository/index.md), or [NPM registry](packages/npm_registry/index.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ | | Publish to [Conan repository](packages/conan_repository/index.md), [Maven repository](packages/maven_repository/index.md), or [NPM registry](packages/npm_registry/index.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ | | Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ |
| Create/edit/delete [Releases](project/releases/index.md)| | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ | | Create new branches | | | ✓ | ✓ | ✓ |
| Push to non-protected branches | | | ✓ | ✓ | ✓ | | Push to non-protected branches | | | ✓ | ✓ | ✓ |
| Force push to non-protected branches | | | ✓ | ✓ | ✓ | | Force push to non-protected branches | | | ✓ | ✓ | ✓ |
| Remove non-protected branches | | | ✓ | ✓ | ✓ | | Remove non-protected branches | | | ✓ | ✓ | ✓ |
| Create new merge request | | ✓ | ✓ | ✓ | ✓ |
| Assign merge requests | | | ✓ | ✓ | ✓ | | Assign merge requests | | | ✓ | ✓ | ✓ |
| Label merge requests | | | ✓ | ✓ | ✓ | | Label merge requests | | | ✓ | ✓ | ✓ |
| Lock merge request threads | | | ✓ | ✓ | ✓ | | Lock merge request threads | | | ✓ | ✓ | ✓ |
...@@ -107,8 +107,12 @@ The following table depicts the various user permission levels in a project. ...@@ -107,8 +107,12 @@ The following table depicts the various user permission levels in a project.
| Remove a container registry image | | | ✓ | ✓ | ✓ | | Remove a container registry image | | | ✓ | ✓ | ✓ |
| Create/edit/delete project milestones | | | ✓ | ✓ | ✓ | | Create/edit/delete project milestones | | | ✓ | ✓ | ✓ |
| Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ | | Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| View vulnerabilities in Dependency list **(ULTIMATE)** | | | ✓ | ✓ | ✓ | | View vulnerability findings in Dependency list **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| Create issue from vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ | | Create issue from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| Dismiss vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| View vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| Create vulnerability from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| Resolve vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| Dismiss vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ | | Dismiss vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| Apply code change suggestions | | | ✓ | ✓ | ✓ | | Apply code change suggestions | | | ✓ | ✓ | ✓ |
| Create and edit wiki pages | | | ✓ | ✓ | ✓ | | Create and edit wiki pages | | | ✓ | ✓ | ✓ |
...@@ -217,21 +221,21 @@ group. ...@@ -217,21 +221,21 @@ group.
| View group epic **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ | | View group epic **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| Create/edit group epic **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | | Create/edit group epic **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
| Manage group labels | | ✓ | ✓ | ✓ | ✓ | | Manage group labels | | ✓ | ✓ | ✓ | ✓ |
| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| Create project in group | | | ✓ (3) | ✓ (3) | ✓ (3) | | Create project in group | | | ✓ (3) | ✓ (3) | ✓ (3) |
| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ | | Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| Enable/disable a dependency proxy **(PREMIUM)** | | | ✓ | ✓ | ✓ | | Enable/disable a dependency proxy **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ | | Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
| Create subgroup | | | | ✓ (1) | ✓ | | Create subgroup | | | | ✓ (1) | ✓ |
| Edit epic comments (posted by any user) **(ULTIMATE)** | | | | ✓ (2) | ✓ (2) |
| Edit group | | | | | ✓ | | Edit group | | | | | ✓ |
| Manage group level CI/CD variables | | | | | ✓ | | Manage group level CI/CD variables | | | | | ✓ |
| Manage group members | | | | | ✓ | | Manage group members | | | | | ✓ |
| Remove group | | | | | ✓ | | Remove group | | | | | ✓ |
| Delete group epic **(ULTIMATE)** | | | | | ✓ | | Delete group epic **(ULTIMATE)** | | | | | ✓ |
| Edit epic comments (posted by any user) **(ULTIMATE)** | | | | ✓ (2) | ✓ (2) |
| View group Audit Events | | | | | ✓ | | View group Audit Events | | | | | ✓ |
| Disable notification emails | | | | | ✓ | | Disable notification emails | | | | | ✓ |
| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
1. Groups can be set to [allow either Owners or Owners and 1. Groups can be set to [allow either Owners or Owners and
Maintainers to create subgroups](group/subgroups/index.md#creating-a-subgroup) Maintainers to create subgroups](group/subgroups/index.md#creating-a-subgroup)
......
...@@ -10,7 +10,7 @@ module Gitlab ...@@ -10,7 +10,7 @@ module Gitlab
# { # {
# 'action' => 'geo_proxy_to_primary', # 'action' => 'geo_proxy_to_primary',
# 'data' => { # 'data' => {
# 'api_endpoints' => %w{geo/proxy_git_push_ssh/info_refs geo/proxy_git_push_ssh/push}, # 'api_endpoints' => %w{geo/proxy_git_ssh/info_refs_receive_pack geo/proxy_git_ssh/receive_pack},
# 'gl_username' => user.username, # 'gl_username' => user.username,
# 'primary_repo' => geo_primary_http_url_to_repo(project_or_wiki) # 'primary_repo' => geo_primary_http_url_to_repo(project_or_wiki)
# } # }
......
...@@ -6,7 +6,7 @@ module Gitlab ...@@ -6,7 +6,7 @@ module Gitlab
attr_reader :project, :client, :formatter, :jira_project_key attr_reader :project, :client, :formatter, :jira_project_key
def initialize(project) def initialize(project)
raise Projects::ImportService::Error, _('Jira import feature is disabled.') unless Feature.enabled?(:jira_issue_import, project) raise Projects::ImportService::Error, _('Jira import feature is disabled.') unless project.jira_issues_import_feature_flag_enabled?
raise Projects::ImportService::Error, _('Jira integration not configured.') unless project.jira_service&.active? raise Projects::ImportService::Error, _('Jira integration not configured.') unless project.jira_service&.active?
@jira_project_key = project.latest_jira_import&.jira_project_key @jira_project_key = project.latest_jira_import&.jira_project_key
......
...@@ -9,6 +9,13 @@ module Gitlab ...@@ -9,6 +9,13 @@ module Gitlab
module ControllerConcern module ControllerConcern
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do
# Tracking events from the template is not ideal and we are moving this to the client in https://gitlab.com/gitlab-org/gitlab/-/issues/213712
# In the meantime, using this method from the view is frowned upon and this line will likely be removed
# in the near future
helper_method :track_event
end
protected protected
def track_event(action = action_name, **args) def track_event(action = action_name, **args)
......
...@@ -68,9 +68,11 @@ module Gitlab ...@@ -68,9 +68,11 @@ module Gitlab
clusters_enabled: count(::Clusters::Cluster.enabled), clusters_enabled: count(::Clusters::Cluster.enabled),
project_clusters_enabled: count(::Clusters::Cluster.enabled.project_type), project_clusters_enabled: count(::Clusters::Cluster.enabled.project_type),
group_clusters_enabled: count(::Clusters::Cluster.enabled.group_type), group_clusters_enabled: count(::Clusters::Cluster.enabled.group_type),
instance_clusters_enabled: count(::Clusters::Cluster.enabled.instance_type),
clusters_disabled: count(::Clusters::Cluster.disabled), clusters_disabled: count(::Clusters::Cluster.disabled),
project_clusters_disabled: count(::Clusters::Cluster.disabled.project_type), project_clusters_disabled: count(::Clusters::Cluster.disabled.project_type),
group_clusters_disabled: count(::Clusters::Cluster.disabled.group_type), group_clusters_disabled: count(::Clusters::Cluster.disabled.group_type),
instance_clusters_disabled: count(::Clusters::Cluster.disabled.instance_type),
clusters_platforms_eks: count(::Clusters::Cluster.aws_installed.enabled), clusters_platforms_eks: count(::Clusters::Cluster.aws_installed.enabled),
clusters_platforms_gke: count(::Clusters::Cluster.gcp_installed.enabled), clusters_platforms_gke: count(::Clusters::Cluster.gcp_installed.enabled),
clusters_platforms_user: count(::Clusters::Cluster.user_provided.enabled), clusters_platforms_user: count(::Clusters::Cluster.user_provided.enabled),
...@@ -83,6 +85,7 @@ module Gitlab ...@@ -83,6 +85,7 @@ module Gitlab
clusters_applications_knative: count(::Clusters::Applications::Knative.available), clusters_applications_knative: count(::Clusters::Applications::Knative.available),
clusters_applications_elastic_stack: count(::Clusters::Applications::ElasticStack.available), clusters_applications_elastic_stack: count(::Clusters::Applications::ElasticStack.available),
clusters_applications_jupyter: count(::Clusters::Applications::Jupyter.available), clusters_applications_jupyter: count(::Clusters::Applications::Jupyter.available),
clusters_management_project: count(::Clusters::Cluster.with_management_project),
in_review_folder: count(::Environment.in_review_folder), in_review_folder: count(::Environment.in_review_folder),
grafana_integrated_projects: count(GrafanaIntegration.enabled), grafana_integrated_projects: count(GrafanaIntegration.enabled),
groups: count(Group), groups: count(Group),
......
...@@ -931,6 +931,9 @@ msgstr "" ...@@ -931,6 +931,9 @@ msgstr ""
msgid "Accept terms" msgid "Accept terms"
msgstr "" msgstr ""
msgid "Acceptable for use in this project"
msgstr ""
msgid "Accepted MR" msgid "Accepted MR"
msgstr "" msgstr ""
...@@ -4001,6 +4004,9 @@ msgstr "" ...@@ -4001,6 +4004,9 @@ msgstr ""
msgid "Class" msgid "Class"
msgstr "" msgstr ""
msgid "Class:"
msgstr ""
msgid "Classification Label (optional)" msgid "Classification Label (optional)"
msgstr "" msgstr ""
...@@ -6645,6 +6651,11 @@ msgid_plural "Dependencies|%d vulnerabilities" ...@@ -6645,6 +6651,11 @@ msgid_plural "Dependencies|%d vulnerabilities"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more" msgid "Dependencies|%{remainingLicensesCount} more"
msgstr "" msgstr ""
...@@ -6684,6 +6695,9 @@ msgstr "" ...@@ -6684,6 +6695,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again." msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "" msgstr ""
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
msgid "Dependencies|Unsupported file(s) detected" msgid "Dependencies|Unsupported file(s) detected"
msgstr "" msgstr ""
...@@ -8999,6 +9013,9 @@ msgstr "" ...@@ -8999,6 +9013,9 @@ msgstr ""
msgid "File upload error." msgid "File upload error."
msgstr "" msgstr ""
msgid "File:"
msgstr ""
msgid "Files" msgid "Files"
msgstr "" msgstr ""
...@@ -12000,6 +12017,15 @@ msgstr "" ...@@ -12000,6 +12017,15 @@ msgstr ""
msgid "LicenseCompliance|You are about to remove the license, %{name}, from this project." msgid "LicenseCompliance|You are about to remove the license, %{name}, from this project."
msgstr "" msgstr ""
msgid "LicenseManagement|Allowed"
msgstr ""
msgid "LicenseManagement|Denied"
msgstr ""
msgid "LicenseManagement|Uncategorized"
msgstr ""
msgid "Licensed Features" msgid "Licensed Features"
msgstr "" msgstr ""
...@@ -12173,6 +12199,9 @@ msgstr "" ...@@ -12173,6 +12199,9 @@ msgstr ""
msgid "Localization" msgid "Localization"
msgstr "" msgstr ""
msgid "Location"
msgstr ""
msgid "Lock" msgid "Lock"
msgstr "" msgstr ""
...@@ -12752,6 +12781,9 @@ msgstr "" ...@@ -12752,6 +12781,9 @@ msgstr ""
msgid "Method" msgid "Method"
msgstr "" msgstr ""
msgid "Method:"
msgstr ""
msgid "Metric was successfully added." msgid "Metric was successfully added."
msgstr "" msgstr ""
...@@ -13556,6 +13588,9 @@ msgstr "" ...@@ -13556,6 +13588,9 @@ msgstr ""
msgid "No pods available" msgid "No pods available"
msgstr "" msgstr ""
msgid "No policy matches this license"
msgstr ""
msgid "No preview for this file type" msgid "No preview for this file type"
msgstr "" msgstr ""
...@@ -14086,6 +14121,9 @@ msgstr "" ...@@ -14086,6 +14121,9 @@ msgstr ""
msgid "Other visibility settings have been disabled by the administrator." msgid "Other visibility settings have been disabled by the administrator."
msgstr "" msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
msgid "Outbound requests" msgid "Outbound requests"
msgstr "" msgstr ""
...@@ -17850,9 +17888,6 @@ msgstr "" ...@@ -17850,9 +17888,6 @@ msgstr ""
msgid "SecurityConfiguration|Status" msgid "SecurityConfiguration|Status"
msgstr "" msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
msgid "SecurityDashboard|%{firstProject} and %{secondProject}" msgid "SecurityDashboard|%{firstProject} and %{secondProject}"
msgstr "" msgstr ""
...@@ -17913,6 +17948,9 @@ msgstr "" ...@@ -17913,6 +17948,9 @@ msgstr ""
msgid "SecurityDashboard|The security dashboard displays the latest security findings for projects you wish to monitor. Select \"Edit dashboard\" to add and remove projects." msgid "SecurityDashboard|The security dashboard displays the latest security findings for projects you wish to monitor. Select \"Edit dashboard\" to add and remove projects."
msgstr "" msgstr ""
msgid "SecurityDashboard|The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
msgid "SecurityDashboard|Unable to add %{invalidProjects}" msgid "SecurityDashboard|Unable to add %{invalidProjects}"
msgstr "" msgstr ""
...@@ -18324,6 +18362,12 @@ msgstr "" ...@@ -18324,6 +18362,12 @@ msgstr ""
msgid "Set up CI/CD" msgid "Set up CI/CD"
msgstr "" msgstr ""
msgid "Set up Jira Integration"
msgstr ""
msgid "Set up Jira Integration illustration"
msgstr ""
msgid "Set up a %{type} Runner automatically" msgid "Set up a %{type} Runner automatically"
msgstr "" msgstr ""
...@@ -23583,6 +23627,9 @@ msgstr "" ...@@ -23583,6 +23627,9 @@ msgstr ""
msgid "You will be removed from existing projects/groups" msgid "You will be removed from existing projects/groups"
msgstr "" msgstr ""
msgid "You will first need to set up Jira Integration to use this feature."
msgstr ""
msgid "You will lose all changes you've made to this file. This action cannot be undone." msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr "" msgstr ""
......
...@@ -13,7 +13,7 @@ describe Groups::SharedProjectsController do ...@@ -13,7 +13,7 @@ describe Groups::SharedProjectsController do
Projects::GroupLinks::CreateService.new( Projects::GroupLinks::CreateService.new(
project, project,
user, user,
link_group_access: ProjectGroupLink::DEVELOPER link_group_access: Gitlab::Access::DEVELOPER
).execute(group) ).execute(group)
end end
......
...@@ -4,6 +4,12 @@ FactoryBot.define do ...@@ -4,6 +4,12 @@ FactoryBot.define do
factory :group_group_link do factory :group_group_link do
shared_group { create(:group) } shared_group { create(:group) }
shared_with_group { create(:group) } shared_with_group { create(:group) }
group_access { GroupMember::DEVELOPER } group_access { Gitlab::Access::DEVELOPER }
trait(:guest) { group_access { Gitlab::Access::GUEST } }
trait(:reporter) { group_access { Gitlab::Access::REPORTER } }
trait(:developer) { group_access { Gitlab::Access::DEVELOPER } }
trait(:owner) { group_access { Gitlab::Access::OWNER } }
trait(:maintainer) { group_access { Gitlab::Access::MAINTAINER } }
end end
end end
...@@ -5,5 +5,10 @@ FactoryBot.define do ...@@ -5,5 +5,10 @@ FactoryBot.define do
project project
group group
expires_at { nil } expires_at { nil }
trait(:guest) { group_access { Gitlab::Access::GUEST } }
trait(:reporter) { group_access { Gitlab::Access::REPORTER } }
trait(:developer) { group_access { Gitlab::Access::DEVELOPER } }
trait(:maintainer) { group_access { Gitlab::Access::MAINTAINER } }
end end
end end
...@@ -39,12 +39,14 @@ FactoryBot.define do ...@@ -39,12 +39,14 @@ FactoryBot.define do
gcp_cluster = create(:cluster_provider_gcp, :created).cluster gcp_cluster = create(:cluster_provider_gcp, :created).cluster
create(:cluster_provider_aws, :created) create(:cluster_provider_aws, :created)
create(:cluster_platform_kubernetes) create(:cluster_platform_kubernetes)
create(:cluster, :management_project, management_project: projects[0])
create(:cluster, :group) create(:cluster, :group)
create(:cluster, :instance, :production_environment)
# Disabled clusters # Disabled clusters
create(:cluster, :disabled) create(:cluster, :disabled)
create(:cluster, :group, :disabled) create(:cluster, :group, :disabled)
create(:cluster, :group, :disabled) create(:cluster, :instance, :disabled)
# Applications # Applications
create(:clusters_applications_helm, :installed, cluster: gcp_cluster) create(:clusters_applications_helm, :installed, cluster: gcp_cluster)
......
...@@ -123,7 +123,7 @@ describe GroupDescendantsFinder do ...@@ -123,7 +123,7 @@ describe GroupDescendantsFinder do
project = create(:project, namespace: group) project = create(:project, namespace: group)
other_project = create(:project) other_project = create(:project)
other_project.project_group_links.create(group: group, other_project.project_group_links.create(group: group,
group_access: ProjectGroupLink::MAINTAINER) group_access: Gitlab::Access::MAINTAINER)
expect(finder.execute).to contain_exactly(project) expect(finder.execute).to contain_exactly(project)
end end
......
import { shallowMount } from '@vue/test-utils';
import JiraImportApp from '~/jira_import/components/jira_import_app.vue';
import JiraImportSetup from '~/jira_import/components/jira_import_setup.vue';
describe('JiraImportApp', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('set up Jira integration page', () => {
beforeEach(() => {
wrapper = shallowMount(JiraImportApp, {
propsData: {
isJiraConfigured: true,
projectPath: 'gitlab-org/gitlab-test',
setupIllustration: 'illustration.svg',
},
});
});
it('is shown when Jira integration is not configured', () => {
wrapper.setProps({
isJiraConfigured: false,
});
return wrapper.vm.$nextTick(() => {
expect(wrapper.find(JiraImportSetup).exists()).toBe(true);
});
});
it('is not shown when Jira integration is configured', () => {
expect(wrapper.find(JiraImportSetup).exists()).toBe(false);
});
});
});
import { shallowMount } from '@vue/test-utils';
import JiraImportSetup from '~/jira_import/components/jira_import_setup.vue';
describe('JiraImportSetup', () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(JiraImportSetup, {
propsData: {
illustration: 'illustration.svg',
},
});
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('displays a message to the user', () => {
const message = 'You will first need to set up Jira Integration to use this feature.';
expect(wrapper.find('p').text()).toBe(message);
});
it('contains button to set up Jira integration', () => {
expect(wrapper.find('a').text()).toBe('Set up Jira Integration');
});
});
...@@ -58,13 +58,14 @@ describe Gitlab::UsageData, :aggregate_failures do ...@@ -58,13 +58,14 @@ describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:issues_with_embedded_grafana_charts_approx]).to eq(2) expect(count_data[:issues_with_embedded_grafana_charts_approx]).to eq(2)
expect(count_data[:incident_issues]).to eq(4) expect(count_data[:incident_issues]).to eq(4)
expect(count_data[:clusters_enabled]).to eq(4) expect(count_data[:clusters_enabled]).to eq(6)
expect(count_data[:project_clusters_enabled]).to eq(3) expect(count_data[:project_clusters_enabled]).to eq(4)
expect(count_data[:group_clusters_enabled]).to eq(1) expect(count_data[:group_clusters_enabled]).to eq(1)
expect(count_data[:instance_clusters_enabled]).to eq(1)
expect(count_data[:clusters_disabled]).to eq(3) expect(count_data[:clusters_disabled]).to eq(3)
expect(count_data[:project_clusters_disabled]).to eq(1) expect(count_data[:project_clusters_disabled]).to eq(1)
expect(count_data[:group_clusters_disabled]).to eq(2) expect(count_data[:group_clusters_disabled]).to eq(1)
expect(count_data[:group_clusters_enabled]).to eq(1) expect(count_data[:instance_clusters_disabled]).to eq(1)
expect(count_data[:clusters_platforms_eks]).to eq(1) expect(count_data[:clusters_platforms_eks]).to eq(1)
expect(count_data[:clusters_platforms_gke]).to eq(1) expect(count_data[:clusters_platforms_gke]).to eq(1)
expect(count_data[:clusters_platforms_user]).to eq(1) expect(count_data[:clusters_platforms_user]).to eq(1)
...@@ -78,6 +79,7 @@ describe Gitlab::UsageData, :aggregate_failures do ...@@ -78,6 +79,7 @@ describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:clusters_applications_elastic_stack]).to eq(1) expect(count_data[:clusters_applications_elastic_stack]).to eq(1)
expect(count_data[:grafana_integrated_projects]).to eq(2) expect(count_data[:grafana_integrated_projects]).to eq(2)
expect(count_data[:clusters_applications_jupyter]).to eq(1) expect(count_data[:clusters_applications_jupyter]).to eq(1)
expect(count_data[:clusters_management_project]).to eq(1)
end end
it 'works when queries time out' do it 'works when queries time out' do
......
...@@ -156,6 +156,22 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do ...@@ -156,6 +156,22 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end end
end end
describe '.with_management_project' do
subject { described_class.with_management_project }
context 'cluster has a management project' do
let!(:cluster) { create(:cluster, :management_project) }
it { is_expected.to include(cluster) }
end
context 'cluster does not have a management project' do
let!(:cluster) { create(:cluster) }
it { is_expected.not_to include(cluster) }
end
end
describe '.for_project_namespace' do describe '.for_project_namespace' do
subject { described_class.for_project_namespace(namespace_id) } subject { described_class.for_project_namespace(namespace_id) }
......
...@@ -15,6 +15,22 @@ describe GroupGroupLink do ...@@ -15,6 +15,22 @@ describe GroupGroupLink do
it { is_expected.to belong_to(:shared_with_group) } it { is_expected.to belong_to(:shared_with_group) }
end end
describe 'scopes' do
describe '.non_guests' do
let!(:group_group_link_reporter) { create :group_group_link, :reporter }
let!(:group_group_link_maintainer) { create :group_group_link, :maintainer }
let!(:group_group_link_owner) { create :group_group_link, :owner }
let!(:group_group_link_guest) { create :group_group_link, :guest }
it 'returns all records which are greater than Guests access' do
expect(described_class.non_guests).to match_array([
group_group_link_reporter, group_group_link,
group_group_link_maintainer, group_group_link_owner
])
end
end
end
describe 'validation' do describe 'validation' do
it { is_expected.to validate_presence_of(:shared_group) } it { is_expected.to validate_presence_of(:shared_group) }
......
...@@ -32,6 +32,23 @@ describe ProjectGroupLink do ...@@ -32,6 +32,23 @@ describe ProjectGroupLink do
end end
end end
describe 'scopes' do
describe '.non_guests' do
let!(:project_group_link_reporter) { create :project_group_link, :reporter }
let!(:project_group_link_maintainer) { create :project_group_link, :maintainer }
let!(:project_group_link_developer) { create :project_group_link }
let!(:project_group_link_guest) { create :project_group_link, :guest }
it 'returns all records which are greater than Guests access' do
expect(described_class.non_guests).to match_array([
project_group_link_reporter,
project_group_link_developer,
project_group_link_maintainer
])
end
end
end
describe "destroying a record", :delete do describe "destroying a record", :delete do
it "refreshes group users' authorized projects" do it "refreshes group users' authorized projects" do
project = create(:project, :private) project = create(:project, :private)
......
...@@ -582,7 +582,7 @@ describe API::Internal::Base do ...@@ -582,7 +582,7 @@ describe API::Internal::Base do
{ {
'action' => 'geo_proxy_to_primary', 'action' => 'geo_proxy_to_primary',
'data' => { 'data' => {
'api_endpoints' => %w{geo/proxy_git_push_ssh/info_refs geo/proxy_git_push_ssh/push}, 'api_endpoints' => %w{geo/proxy_git_ssh/info_refs_receive_pack geo/proxy_git_ssh/receive_pack},
'gl_username' => 'testuser', 'gl_username' => 'testuser',
'primary_repo' => 'http://localhost:3000/testuser/repo.git' 'primary_repo' => 'http://localhost:3000/testuser/repo.git'
} }
......
...@@ -43,9 +43,11 @@ module UsageDataHelpers ...@@ -43,9 +43,11 @@ module UsageDataHelpers
clusters_enabled clusters_enabled
project_clusters_enabled project_clusters_enabled
group_clusters_enabled group_clusters_enabled
instance_clusters_enabled
clusters_disabled clusters_disabled
project_clusters_disabled project_clusters_disabled
group_clusters_disabled group_clusters_disabled
instance_clusters_disabled
clusters_platforms_eks clusters_platforms_eks
clusters_platforms_gke clusters_platforms_gke
clusters_platforms_user clusters_platforms_user
...@@ -58,6 +60,7 @@ module UsageDataHelpers ...@@ -58,6 +60,7 @@ module UsageDataHelpers
clusters_applications_knative clusters_applications_knative
clusters_applications_elastic_stack clusters_applications_elastic_stack
clusters_applications_jupyter clusters_applications_jupyter
clusters_management_project
in_review_folder in_review_folder
grafana_integrated_projects grafana_integrated_projects
groups groups
......
...@@ -52,6 +52,7 @@ RSpec.shared_examples 'a blob replicator' do ...@@ -52,6 +52,7 @@ RSpec.shared_examples 'a blob replicator' do
replicator.calculate_checksum! replicator.calculate_checksum!
expect(model_record.reload.verification_checksum).not_to be_nil expect(model_record.reload.verification_checksum).not_to be_nil
expect(model_record.reload.verified_at).not_to be_nil
end end
it 'saves the error message and increments retry counter' do it 'saves the error message and increments retry counter' do
......
...@@ -781,15 +781,15 @@ ...@@ -781,15 +781,15 @@
eslint-plugin-vue "^6.2.1" eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0" vue-eslint-parser "^7.0.0"
"@gitlab/svgs@1.117.0": "@gitlab/svgs@1.119.0":
version "1.117.0" version "1.119.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.117.0.tgz#05239ddcf529c62ca29e1ec1a25a7e24efb98207" resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.119.0.tgz#ff35c160b1e726f4f1702a4a152712fb669cde4e"
integrity sha512-dGy/VWuRAFCTZX3Yqu1+RnAHTSUWafteIk/RMfUCN9B/EMbYzjhYsNy0NLVoZ23Rj/KGv1bUGHvyQCoPP6VzpA== integrity sha512-bI+kewDLJy1N0//BpUPMx3h5AqG6lfIiV53lxQP9ttn8j/jhyxigZXq1wZ901PI4/ALv9IY1DOSSuLouK4sJsQ==
"@gitlab/ui@11.1.0": "@gitlab/ui@11.2.1":
version "11.1.0" version "11.2.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-11.1.0.tgz#72dd6d4309909fd1874f8abc42be8365e875822e" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-11.2.1.tgz#c031c92204eb2a6036ae3c7482387f66c75524fd"
integrity sha512-lmHTIUIYuUSGiisvnndhpUASvXZokP8/1LBfws9qkbEFPnMIvJAxGRHo3F7dLjcDBCvy4xepgDFFjI6HNFhLWA== integrity sha512-AhDPYmrBtaW6Qu+inSjoMCWx+Ou3CVIhhGAEjyVsAG7rSOilevVMZui2IlSb6fPtLcXS8F78DTWjp3R1YgxxbQ==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0" "@gitlab/vue-toasted" "^1.3.0"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment