Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
35305bfc83
commit
79c812847f
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
# Cop supports --autocorrect.
|
||||
Layout/LeadingCommentSpace:
|
||||
Exclude:
|
||||
- 'config/initializers/kaminari_active_record_relation_methods_with_limit.rb'
|
||||
- 'lib/uploaded_file.rb'
|
||||
|
|
@ -2,17 +2,6 @@
|
|||
# Cop supports --autocorrect.
|
||||
Layout/SpaceInsideParens:
|
||||
Exclude:
|
||||
- 'ee/app/models/ee/dependency_proxy/blob.rb'
|
||||
- 'ee/app/models/ee/dependency_proxy/manifest.rb'
|
||||
- 'ee/app/services/gitlab_subscriptions/notify_seats_exceeded_batch_service.rb'
|
||||
- 'ee/lib/ee/gitlab/auth/ldap/access.rb'
|
||||
- 'ee/lib/gitlab/auth/smartcard/session.rb'
|
||||
- 'ee/lib/system_check/geo/current_node_check.rb'
|
||||
- 'ee/spec/controllers/projects/mirrors_controller_spec.rb'
|
||||
- 'ee/spec/features/groups/saml_enforcement_spec.rb'
|
||||
- 'ee/spec/finders/ee/alert_management/http_integrations_finder_spec.rb'
|
||||
- 'ee/spec/finders/epics_finder_spec.rb'
|
||||
- 'ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb'
|
||||
- 'ee/spec/finders/security/vulnerability_feedbacks_finder_spec.rb'
|
||||
- 'ee/spec/frontend/fixtures/analytics/devops_reports/devops_adoption/enabled_namespaces.rb'
|
||||
- 'ee/spec/frontend/fixtures/epic.rb'
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -133,7 +133,7 @@ gem 'net-ldap', '~> 0.17.1' # rubocop:todo Gemfile/MissingFeatureCategory
|
|||
|
||||
# API
|
||||
gem 'grape', '~> 2.0.0', feature_category: :api
|
||||
gem 'grape-entity', '~> 0.10.2', feature_category: :api
|
||||
gem 'grape-entity', '~> 1.0.1', feature_category: :api
|
||||
gem 'grape-swagger', '~> 2.0.2', group: [:development, :test], feature_category: :api
|
||||
gem 'grape-swagger-entity', '~> 0.5.1', group: [:development, :test], feature_category: :api
|
||||
gem 'grape-path-helpers', '~> 2.0.1', feature_category: :api
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@
|
|||
{"name":"googleauth","version":"1.8.1","platform":"ruby","checksum":"814adadaaa1221dce72a67131e3ecbd6d23491a161ec84fb15fd353b87d8c9e7"},
|
||||
{"name":"gpgme","version":"2.0.23","platform":"ruby","checksum":"c87bbafdb8719da7c58ebcac08297aa1fb227022ac6cd2972829ba68adc91c04"},
|
||||
{"name":"grape","version":"2.0.0","platform":"ruby","checksum":"3aeff94c17e84ccead4ff98833df691e7da0c108878cc128ca31f80c1047494a"},
|
||||
{"name":"grape-entity","version":"0.10.2","platform":"ruby","checksum":"9eb584548135419d1c8ada7d21f7c174a7644e56a8b8e5bfc65d1a7a3421b571"},
|
||||
{"name":"grape-entity","version":"1.0.1","platform":"ruby","checksum":"e00f9e94e407aff77aa2945d741f544d07e48501927942988799913151d02634"},
|
||||
{"name":"grape-path-helpers","version":"2.0.1","platform":"ruby","checksum":"ad5216e52c6e796738a9118087352ab4c962900dbad1d8f8c0f96e093c6702d7"},
|
||||
{"name":"grape-swagger","version":"2.0.2","platform":"ruby","checksum":"a7139a56ba36fab2e8465f10d668a8c73c30cf44ebe8af960f5a4e3beb200805"},
|
||||
{"name":"grape-swagger-entity","version":"0.5.1","platform":"ruby","checksum":"f51e372d00ac96cf90d948f87b3f4eb287ab053976ca57ad503d442ad8605523"},
|
||||
|
|
|
|||
|
|
@ -846,7 +846,7 @@ GEM
|
|||
mustermann-grape (~> 1.0.0)
|
||||
rack (>= 1.3.0)
|
||||
rack-accept
|
||||
grape-entity (0.10.2)
|
||||
grape-entity (1.0.1)
|
||||
activesupport (>= 3.0.0)
|
||||
multi_json (>= 1.3.2)
|
||||
grape-path-helpers (2.0.1)
|
||||
|
|
@ -2047,7 +2047,7 @@ DEPENDENCIES
|
|||
googleauth (~> 1.8.1)
|
||||
gpgme (~> 2.0.23)
|
||||
grape (~> 2.0.0)
|
||||
grape-entity (~> 0.10.2)
|
||||
grape-entity (~> 1.0.1)
|
||||
grape-path-helpers (~> 2.0.1)
|
||||
grape-swagger (~> 2.0.2)
|
||||
grape-swagger-entity (~> 0.5.1)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
<script>
|
||||
import { GlBanner, GlTableLite, GlBadge } from '@gitlab/ui';
|
||||
import emptyStateIllustration from '@gitlab/svgs/dist/illustrations/lock_promotion.svg?url';
|
||||
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
|
||||
import { s__, __ } from '~/locale';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UserCalloutDismisser,
|
||||
GlBanner,
|
||||
GlTableLite,
|
||||
GlBadge,
|
||||
},
|
||||
props: {
|
||||
bannerTitle: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: s__('Deployment|Upgrade to get more our of your deployments'),
|
||||
},
|
||||
buttonText: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: __('Learn more'),
|
||||
},
|
||||
buttonLink: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: helpPagePath('ci/environments/deployment_approvals'),
|
||||
},
|
||||
illustration: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: emptyStateIllustration,
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{ key: 'approvers', label: s__('DeploymentApprovals|Approvers') },
|
||||
{ key: 'approvals', label: s__('DeploymentApprovals|Approvals') },
|
||||
{ key: 'approvedBy', label: s__('DeploymentApprovals|Approved By') },
|
||||
],
|
||||
items: [
|
||||
{ approvers: s__('Deployment|You'), approvals: '0/1' },
|
||||
{ approvers: s__('Deployment|A colleague'), approvals: '0/1' },
|
||||
],
|
||||
i18n: {
|
||||
bannerDescription: s__(
|
||||
'Deployment|Improve your continuous delivery practices with deployment approvals. Configure rules for required approvals, control which users can deploy to your environments, and collaborate throughout the delivery process.',
|
||||
),
|
||||
tableHeader: s__('Deployment|Deployment approvals require a Premium or Ultimate subscription'),
|
||||
readyText: s__('Deployment|Ready to use deployment approvals?'),
|
||||
premiumTitle: __('GitLab Premium'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<user-callout-dismisser feature-name="deployment_approvals_empty_state">
|
||||
<template #default="{ dismiss, shouldShowCallout }">
|
||||
<gl-banner
|
||||
v-if="shouldShowCallout"
|
||||
:title="bannerTitle"
|
||||
:button-text="buttonText"
|
||||
:button-link="buttonLink"
|
||||
:svg-path="illustration"
|
||||
class="gl-mt-5"
|
||||
@close="dismiss"
|
||||
>
|
||||
<p>{{ $options.i18n.bannerDescription }}</p>
|
||||
|
||||
<div class="gl-border-l gl-border-t gl-border-r gl-rounded-base gl-mb-5">
|
||||
<div class="gl-m-5">
|
||||
<slot name="table-header">
|
||||
<gl-badge size="md" class="gl-mr-2 gl-align-middle" icon="license" variant="tier">{{
|
||||
$options.i18n.premiumTitle
|
||||
}}</gl-badge>
|
||||
<strong class="gl-align-middle">{{ $options.i18n.tableHeader }}</strong>
|
||||
</slot>
|
||||
</div>
|
||||
<gl-table-lite :fields="$options.fields" :items="$options.items" />
|
||||
</div>
|
||||
|
||||
<template #actions>
|
||||
<slot name="banner-actions">
|
||||
<strong class="gl-ml-2 gl-align-middle">{{ $options.i18n.readyText }}</strong>
|
||||
</slot>
|
||||
</template>
|
||||
</gl-banner>
|
||||
</template>
|
||||
</user-callout-dismisser>
|
||||
</template>
|
||||
|
|
@ -23,6 +23,8 @@ export default {
|
|||
DeploymentApprovals: () =>
|
||||
import('ee_component/deployments/components/deployment_approvals.vue'),
|
||||
DeploymentTimeline: () => import('ee_component/deployments/components/deployment_timeline.vue'),
|
||||
ApprovalsEmptyState: () =>
|
||||
import('ee_else_ce/deployments/components/approvals_empty_state.vue'),
|
||||
},
|
||||
inject: ['projectPath', 'deploymentIid', 'environmentName', 'graphqlEtagKey'],
|
||||
apollo: {
|
||||
|
|
@ -70,6 +72,9 @@ export default {
|
|||
isManual() {
|
||||
return this.deployment.job?.manualJob;
|
||||
},
|
||||
isLoading() {
|
||||
return this.$apollo.queries.deployment.loading;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
toggleQueryPollingByVisibility(
|
||||
|
|
@ -99,7 +104,7 @@ export default {
|
|||
v-else
|
||||
:deployment="deployment"
|
||||
:environment="environment"
|
||||
:loading="$apollo.queries.deployment.loading"
|
||||
:loading="isLoading"
|
||||
/>
|
||||
<details-feedback class="gl-mt-6 gl-w-90p" />
|
||||
<deployment-approvals
|
||||
|
|
@ -119,10 +124,15 @@ export default {
|
|||
:approval-summary="deployment.approvalSummary"
|
||||
class="gl-w-90p"
|
||||
/>
|
||||
<approvals-empty-state
|
||||
v-if="!isLoading"
|
||||
:approval-summary="deployment.approvalSummary"
|
||||
class="gl-w-90p"
|
||||
/>
|
||||
</div>
|
||||
<deployment-aside
|
||||
v-if="!hasError"
|
||||
:loading="$apollo.queries.deployment.loading"
|
||||
:loading="isLoading"
|
||||
:deployment="deployment"
|
||||
:environment="environment"
|
||||
class="gl-w-20p"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createDefaultClient from '~/lib/graphql';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import ShowDeployment from './components/show_deployment.vue';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
|
@ -11,7 +12,14 @@ export const initializeShowDeployment = (selector = 'js-deployment-details') =>
|
|||
const apolloProvider = new VueApollo({
|
||||
defaultClient: createDefaultClient(),
|
||||
});
|
||||
const { projectPath, deploymentIid, environmentName, graphqlEtagKey } = el.dataset;
|
||||
const {
|
||||
projectPath,
|
||||
deploymentIid,
|
||||
environmentName,
|
||||
graphqlEtagKey,
|
||||
protectedEnvironmentsAvailable,
|
||||
protectedEnvironmentsSettingsPath,
|
||||
} = el.dataset;
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
|
|
@ -21,6 +29,8 @@ export const initializeShowDeployment = (selector = 'js-deployment-details') =>
|
|||
deploymentIid,
|
||||
environmentName,
|
||||
graphqlEtagKey,
|
||||
protectedEnvironmentsAvailable: parseBoolean(protectedEnvironmentsAvailable),
|
||||
protectedEnvironmentsSettingsPath,
|
||||
},
|
||||
render(h) {
|
||||
return h(ShowDeployment);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ import {
|
|||
} from '../utils/trigger_successful_invite_alert';
|
||||
|
||||
import {
|
||||
BLOCKED_SEAT_OVERAGES_ERROR_REASON,
|
||||
BLOCKED_SEAT_OVERAGES_BODY,
|
||||
BLOCKED_SEAT_OVERAGES_CTA,
|
||||
PROJECT_SELECT_LABEL_ID,
|
||||
IMPORT_PROJECT_MEMBERS_MODAL_TRACKING_CATEGORY,
|
||||
IMPORT_PROJECT_MEMBERS_MODAL_TRACKING_LABEL,
|
||||
|
|
@ -42,6 +45,11 @@ export default {
|
|||
label: IMPORT_PROJECT_MEMBERS_MODAL_TRACKING_LABEL,
|
||||
}),
|
||||
],
|
||||
inject: {
|
||||
addSeatsHref: {
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
props: {
|
||||
projectId: {
|
||||
type: String,
|
||||
|
|
@ -64,6 +72,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
errorReason: '',
|
||||
projectToBeImported: {},
|
||||
invalidFeedbackMessage: '',
|
||||
totalMembersCount: 0,
|
||||
|
|
@ -137,6 +146,9 @@ export default {
|
|||
count: this.errorsExpanded.length,
|
||||
});
|
||||
},
|
||||
shouldShowSeatOverageNotification() {
|
||||
return this.errorReason === BLOCKED_SEAT_OVERAGES_ERROR_REASON && this.addSeatsHref;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.reloadPageOnSubmit) {
|
||||
|
|
@ -178,8 +190,9 @@ export default {
|
|||
this.onInviteSuccess();
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error.response.data?.message;
|
||||
const { message, reason } = error.response.data || {};
|
||||
|
||||
this.errorReason = reason;
|
||||
this.showErrorAlert(message);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
|
|
@ -213,6 +226,7 @@ export default {
|
|||
this.track('click_x');
|
||||
},
|
||||
clearValidation() {
|
||||
this.errorReason = '';
|
||||
this.invalidFeedbackMessage = '';
|
||||
this.invalidMembers = {};
|
||||
},
|
||||
|
|
@ -240,6 +254,8 @@ export default {
|
|||
modalCancelButton: __('Cancel'),
|
||||
defaultError: s__('ImportAProjectModal|Unable to import project members'),
|
||||
successMessage: s__('ImportAProjectModal|Successfully imported'),
|
||||
BLOCKED_SEAT_OVERAGES_BODY,
|
||||
BLOCKED_SEAT_OVERAGES_CTA,
|
||||
},
|
||||
errorsLimit: 2,
|
||||
projectSelectLabelId: PROJECT_SELECT_LABEL_ID,
|
||||
|
|
@ -329,6 +345,18 @@ export default {
|
|||
>
|
||||
<project-select v-model="projectToBeImported" />
|
||||
</gl-form-group>
|
||||
<gl-alert
|
||||
v-if="shouldShowSeatOverageNotification"
|
||||
id="import-project-members-seat-overages-alert"
|
||||
class="gl-mb-4"
|
||||
dismissable
|
||||
data-testid="import-project-members-seat-overages-alert"
|
||||
:primary-button-link="addSeatsHref"
|
||||
:primary-button-text="$options.i18n.BLOCKED_SEAT_OVERAGES_CTA"
|
||||
@dismiss="errorReason = false"
|
||||
>
|
||||
{{ $options.i18n.BLOCKED_SEAT_OVERAGES_BODY }}
|
||||
</gl-alert>
|
||||
<p>{{ $options.i18n.modalHelpText }}</p>
|
||||
</gl-modal>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -9,12 +9,19 @@ export default function initImportProjectMembersModal() {
|
|||
return false;
|
||||
}
|
||||
|
||||
const { projectId, projectName, reloadPageOnSubmit, usersLimitDataset } = el.dataset;
|
||||
const {
|
||||
projectId,
|
||||
projectName,
|
||||
reloadPageOnSubmit,
|
||||
usersLimitDataset,
|
||||
addSeatsHref,
|
||||
} = el.dataset;
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
provide: {
|
||||
name: projectName,
|
||||
addSeatsHref,
|
||||
},
|
||||
render: (createElement) =>
|
||||
createElement(ImportProjectMembersModal, {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export default {
|
|||
i18n: {
|
||||
toggleLabelTitle: s__('CICD|Limit access %{italicStart}to%{italicEnd} this project'),
|
||||
toggleHelpText: s__(
|
||||
`CICD|Prevent access to this project from other project CI/CD job tokens, unless the other project is added to the allowlist. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API. %{linkStart}Learn more.%{linkEnd}`,
|
||||
`CICD|Prevent access to this project from other project CI/CD job tokens, unless the other project is added to the allowlist. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API. %{linkStart}Learn more%{linkEnd}.`,
|
||||
),
|
||||
cardHeaderTitle: s__(
|
||||
'CICD|Allow CI job tokens from the following projects to access this project',
|
||||
|
|
@ -218,9 +218,9 @@ export default {
|
|||
<template #help>
|
||||
<gl-sprintf :message="$options.i18n.toggleHelpText">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="ciJobTokenHelpPage" class="inline-link" target="_blank">
|
||||
{{ content }}
|
||||
</gl-link>
|
||||
<gl-link :href="ciJobTokenHelpPage" class="inline-link" target="_blank">{{
|
||||
content
|
||||
}}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -88,7 +88,8 @@ module Users
|
|||
duo_pro_trial_alert: 86, # EE-only
|
||||
deployment_details_feedback: 87,
|
||||
duo_chat_ga_alert: 88, # EE-only
|
||||
board_add_new_column_trigger_popover: 89
|
||||
board_add_new_column_trigger_popover: 89,
|
||||
deployment_approvals_empty_state: 90
|
||||
}
|
||||
|
||||
validates :feature_name,
|
||||
|
|
|
|||
|
|
@ -27,24 +27,5 @@ module Groups
|
|||
def remove_unallowed_params
|
||||
# overridden in EE
|
||||
end
|
||||
|
||||
# This is a temporary shim to address an issue with
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135959 and should
|
||||
# be removed when the issue is resolved.
|
||||
#
|
||||
# rubocop:disable Style/IfUnlessModifier -- you're entirely wrong
|
||||
# rubocop:disable Style/NegatedIf -- you're entirely wrong
|
||||
def invert_emails_disabled_to_emails_enabled
|
||||
return unless Feature.enabled?(:invert_emails_disabled_to_emails_enabled)
|
||||
return unless params.key?(:emails_disabled)
|
||||
|
||||
if !params[:emails_disabled].nil?
|
||||
params[:emails_enabled] = !Gitlab::Utils.to_boolean(params[:emails_disabled])
|
||||
end
|
||||
|
||||
params.delete(:emails_disabled)
|
||||
end
|
||||
# rubocop:enable Style/IfUnlessModifier
|
||||
# rubocop:enable Style/NegatedIf
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ module Groups
|
|||
|
||||
def build_group
|
||||
remove_unallowed_params
|
||||
invert_emails_disabled_to_emails_enabled
|
||||
|
||||
set_visibility_level
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ module Groups
|
|||
reject_parent_id!
|
||||
remove_unallowed_params
|
||||
|
||||
invert_emails_disabled_to_emails_enabled
|
||||
|
||||
before_assignment_hook(group, params)
|
||||
|
||||
if renaming_group_with_container_registry_images?
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ module Members
|
|||
|
||||
result
|
||||
rescue ArgumentError, ImportProjectTeamForbiddenError, SeatLimitExceededError => e
|
||||
ServiceResponse.error(message: e.message, reason: :unprocessable_entity)
|
||||
ServiceResponse.error(message: e.message, reason: e.class.name.demodulize.underscore.to_sym)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -34,7 +34,7 @@ module Members
|
|||
if members.is_a?(Array)
|
||||
members.each { |member| check_member_validity(member) }
|
||||
else
|
||||
@result = ServiceResponse.error(message: 'Import failed', reason: :unprocessable_entity)
|
||||
@result = ServiceResponse.error(message: 'Import failed', reason: :import_failed_error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,4 +6,6 @@
|
|||
#js-deployment-details{ data: { project_path: @project.full_path,
|
||||
environment_name: @environment.name,
|
||||
deployment_iid: @deployment.iid,
|
||||
graphql_etag_key: @environment.etag_cache_key } }
|
||||
graphql_etag_key: @environment.etag_cache_key,
|
||||
protected_environments_available: @project.licensed_feature_available?(:protected_environments).to_s,
|
||||
protected_environments_settings_path: can?(current_user, :admin_pipeline, @project) && project_settings_ci_cd_path(@project, anchor: 'js-protected-environments-settings') } }
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
.js-import-project-members-trigger{ data: { classes: 'gl-md-w-auto gl-w-full' } }
|
||||
.js-import-project-members-modal{ data: { project_id: @project.id,
|
||||
project_name: @project.name,
|
||||
reload_page_on_submit: true.to_s,
|
||||
users_limit_dataset: common_invite_modal_dataset(@project)[:users_limit_dataset] } }
|
||||
reload_page_on_submit: true.to_s }
|
||||
.merge(common_invite_modal_dataset(@project).slice(:users_limit_dataset, :add_seats_href)) }
|
||||
- invite_group_top_margin = 'gl-md-mt-0 gl-mt-3'
|
||||
- if @project.allowed_to_share_with_group?
|
||||
.js-invite-group-trigger{ data: { classes: "gl-md-w-auto gl-w-full gl-md-ml-3 #{invite_group_top_margin}", display_text: _('Invite a group') } }
|
||||
|
|
|
|||
|
|
@ -17,6 +17,14 @@
|
|||
- if @scope == 'projects'
|
||||
.term
|
||||
= render 'shared/projects/list', projects: @search_objects, pipeline_status: false
|
||||
- elsif @scope === 'users'
|
||||
%table.table.b-table.gl-table.b-table-stacked-md{ role: 'table' }
|
||||
%thead
|
||||
%tr
|
||||
%th= _('User')
|
||||
%th.text-right= _('Activity')
|
||||
%tbody
|
||||
= render_if_exists partial: "search/results/user", collection: @search_objects
|
||||
- else
|
||||
= render_if_exists partial: "search/results/#{@scope.singularize}", collection: @search_objects
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,20 @@
|
|||
%ul.content-list
|
||||
%li
|
||||
.avatar-cell
|
||||
= user_avatar(user: user, size: 40, user_name: user.name)
|
||||
.user-info
|
||||
= link_to user_path(user) do
|
||||
.item-title
|
||||
= simple_search_highlight_and_truncate(user.name, @search_term)
|
||||
= user_status(user)
|
||||
.cgray= simple_search_highlight_and_truncate(user.to_reference, @search_term)
|
||||
%tr
|
||||
%td{ data: { label: _('User') } }
|
||||
%div
|
||||
%div{ class: 'gl-display-inline-flex!' }
|
||||
= render Pajamas::AvatarComponent.new(user, size: 32, alt: '')
|
||||
.gl-ml-3{ class: 'gl-text-left!' }
|
||||
= link_to user_path(user), class: 'gl-text-body' do
|
||||
.gl-display-inline-block.gl-font-weight-bold= simple_search_highlight_and_truncate(user.name, @search_term)
|
||||
= user_status(user)
|
||||
%div{ class: 'gl-text-left!' }= simple_search_highlight_and_truncate(user.to_reference, @search_term)
|
||||
%td.gl-text-right{ data: { label: _('Activity') } }
|
||||
%div
|
||||
%span.gl-font-weight-bold= _('User created:')
|
||||
= l(user.created_at.to_date, format: :long)
|
||||
%div
|
||||
%span.gl-font-weight-bold= _('Last activity:')
|
||||
- if user.last_activity_on
|
||||
= l(user.last_activity_on.to_date, format: :long)
|
||||
- else
|
||||
= _('Never')
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
name: invert_emails_disabled_to_emails_enabled
|
||||
feature_issue_url:
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148577
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/454371
|
||||
milestone: '16.11'
|
||||
group: group::code review
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -10,7 +10,7 @@ module Kaminari
|
|||
# that limit the COUNT query to a configurable value to avoid query timeouts.
|
||||
# The default limit value is 10,000 records
|
||||
# rubocop: disable Gitlab/ModuleWithInstanceVariables
|
||||
def total_count_with_limit(column_name = :all, options = {}) #:nodoc:
|
||||
def total_count_with_limit(column_name = :all, options = {}) # :nodoc:
|
||||
return @total_count if defined?(@total_count) && @total_count
|
||||
|
||||
# There are some cases that total count can be deduced from loaded records
|
||||
|
|
|
|||
|
|
@ -957,6 +957,10 @@ response to events happening in the registry.
|
|||
Read more about the container registry notifications configuration options in the
|
||||
[Docker Registry notifications documentation](https://distribution.github.io/distribution/about/notifications/).
|
||||
|
||||
WARNING:
|
||||
Support for the `threshold` parameter was [deprecated](https://gitlab.com/gitlab-org/container-registry/-/issues/1243)
|
||||
in GitLab 17.0, and is planned for removal in 18.0. Use `maxretries` instead.
|
||||
|
||||
You can configure multiple endpoints for the container registry.
|
||||
|
||||
::Tabs
|
||||
|
|
@ -973,7 +977,8 @@ To configure a notification endpoint for a Linux package installation:
|
|||
'name' => 'test_endpoint',
|
||||
'url' => 'https://gitlab.example.com/notify',
|
||||
'timeout' => '500ms',
|
||||
'threshold' => 5,
|
||||
'threshold' => 5, # DEPRECATED: use `maxretries` instead.
|
||||
'maxretries' => 5,
|
||||
'backoff' => '1s',
|
||||
'headers' => {
|
||||
"Authorization" => ["AUTHORIZATION_EXAMPLE_TOKEN"]
|
||||
|
|
@ -999,7 +1004,8 @@ notifications:
|
|||
url: https://my.listener.com/event
|
||||
headers: <http.Header>
|
||||
timeout: 500
|
||||
threshold: 5
|
||||
threshold: 5 # DEPRECATED: use `maxretries` instead.
|
||||
maxretries: 5
|
||||
backoff: 1000
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -34414,6 +34414,7 @@ Name of the feature that the callout is for.
|
|||
| <a id="usercalloutfeaturenameenumci_deprecation_warning_for_types_keyword"></a>`CI_DEPRECATION_WARNING_FOR_TYPES_KEYWORD` | Callout feature name for ci_deprecation_warning_for_types_keyword. |
|
||||
| <a id="usercalloutfeaturenameenumcloud_licensing_subscription_activation_banner"></a>`CLOUD_LICENSING_SUBSCRIPTION_ACTIVATION_BANNER` | Callout feature name for cloud_licensing_subscription_activation_banner. |
|
||||
| <a id="usercalloutfeaturenameenumcluster_security_warning"></a>`CLUSTER_SECURITY_WARNING` | Callout feature name for cluster_security_warning. |
|
||||
| <a id="usercalloutfeaturenameenumdeployment_approvals_empty_state"></a>`DEPLOYMENT_APPROVALS_EMPTY_STATE` | Callout feature name for deployment_approvals_empty_state. |
|
||||
| <a id="usercalloutfeaturenameenumdeployment_details_feedback"></a>`DEPLOYMENT_DETAILS_FEEDBACK` | Callout feature name for deployment_details_feedback. |
|
||||
| <a id="usercalloutfeaturenameenumduo_chat_callout"></a>`DUO_CHAT_CALLOUT` | Callout feature name for duo_chat_callout. |
|
||||
| <a id="usercalloutfeaturenameenumduo_chat_ga_alert"></a>`DUO_CHAT_GA_ALERT` | Callout feature name for duo_chat_ga_alert. |
|
||||
|
|
|
|||
|
|
@ -31,6 +31,23 @@ in your local GitLab Development Kit or GitLab Docker instance.
|
|||
For a real-life example, refer to
|
||||
[this failed job](https://gitlab.com/gitlab-org/gitlab/-/jobs/6418619509#L4970).
|
||||
|
||||
#### Broken master
|
||||
|
||||
When a new required upgrade stop is added (every three or four milestones), it triggers the build of a new PostgreSQL Dump.
|
||||
In some cases, this might cause the `db:migrate:multi-version-upgrade` job to fail in `master` pipeline.
|
||||
For example, if new additional tables are seeded, it helps detect migration errors that might have been missed in older dumps without these seeded tables.
|
||||
|
||||
Workflow for the [broken master](https://handbook.gitlab.com/handbook/engineering/workflow/#broken-master) case:
|
||||
|
||||
1. Identify the root cause MR by searching for the migration that caused the error. For instance, [`db/migrate/20240416123401_add_security_policy_management_project_id_to_security_policies.rb` in failing job](https://gitlab.com/gitlab-org/gitlab-foss/-/jobs/6671417979#L1547)
|
||||
- Debug locally if needed as described in the [Database reconfigure failures](#database-reconfigure-failures)
|
||||
1. Reach out to the relevant team that introduced the migration to discuss whether the MR should be reverted or if a fix will be worked on
|
||||
- If the team isn't available, post about it in the `#database` Slack channel
|
||||
1. While a fix or revert is being worked on, `master` pipeline can be unblocked by disabling the job temporarily by setting `DISABLE_DB_MULTI_VERSION_UPGRADE=true` in [CI/CD Settings page](https://gitlab.com/gitlab-org/gitlab/-/settings/ci_cd)
|
||||
- When disabling the job, announce it in the `#master-broken` Slack channel
|
||||
1. Add a note to [job stability tracking issue#458402](https://gitlab.com/gitlab-org/gitlab/-/issues/458402)
|
||||
1. Reinstate the job by removing `DISABLE_DB_MULTI_VERSION_UPGRADE` from CI/CD Settings
|
||||
|
||||
### Database import failures
|
||||
|
||||
If job is failing on setup stage prior to `gitlab:db:configure`
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ When working with directories and files:
|
|||
1. When creating or renaming a file or directory and it has more than one word
|
||||
in its name, use underscores (`_`) instead of spaces or dashes. For example,
|
||||
proper naming would be `import_project/import_from_github.md`. This applies
|
||||
to both [image files](../styleguide/index.md#images) and Markdown files.
|
||||
to both [image files](../styleguide/index.md#illustrations) and Markdown files.
|
||||
1. Do not upload video files to the product repositories.
|
||||
[Link or embed videos](../styleguide/index.md#videos) instead.
|
||||
1. In the `doc/user/` directory:
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ Also, keep the following guidance in mind:
|
|||
use **custom settings for project integrations**.
|
||||
- Format [dates and times](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/date-time-terms)
|
||||
consistently and for an international audience.
|
||||
- Use [images](#images), including screenshots, sparingly.
|
||||
- Use [illustrations](#illustrations), including screenshots, sparingly.
|
||||
- For [UI text](#ui-text), allow for up to 30% expansion and contraction in translation.
|
||||
To see how much a string expands or contracts in another language, paste the string
|
||||
into [Google Translate](https://translate.google.com/) and review the results.
|
||||
|
|
@ -568,7 +568,7 @@ indentation as the list item. You can do this with:
|
|||
- [Code blocks](#code-blocks)
|
||||
- [Blockquotes](#blockquotes)
|
||||
- [Alert boxes](#alert-boxes)
|
||||
- [Images](#images)
|
||||
- [Illustrations](#illustrations)
|
||||
- [Tabs](#tabs)
|
||||
|
||||
Nested items should always align with the first character of the list
|
||||
|
|
@ -1121,21 +1121,71 @@ To describe multiple fields, use unordered list items:
|
|||
- **Branch name** must be a regular expression.
|
||||
- **User** must be a user with at least the **Maintainer** role.
|
||||
|
||||
## Images
|
||||
## Illustrations
|
||||
|
||||
Images, including screenshots, can help a reader better understand a concept.
|
||||
However, they should be used sparingly because:
|
||||
Use illustrations only to supplement text, not replace it.
|
||||
|
||||
- They tend to become out-of-date.
|
||||
- They are difficult and expensive to localize.
|
||||
- They cannot be read by screen readers.
|
||||
|
||||
When needed, use images to help the reader understand:
|
||||
Illustrations can help the reader understand:
|
||||
|
||||
- A concept.
|
||||
- Where they are in a complicated process.
|
||||
- How they should interact with the application.
|
||||
|
||||
### Capture the image
|
||||
Use illustrations sparingly because:
|
||||
|
||||
- They tend to become out-of-date.
|
||||
- They are difficult and expensive to localize.
|
||||
- Their content cannot be read by screen readers.
|
||||
|
||||
Types of illustrations used in GitLab documentation are:
|
||||
|
||||
- Diagram. Use a diagram to illustrate a process or the relationship between entities, for example.
|
||||
- Screenshot. Use a screenshot when you need to show a portion of the GitLab user interface.
|
||||
|
||||
Use a diagram instead of a screenshot when possible because:
|
||||
|
||||
- A diagram's file size is usually much smaller than that of a screenshot.
|
||||
- A screenshot often needs to be compressed, which generally reduces the image's quality.
|
||||
- A diagram in SVG format can be displayed at any size without affecting the image's quality.
|
||||
|
||||
### Diagram
|
||||
|
||||
Use a diagram to illustrate a process or the relationship between entities, for example.
|
||||
|
||||
Use [Mermaid](https://mermaid.js.org/#/) to create a diagram. This method has several advantages
|
||||
over a static image format (screenshot):
|
||||
|
||||
- The Mermaid format is easier to maintain because:
|
||||
- Their definition is stored as a code block in the documentation's Markdown source.
|
||||
- The diagram is rendered dynamically at runtime.
|
||||
- Text content that may change over time, such as feature names, can be found using text search
|
||||
tools and edited.
|
||||
- The diagram is rendered as an scalable image, better suited to various output devices and sizes.
|
||||
|
||||
#### Create a diagram
|
||||
|
||||
To create a diagram:
|
||||
|
||||
1. Use the [Mermaid Live Editor](https://mermaid.live/) to create the diagram.
|
||||
1. Copy the content of the **Code** pane into a `mermaid` code block in the Markdown file. For more
|
||||
details, see [Mermaid](../../../user/markdown.md#mermaid).
|
||||
1. To improve accessibility of diagrams, add a title and description. Add these lines on the next
|
||||
line after declaring the type of diagram, like `flowchart` or `sequenceDiagram`:
|
||||
|
||||
```yaml
|
||||
accTitle: your diagram title here
|
||||
accDescr: describe what your diagram does in a single sentence, with no line breaks.
|
||||
```
|
||||
|
||||
The Mermaid diagram syntax can be difficult to learn. To make this a little easier, see the Mermaid
|
||||
[Beginner's Guide](https://mermaid.js.org/intro/getting-started.html) and the examples on the
|
||||
Mermaid site.
|
||||
|
||||
### Screenshot
|
||||
|
||||
Use a screenshot when you need to show a portion of the GitLab user interface.
|
||||
|
||||
#### Capture the screenshot
|
||||
|
||||
When you take screenshots:
|
||||
|
||||
|
|
@ -1155,7 +1205,7 @@ When you take screenshots:
|
|||
a documentation page for a consistent reading experience. Ensure your navigation theme
|
||||
is **Indigo** and the syntax highlighting theme is **Light**. These are the default preferences.
|
||||
|
||||
### Add callouts
|
||||
#### Add callouts
|
||||
|
||||
If you need to emphasize an area in a screenshot, use an arrow.
|
||||
|
||||
|
|
@ -1166,7 +1216,7 @@ If you need to emphasize an area in a screenshot, use an arrow.
|
|||
|
||||

|
||||
|
||||
### Save the image
|
||||
#### Save the image
|
||||
|
||||
- Resize any wide or tall screenshots if needed, but make sure the screenshot is
|
||||
still clear after being resized and compressed.
|
||||
|
|
@ -1184,23 +1234,9 @@ If you need to emphasize an area in a screenshot, use an arrow.
|
|||
the `.md` document that you're working on is located.
|
||||
- Consider using PNG images instead of JPEG.
|
||||
- Compress GIFs with <https://ezgif.com/optimize> or similar tool.
|
||||
- Images should be used (only when necessary) to illustrate the description
|
||||
of a process, not to replace it.
|
||||
- See also how to link and embed [videos](#videos) to illustrate the documentation.
|
||||
|
||||
### Add the image link to content
|
||||
|
||||
The Markdown code for including an image in a document is:
|
||||
``
|
||||
|
||||
The image description is the alt text for the rendered image on the
|
||||
documentation site. For accessibility and SEO, use [descriptions](https://webaim.org/techniques/alttext/)
|
||||
that:
|
||||
|
||||
- Are accurate, succinct, and unique.
|
||||
- Don't use **image of** or **graphic of** to describe the image.
|
||||
|
||||
### Compress images
|
||||
#### Compress images
|
||||
|
||||
You should always compress any new images you add to the documentation. One
|
||||
known tool is [`pngquant`](https://pngquant.org/), which is cross-platform and
|
||||
|
|
@ -1239,7 +1275,7 @@ copy of `https://gitlab.com/gitlab-org/gitlab`, run in a terminal:
|
|||
bin/pngquant compress doc/user/img
|
||||
```
|
||||
|
||||
### Animated images
|
||||
#### Animated images
|
||||
|
||||
Avoid using animated images (such as animated GIFs). They can be distracting
|
||||
and annoying for users.
|
||||
|
|
@ -1250,7 +1286,18 @@ include a visual representation to help readers understand it, you can:
|
|||
- Use a static image (screenshot) and if necessary, add callouts to emphasize an area of the screen.
|
||||
- Create a short video of the interaction and link to it.
|
||||
|
||||
### Automatic screenshot generator
|
||||
#### Add the image link to content
|
||||
|
||||
The Markdown code for including an image in a document is:
|
||||
``
|
||||
|
||||
The image description is the alt text for the rendered image on the
|
||||
documentation site. For accessibility and SEO, use [descriptions](https://webaim.org/techniques/alttext/)
|
||||
that are accurate, succinct, and unique.
|
||||
|
||||
Don't use **image of** or **graphic of** to describe the image.
|
||||
|
||||
#### Automatic screenshot generator
|
||||
|
||||
You can use an automatic screenshot generator to take and compress screenshots.
|
||||
|
||||
|
|
@ -1262,7 +1309,7 @@ You can use an automatic screenshot generator to take and compress screenshots.
|
|||
1. Identify the location of the screenshots, based on the `gitlab/doc` location defined by the `it` parameter in your script.
|
||||
1. Commit the newly created screenshots.
|
||||
|
||||
#### Extending the tool
|
||||
##### Extending the tool
|
||||
|
||||
To add an additional screenshot generator:
|
||||
|
||||
|
|
@ -1289,7 +1336,7 @@ To add an additional screenshot generator:
|
|||
You can take a screenshot of a page with `visit <path>`.
|
||||
To avoid blank screenshots, use `expect` to wait for the content to load.
|
||||
|
||||
##### Single-element screenshots
|
||||
###### Single-element screenshots
|
||||
|
||||
You can take a screenshot of a single element.
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ do not use `Tutorial` in the title.
|
|||
## Screenshots
|
||||
|
||||
You can include screenshots in a tutorial to illustrate important steps in the process.
|
||||
In the core product documentation, you should [use screenshots sparingly](../styleguide/index.md#images).
|
||||
In the core product documentation, you should [use illustrations sparingly](../styleguide/index.md#illustrations).
|
||||
However, in tutorials, screenshots can help users understand where they are in a complex process.
|
||||
|
||||
Try to balance the number of screenshots in the tutorial so they don't disrupt
|
||||
|
|
|
|||
|
|
@ -204,7 +204,6 @@ possible selectors include:
|
|||
- A semantic attribute like `name` (also verifies that `name` was setup properly)
|
||||
- A `data-testid` attribute ([recommended by maintainers of `@vue/test-utils`](https://github.com/vuejs/vue-test-utils/issues/1498#issuecomment-610133465))
|
||||
optionally combined with [`shallowMountExtended` or `mountExtended`](#shallowmountextended-and-mountextended)
|
||||
- a Vue `ref` (if using `@vue/test-utils`)
|
||||
|
||||
```javascript
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'
|
||||
|
|
@ -223,9 +222,9 @@ it('exists', () => {
|
|||
wrapper.find('input[name=foo]');
|
||||
wrapper.find('[data-testid="my-foo-id"]');
|
||||
wrapper.findByTestId('my-foo-id'); // with shallowMountExtended or mountExtended – check below
|
||||
wrapper.find({ ref: 'foo'});
|
||||
|
||||
// Bad
|
||||
wrapper.find({ ref: 'foo'});
|
||||
wrapper.find('.js-foo');
|
||||
wrapper.find('.btn-primary');
|
||||
});
|
||||
|
|
@ -234,6 +233,7 @@ it('exists', () => {
|
|||
You should use `kebab-case` for `data-testid` attribute.
|
||||
|
||||
It is not recommended that you add `.js-*` classes just for testing purposes. Only do this if there are no other feasible options available.
|
||||
Avoid using Vue template refs to query DOM elements in tests because they're an implementation detail of the component, not a public API.
|
||||
|
||||
### Querying for child components
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
---
|
||||
stage: Data Stores
|
||||
group: Tenant Scale
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Get started organizing work with projects
|
||||
|
||||
In GitLab, the data related to a specific development effort goes in a project.
|
||||
The project serves as a central hub for collaboration, version control, and project management.
|
||||
|
||||
Projects provide the environment for managing and collaborating
|
||||
on software development projects, from planning and coding to testing and deployment.
|
||||
|
||||
Project creation and maintenance is part of a larger workflow:
|
||||
|
||||

|
||||
|
||||
## Step 1: Create a project
|
||||
|
||||
Start by creating a new project in GitLab to contain your codebase,
|
||||
documentation, and related resources.
|
||||
|
||||
A project contains a repository. A repository contains all the files,
|
||||
directories, and data related to your work.
|
||||
|
||||
Set the appropriate visibility level (public, internal, or private) for your project,
|
||||
based on your project's security and collaboration requirements.
|
||||
Configure project settings, like merge request approvals, issue tracking,
|
||||
and CI/CD pipelines, to align with your development workflow.
|
||||
|
||||
Use description templates to maintain consistency and provide essential information
|
||||
when creating issues, merge requests, or other project entities.
|
||||
|
||||
For more information, see:
|
||||
|
||||
- [Create a project](../project/index.md)
|
||||
- [Manage projects](../project/working_with_projects.md)
|
||||
- [Project visibility](../public_access.md)
|
||||
- [Project settings](../project/settings/index.md)
|
||||
- [Description templates](../project/description_templates.md)
|
||||
|
||||
## Step 2: Secure and control access to projects
|
||||
|
||||
To grant specific access rights to automated tools or external systems,
|
||||
helping ensure secure integration with your GitLab projects, generate project access tokens.
|
||||
|
||||
If you want to securely deploy your project to external systems,
|
||||
create deploy keys. These keys can grant read-only access to your repositories.
|
||||
|
||||
And finally, to provide temporary and limited access to
|
||||
your project's repository and registry, create deploy tokens, which
|
||||
help enable secure deployments and automation.
|
||||
|
||||
For more information, see:
|
||||
|
||||
- [Project access tokens](../project/settings/project_access_tokens.md)
|
||||
- [Deploy keys](../project/deploy_keys/index.md)
|
||||
- [Deploy tokens](../project/deploy_tokens/index.md)
|
||||
|
||||
## Step 3: Collaborate and share projects
|
||||
|
||||
You can invite multiple projects to a group, sometimes called
|
||||
`sharing a project with a group`. Each project has its own repository,
|
||||
issues, merge requests, and other features.
|
||||
When you have multiple projects in the same group, your team members can collaborate
|
||||
on specific projects while still maintaining
|
||||
a high-level overview of all the work being done in the group.
|
||||
|
||||
To further refine who has access to which projects, you can
|
||||
add subgroups to your group.
|
||||
|
||||
For more information, see:
|
||||
|
||||
- [Share projects](../project/members/share_project_with_groups.md)
|
||||
|
||||
## Step 4: Enhance project discoverability and recognition
|
||||
|
||||
To create a consistent and easily recognizable naming scheme for your projects,
|
||||
use reserved project and group names. Consistent names can help make projects
|
||||
more discoverable.
|
||||
|
||||
Use the search functionality to quickly find specific projects,
|
||||
issues, merge requests, or code snippets across your GitLab instance.
|
||||
|
||||
Another way to make your projects more discoverable is to add badges
|
||||
to your project's `README` file. Badges can display important information,
|
||||
like build status, test coverage, or version number. They provide a
|
||||
quick overview of your project's health and status.
|
||||
|
||||
And finally, topics are labels that you can assign to projects
|
||||
to help you organize and find them. You can assign a topic to several projects.
|
||||
|
||||
For more information, see:
|
||||
|
||||
- [Reserved project and group names](../reserved_names.md)
|
||||
- [Search](../search/index.md)
|
||||
- [Badges](../project/badges.md)
|
||||
- [Project topics](../project/project_topics.md)
|
||||
|
||||
## Step 5: Boost development efficiency and maintain code quality
|
||||
|
||||
Use the code intelligence features, like code navigation,
|
||||
hover information, and auto-completion, to enhance your productivity and
|
||||
maintain a high-quality codebase. Code intelligence is a range of tools
|
||||
that help you efficiently explore, analyze, and maintain your codebase.
|
||||
|
||||
To quickly locate and go to specific files in your project,
|
||||
use the file finder.
|
||||
|
||||
For more information, see:
|
||||
|
||||
- [Code intelligence](../project/code_intelligence.md)
|
||||
- [File finder](../project/repository/file_finder.md)
|
||||
|
||||
## Step 6: Migrate projects into GitLab
|
||||
|
||||
When necessary, use file exports to migrate projects to GitLab.
|
||||
You can migrate from other version control systems or GitLab instances.
|
||||
When you migrate a frequently accessed repository to GitLab, you can continue to
|
||||
access it by its original name by using a project alias.
|
||||
|
||||
On GitLab.com, you can transfer a project from one namespace to another,
|
||||
which is essentially moving it so that another group or team can have
|
||||
access or ownership.
|
||||
|
||||
For more information, see:
|
||||
|
||||
- [Migrate projects by using file exports](../project/import/index.md)
|
||||
- [Project aliases](../project/working_with_projects.md#project-aliases)
|
||||
- [Transfer a project to another namespace](../project/settings/migrate_projects.md)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
|
|
@ -26,7 +26,7 @@ It can assist various tasks of your daily work with the AI-generated content.
|
|||
> - GitLab self-managed users with a Premium or Ultimate subscription.
|
||||
> - GitLab Dedicated users.
|
||||
>
|
||||
> Eventually a subscription add-on will be required for continued access to GitLab Duo Chat.
|
||||
> Eventually a subscription add-on will be required for continued access to GitLab Duo Chat.
|
||||
> Learn more about [Duo Pro and Duo Enterprise pricing](https://about.gitlab.com/gitlab-duo/#pricing).
|
||||
|
||||
Here are examples of common use cases:
|
||||
|
|
@ -168,7 +168,7 @@ This feature is available in VS Code, JetBrains IDEs, and the Web IDE only.
|
|||
|
||||
`/tests` is a special command to generate a testing suggestion for the selected code in your editor.
|
||||
You can also add additional instructions to be considered, for example: `/tests using the Boost.Test framework`
|
||||
See [Use GitLab Duo Chat in the VS Code](#use-gitlab-duo-chat-in-vs-code) for more information.
|
||||
See [Use GitLab Duo Chat in VS Code](#use-gitlab-duo-chat-in-vs-code) for more information.
|
||||
|
||||
- Use a specific test framework, for example `/tests using the Boost.test framework` (C++) or `/tests using Jest` (JavaScript).
|
||||
- Focus on extreme test cases, for example `/tests focus on extreme cases, force regression testing`.
|
||||
|
|
@ -431,9 +431,13 @@ To use GitLab Duo Chat in the GitLab Duo plugin for JetBrains IDEs:
|
|||
1. In a JetBrains IDE, open a project.
|
||||
1. Open Chat by using one of the following methods:
|
||||
- On the right tool window bar, select **GitLab Duo Chat**.
|
||||
- In the file that you have open in the editor, select some code.
|
||||
- Use a keyboard shortcut: <kbd>ALT</kbd> + <kbd>d</kbd> on Windows and Linux, or
|
||||
<kbd>Option</kbd> + <kbd>d</kbd> on macOS.
|
||||
- In the file that you have open in the editor:
|
||||
1. Optional. Select some code.
|
||||
1. Right-click and select **GitLab Duo Chat**.
|
||||
1. Select **Explain Code** or **Generate Tests** or **Refactor Code**.
|
||||
1. Select **Open Chat Window**.
|
||||
1. Select **Explain Code**, **Generate Tests**, or **Refactor Code**.
|
||||
- Add keyboard or mouse shortcuts for each action under **Keymap** in the **Settings**.
|
||||
1. In the message box, enter your question and press **Enter** or select **Send**.
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ DETAILS:
|
|||
**Tier:** Free, Premium, Ultimate
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
|
||||
> - Searching by image repository name was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31322) in GitLab 13.0.
|
||||
|
||||
You can use the integrated container registry to store container images for each GitLab project.
|
||||
|
||||
To enable the container registry for your GitLab instance, see the [administrator documentation](../../../administration/packages/container_registry.md).
|
||||
|
|
|
|||
|
|
@ -99,16 +99,3 @@ Provide feedback on this experimental feature in [issue 408994](https://gitlab.c
|
|||
|
||||
- Contents of the file
|
||||
- The filename
|
||||
|
||||
<!--- start_remove The following content will be removed on remove_date: '2024-04-12' -->
|
||||
|
||||
## Generate suggested tests in merge requests
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/10366) in GitLab 16.0 as an [Experiment](../../../policy/experiment-beta-support.md#experiment).
|
||||
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141086) to GitLab Duo Chat in GitLab 16.8.
|
||||
|
||||
This feature was [moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141086)
|
||||
into GitLab Duo Chat in GitLab 16.8. Find more information in
|
||||
[Write tests in the IDE](../../gitlab_duo_chat.md#write-tests-in-the-ide).
|
||||
|
||||
<!--- end_remove -->
|
||||
|
|
|
|||
|
|
@ -59,20 +59,32 @@ module API
|
|||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
# This is a separate method so that EE can extend its behaviour, without
|
||||
# having to modify this code directly.
|
||||
#
|
||||
def create_group
|
||||
# This is a separate method so that EE can extend its behaviour, without
|
||||
# having to modify this code directly.
|
||||
::Groups::CreateService.new(current_user, declared_params(include_missing: false)).execute
|
||||
::Groups::CreateService
|
||||
.new(current_user, translate_params_for_compatibility)
|
||||
.execute
|
||||
end
|
||||
|
||||
# This is a separate method so that EE can extend its behaviour, without
|
||||
# having to modify this code directly.
|
||||
#
|
||||
def update_group(group)
|
||||
# This is a separate method so that EE can extend its behaviour, without
|
||||
# having to modify this code directly.
|
||||
::Groups::UpdateService
|
||||
.new(group, current_user, declared_params(include_missing: false))
|
||||
.new(group, current_user, translate_params_for_compatibility)
|
||||
.execute
|
||||
end
|
||||
|
||||
def translate_params_for_compatibility
|
||||
temp_params = declared_params(include_missing: false)
|
||||
|
||||
temp_params[:emails_enabled] = !temp_params.delete(:emails_disabled) if temp_params.key?(:emails_disabled)
|
||||
|
||||
temp_params
|
||||
end
|
||||
|
||||
def find_group_projects(params, finder_options)
|
||||
group = find_group!(params[:id])
|
||||
|
||||
|
|
|
|||
|
|
@ -833,8 +833,8 @@ module API
|
|||
|
||||
if result.success?
|
||||
{ status: result.status }
|
||||
elsif result.reason == :unprocessable_entity
|
||||
render_api_error!(result.message, result.reason)
|
||||
elsif result.reason
|
||||
render_structured_api_error!({ 'message' => result.message, 'reason' => result.reason }, :unprocessable_entity)
|
||||
else
|
||||
{ status: result.status, message: result.message, total_members_count: result.payload[:total_members_count] }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ module Gitlab
|
|||
module Validators
|
||||
class SchemaValidator
|
||||
SUPPORTED_VERSIONS = {
|
||||
cluster_image_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0],
|
||||
container_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0],
|
||||
coverage_fuzzing: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0],
|
||||
dast: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0],
|
||||
api_fuzzing: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0],
|
||||
dependency_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0],
|
||||
sast: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0],
|
||||
secret_detection: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0]
|
||||
cluster_image_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1],
|
||||
container_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1],
|
||||
coverage_fuzzing: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1],
|
||||
dast: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1],
|
||||
api_fuzzing: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1],
|
||||
dependency_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1],
|
||||
sast: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1],
|
||||
secret_detection: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1]
|
||||
}.freeze
|
||||
|
||||
VERSIONS_TO_REMOVE_IN_17_0 = %w[].freeze
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,998 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/container-scanning-report-format.json",
|
||||
"title": "Report format for GitLab Container Scanning",
|
||||
"description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
|
||||
"definitions": {
|
||||
"detail_type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/table"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/text"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/url"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/code"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/value"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/diff"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/markdown"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/commit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/file_location"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/module_location"
|
||||
}
|
||||
]
|
||||
},
|
||||
"text_value": {
|
||||
"type": "string"
|
||||
},
|
||||
"named_field": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"description": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"named_list": {
|
||||
"type": "object",
|
||||
"description": "An object with named and typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "named-list"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.*$": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_field"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"type": "object",
|
||||
"description": "A list of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "list"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"type": "object",
|
||||
"description": "A table of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"rows"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "table"
|
||||
},
|
||||
"header": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
},
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"text": {
|
||||
"type": "object",
|
||||
"description": "Raw text",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "text"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"type": "object",
|
||||
"description": "A single URL",
|
||||
"required": [
|
||||
"type",
|
||||
"href"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "url"
|
||||
},
|
||||
"text": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
},
|
||||
"href": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"http://mysite.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"code": {
|
||||
"type": "object",
|
||||
"description": "A codeblock",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "code"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"lang": {
|
||||
"type": "string",
|
||||
"description": "A programming language"
|
||||
}
|
||||
}
|
||||
},
|
||||
"value": {
|
||||
"type": "object",
|
||||
"description": "A field that can store a range of types of value",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "value"
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"number",
|
||||
"string",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"type": "object",
|
||||
"description": "A diff",
|
||||
"required": [
|
||||
"type",
|
||||
"before",
|
||||
"after"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "diff"
|
||||
},
|
||||
"before": {
|
||||
"type": "string"
|
||||
},
|
||||
"after": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"markdown": {
|
||||
"type": "object",
|
||||
"description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "markdown"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"examples": [
|
||||
"Here is markdown `inline code` #1 [test](gitlab.com)\n\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"description": "A commit/tag/branch within the GitLab project",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "commit"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The commit SHA",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"file_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a file in the project",
|
||||
"required": [
|
||||
"type",
|
||||
"file_name",
|
||||
"line_start"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "file-location"
|
||||
},
|
||||
"file_name": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"line_start": {
|
||||
"type": "integer"
|
||||
},
|
||||
"line_end": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"module_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a binary module of the form module+relative_offset",
|
||||
"required": [
|
||||
"type",
|
||||
"module_name",
|
||||
"offset"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "module-location"
|
||||
},
|
||||
"module_name": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"compiled_binary"
|
||||
]
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"examples": [
|
||||
100
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"self": {
|
||||
"version": "15.1.1"
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"scan",
|
||||
"version",
|
||||
"vulnerabilities"
|
||||
],
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"scan": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"analyzer",
|
||||
"end_time",
|
||||
"scanner",
|
||||
"start_time",
|
||||
"status",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-01-28T03:26:02"
|
||||
]
|
||||
},
|
||||
"messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Communication intended for the initiator of a scan.",
|
||||
"required": [
|
||||
"level",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "string",
|
||||
"description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
|
||||
"enum": [
|
||||
"info",
|
||||
"warn",
|
||||
"fatal"
|
||||
],
|
||||
"examples": [
|
||||
"info"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The message to communicate.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"Permission denied, scanning aborted"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "A configuration option used for this scan.",
|
||||
"required": [
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The configuration option name.",
|
||||
"maxLength": 255,
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"DAST_FF_ENABLE_BAS",
|
||||
"DOCKER_TLS_CERTDIR",
|
||||
"DS_MAX_DEPTH",
|
||||
"SECURE_LOG_LEVEL"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "The source of this option.",
|
||||
"enum": [
|
||||
"argument",
|
||||
"file",
|
||||
"env_variable",
|
||||
"other"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"integer",
|
||||
"null",
|
||||
"string"
|
||||
],
|
||||
"description": "The value used for this scan.",
|
||||
"examples": [
|
||||
true,
|
||||
2,
|
||||
null,
|
||||
"fatal",
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"analyzer": {
|
||||
"type": "object",
|
||||
"description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"gitlab-dast"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the analyzer, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab DAST"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://.+",
|
||||
"description": "A link to more information about the analyzer.",
|
||||
"examples": [
|
||||
"https://docs.gitlab.com/ee/user/application_security/dast"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the analyzer.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"scanner": {
|
||||
"type": "object",
|
||||
"description": "Object defining the scanner used to perform the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"my-sast-scanner"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the scanner, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"My SAST Scanner"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "A link to more information about the scanner.",
|
||||
"examples": [
|
||||
"https://scanner.url"
|
||||
]
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the scanner.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-02-14T16:01:59"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"success",
|
||||
"failure"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Type of the scan.",
|
||||
"enum": [
|
||||
"container_scanning",
|
||||
"container_scanning_for_registry"
|
||||
]
|
||||
},
|
||||
"primary_identifiers": {
|
||||
"type": "array",
|
||||
"description": "An unordered array containing an exhaustive list of primary identifiers for which the analyzer may return results",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"description": "URI pointing to the validating security report schema.",
|
||||
"pattern": "^https?://.+"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the schema to which the JSON report conforms.",
|
||||
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
||||
},
|
||||
"vulnerabilities": {
|
||||
"type": "array",
|
||||
"description": "Array of vulnerability objects.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Describes the vulnerability using GitLab Flavored Markdown",
|
||||
"required": [
|
||||
"id",
|
||||
"identifiers",
|
||||
"location"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"maxLength": 255,
|
||||
"description": "The name of the vulnerability. This must not include the finding's specific information."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 1048576,
|
||||
"description": "A long text section describing the vulnerability more fully."
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
|
||||
"enum": [
|
||||
"Info",
|
||||
"Unknown",
|
||||
"Low",
|
||||
"Medium",
|
||||
"High",
|
||||
"Critical"
|
||||
]
|
||||
},
|
||||
"solution": {
|
||||
"type": "string",
|
||||
"maxLength": 7000,
|
||||
"description": "Explanation of how to fix the vulnerability."
|
||||
},
|
||||
"identifiers": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cvss_vectors": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
"description": "An ordered array of CVSS vectors, each issued by a vendor to rate the vulnerability. The first item in the array is used as the primary CVSS vector, and is used to filter and sort the vulnerability.",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 16,
|
||||
"maxLength": 128,
|
||||
"pattern": "^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 32,
|
||||
"maxLength": 128,
|
||||
"pattern": "^CVSS:3[.][01]/((AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"description": "An array of references to external documentation or articles that describe the vulnerability.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the vulnerability details link."
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the vulnerability details document.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"$ref": "#/definitions/named_list/properties/items"
|
||||
},
|
||||
"tracking": {
|
||||
"type": "object",
|
||||
"description": "Describes how this vulnerability should be tracked as the project changes.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Declares that a series of items should be tracked using source-specific tracking methods.",
|
||||
"required": [
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "source"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "An item that should be tracked using source-specific tracking methods.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"signatures"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Path to the file where the vulnerability is located."
|
||||
},
|
||||
"start_line": {
|
||||
"type": "number",
|
||||
"description": "The first line of the file that includes the vulnerability."
|
||||
},
|
||||
"end_line": {
|
||||
"type": "number",
|
||||
"description": "The last line of the file that includes the vulnerability."
|
||||
},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"description": "An array of calculated tracking signatures for this tracking item.",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"description": "A calculated tracking signature value and metadata.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"algorithm",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"description": "The algorithm used to generate the signature."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The result of this signature algorithm."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Each tracking type must declare its own type."
|
||||
}
|
||||
}
|
||||
},
|
||||
"flags": {
|
||||
"description": "Flags that can be attached to vulnerabilities.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Informational flags identified and assigned to a vulnerability.",
|
||||
"required": [
|
||||
"type",
|
||||
"origin",
|
||||
"description"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"flagged-as-likely-false-positive"
|
||||
]
|
||||
},
|
||||
"origin": {
|
||||
"minLength": 1,
|
||||
"description": "Tool that issued the flag.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"minLength": 1,
|
||||
"description": "What the flag is about.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "object",
|
||||
"description": "Identifies the vulnerability's location.",
|
||||
"required": [
|
||||
"dependency",
|
||||
"operating_system",
|
||||
"image"
|
||||
],
|
||||
"properties": {
|
||||
"dependency": {
|
||||
"type": "object",
|
||||
"description": "Describes the dependency of a project where the vulnerability is located.",
|
||||
"required": [
|
||||
"package",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "object",
|
||||
"description": "Provides information on the package where the vulnerability is located.",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the package where the vulnerability is located."
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Version of the vulnerable package."
|
||||
},
|
||||
"direct": {
|
||||
"type": "boolean",
|
||||
"description": "Tells whether this is a direct, top-level dependency of the scanned project."
|
||||
}
|
||||
}
|
||||
},
|
||||
"operating_system": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "The operating system that contains the vulnerable package."
|
||||
},
|
||||
"image": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "The analyzed Docker image."
|
||||
},
|
||||
"default_branch_image": {
|
||||
"type": "string",
|
||||
"maxLength": 255,
|
||||
"description": "The name of the image on the default branch."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"remediations": {
|
||||
"type": "array",
|
||||
"description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"fixes",
|
||||
"summary",
|
||||
"diff"
|
||||
],
|
||||
"properties": {
|
||||
"fixes": {
|
||||
"type": "array",
|
||||
"description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "An overview of how the vulnerabilities were fixed."
|
||||
},
|
||||
"diff": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "A base64-encoded remediation code diff, compatible with git apply."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,975 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/coverage-fuzzing-report-format.json",
|
||||
"title": "Report format for GitLab Fuzz Testing",
|
||||
"description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
|
||||
"definitions": {
|
||||
"detail_type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/table"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/text"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/url"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/code"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/value"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/diff"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/markdown"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/commit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/file_location"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/module_location"
|
||||
}
|
||||
]
|
||||
},
|
||||
"text_value": {
|
||||
"type": "string"
|
||||
},
|
||||
"named_field": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"description": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"named_list": {
|
||||
"type": "object",
|
||||
"description": "An object with named and typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "named-list"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.*$": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_field"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"type": "object",
|
||||
"description": "A list of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "list"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"type": "object",
|
||||
"description": "A table of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"rows"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "table"
|
||||
},
|
||||
"header": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
},
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"text": {
|
||||
"type": "object",
|
||||
"description": "Raw text",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "text"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"type": "object",
|
||||
"description": "A single URL",
|
||||
"required": [
|
||||
"type",
|
||||
"href"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "url"
|
||||
},
|
||||
"text": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
},
|
||||
"href": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"http://mysite.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"code": {
|
||||
"type": "object",
|
||||
"description": "A codeblock",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "code"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"lang": {
|
||||
"type": "string",
|
||||
"description": "A programming language"
|
||||
}
|
||||
}
|
||||
},
|
||||
"value": {
|
||||
"type": "object",
|
||||
"description": "A field that can store a range of types of value",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "value"
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"number",
|
||||
"string",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"type": "object",
|
||||
"description": "A diff",
|
||||
"required": [
|
||||
"type",
|
||||
"before",
|
||||
"after"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "diff"
|
||||
},
|
||||
"before": {
|
||||
"type": "string"
|
||||
},
|
||||
"after": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"markdown": {
|
||||
"type": "object",
|
||||
"description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "markdown"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"examples": [
|
||||
"Here is markdown `inline code` #1 [test](gitlab.com)\n\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"description": "A commit/tag/branch within the GitLab project",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "commit"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The commit SHA",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"file_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a file in the project",
|
||||
"required": [
|
||||
"type",
|
||||
"file_name",
|
||||
"line_start"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "file-location"
|
||||
},
|
||||
"file_name": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"line_start": {
|
||||
"type": "integer"
|
||||
},
|
||||
"line_end": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"module_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a binary module of the form module+relative_offset",
|
||||
"required": [
|
||||
"type",
|
||||
"module_name",
|
||||
"offset"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "module-location"
|
||||
},
|
||||
"module_name": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"compiled_binary"
|
||||
]
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"examples": [
|
||||
100
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"self": {
|
||||
"version": "15.1.1"
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"scan",
|
||||
"version",
|
||||
"vulnerabilities"
|
||||
],
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"scan": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"analyzer",
|
||||
"end_time",
|
||||
"scanner",
|
||||
"start_time",
|
||||
"status",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-01-28T03:26:02"
|
||||
]
|
||||
},
|
||||
"messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Communication intended for the initiator of a scan.",
|
||||
"required": [
|
||||
"level",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "string",
|
||||
"description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
|
||||
"enum": [
|
||||
"info",
|
||||
"warn",
|
||||
"fatal"
|
||||
],
|
||||
"examples": [
|
||||
"info"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The message to communicate.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"Permission denied, scanning aborted"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "A configuration option used for this scan.",
|
||||
"required": [
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The configuration option name.",
|
||||
"maxLength": 255,
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"DAST_FF_ENABLE_BAS",
|
||||
"DOCKER_TLS_CERTDIR",
|
||||
"DS_MAX_DEPTH",
|
||||
"SECURE_LOG_LEVEL"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "The source of this option.",
|
||||
"enum": [
|
||||
"argument",
|
||||
"file",
|
||||
"env_variable",
|
||||
"other"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"integer",
|
||||
"null",
|
||||
"string"
|
||||
],
|
||||
"description": "The value used for this scan.",
|
||||
"examples": [
|
||||
true,
|
||||
2,
|
||||
null,
|
||||
"fatal",
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"analyzer": {
|
||||
"type": "object",
|
||||
"description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"gitlab-dast"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the analyzer, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab DAST"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://.+",
|
||||
"description": "A link to more information about the analyzer.",
|
||||
"examples": [
|
||||
"https://docs.gitlab.com/ee/user/application_security/dast"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the analyzer.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"scanner": {
|
||||
"type": "object",
|
||||
"description": "Object defining the scanner used to perform the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"my-sast-scanner"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the scanner, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"My SAST Scanner"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "A link to more information about the scanner.",
|
||||
"examples": [
|
||||
"https://scanner.url"
|
||||
]
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the scanner.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-02-14T16:01:59"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"success",
|
||||
"failure"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Type of the scan.",
|
||||
"enum": [
|
||||
"coverage_fuzzing"
|
||||
]
|
||||
},
|
||||
"primary_identifiers": {
|
||||
"type": "array",
|
||||
"description": "An unordered array containing an exhaustive list of primary identifiers for which the analyzer may return results",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"description": "URI pointing to the validating security report schema.",
|
||||
"pattern": "^https?://.+"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the schema to which the JSON report conforms.",
|
||||
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
||||
},
|
||||
"vulnerabilities": {
|
||||
"type": "array",
|
||||
"description": "Array of vulnerability objects.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Describes the vulnerability using GitLab Flavored Markdown",
|
||||
"required": [
|
||||
"id",
|
||||
"identifiers",
|
||||
"location"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"maxLength": 255,
|
||||
"description": "The name of the vulnerability. This must not include the finding's specific information."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 1048576,
|
||||
"description": "A long text section describing the vulnerability more fully."
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
|
||||
"enum": [
|
||||
"Info",
|
||||
"Unknown",
|
||||
"Low",
|
||||
"Medium",
|
||||
"High",
|
||||
"Critical"
|
||||
]
|
||||
},
|
||||
"solution": {
|
||||
"type": "string",
|
||||
"maxLength": 7000,
|
||||
"description": "Explanation of how to fix the vulnerability."
|
||||
},
|
||||
"identifiers": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cvss_vectors": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
"description": "An ordered array of CVSS vectors, each issued by a vendor to rate the vulnerability. The first item in the array is used as the primary CVSS vector, and is used to filter and sort the vulnerability.",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 16,
|
||||
"maxLength": 128,
|
||||
"pattern": "^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 32,
|
||||
"maxLength": 128,
|
||||
"pattern": "^CVSS:3[.][01]/((AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"description": "An array of references to external documentation or articles that describe the vulnerability.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the vulnerability details link."
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the vulnerability details document.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"$ref": "#/definitions/named_list/properties/items"
|
||||
},
|
||||
"tracking": {
|
||||
"type": "object",
|
||||
"description": "Describes how this vulnerability should be tracked as the project changes.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Declares that a series of items should be tracked using source-specific tracking methods.",
|
||||
"required": [
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "source"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "An item that should be tracked using source-specific tracking methods.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"signatures"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Path to the file where the vulnerability is located."
|
||||
},
|
||||
"start_line": {
|
||||
"type": "number",
|
||||
"description": "The first line of the file that includes the vulnerability."
|
||||
},
|
||||
"end_line": {
|
||||
"type": "number",
|
||||
"description": "The last line of the file that includes the vulnerability."
|
||||
},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"description": "An array of calculated tracking signatures for this tracking item.",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"description": "A calculated tracking signature value and metadata.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"algorithm",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"description": "The algorithm used to generate the signature."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The result of this signature algorithm."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Each tracking type must declare its own type."
|
||||
}
|
||||
}
|
||||
},
|
||||
"flags": {
|
||||
"description": "Flags that can be attached to vulnerabilities.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Informational flags identified and assigned to a vulnerability.",
|
||||
"required": [
|
||||
"type",
|
||||
"origin",
|
||||
"description"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"flagged-as-likely-false-positive"
|
||||
]
|
||||
},
|
||||
"origin": {
|
||||
"minLength": 1,
|
||||
"description": "Tool that issued the flag.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"minLength": 1,
|
||||
"description": "What the flag is about.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"description": "The location of the error",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"crash_address": {
|
||||
"type": "string",
|
||||
"description": "The relative address in memory were the crash occurred.",
|
||||
"examples": [
|
||||
"0xabababab"
|
||||
]
|
||||
},
|
||||
"stacktrace_snippet": {
|
||||
"type": "string",
|
||||
"description": "The stack trace recorded during fuzzing resulting the crash.",
|
||||
"examples": [
|
||||
"func_a+0xabcd\nfunc_b+0xabcc"
|
||||
]
|
||||
},
|
||||
"crash_state": {
|
||||
"type": "string",
|
||||
"description": "Minimised and normalized crash stack-trace (called crash_state).",
|
||||
"examples": [
|
||||
"func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
|
||||
]
|
||||
},
|
||||
"crash_type": {
|
||||
"type": "string",
|
||||
"description": "Type of the crash.",
|
||||
"examples": [
|
||||
"Heap-Buffer-overflow",
|
||||
"Division-by-zero"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"remediations": {
|
||||
"type": "array",
|
||||
"description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"fixes",
|
||||
"summary",
|
||||
"diff"
|
||||
],
|
||||
"properties": {
|
||||
"fixes": {
|
||||
"type": "array",
|
||||
"description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "An overview of how the vulnerabilities were fixed."
|
||||
},
|
||||
"diff": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "A base64-encoded remediation code diff, compatible with git apply."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,986 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/dependency-scanning-report-format.json",
|
||||
"title": "Report format for GitLab Dependency Scanning",
|
||||
"description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
|
||||
"definitions": {
|
||||
"detail_type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/table"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/text"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/url"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/code"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/value"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/diff"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/markdown"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/commit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/file_location"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/module_location"
|
||||
}
|
||||
]
|
||||
},
|
||||
"text_value": {
|
||||
"type": "string"
|
||||
},
|
||||
"named_field": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"description": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"named_list": {
|
||||
"type": "object",
|
||||
"description": "An object with named and typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "named-list"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.*$": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_field"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"type": "object",
|
||||
"description": "A list of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "list"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"type": "object",
|
||||
"description": "A table of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"rows"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "table"
|
||||
},
|
||||
"header": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
},
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"text": {
|
||||
"type": "object",
|
||||
"description": "Raw text",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "text"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"type": "object",
|
||||
"description": "A single URL",
|
||||
"required": [
|
||||
"type",
|
||||
"href"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "url"
|
||||
},
|
||||
"text": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
},
|
||||
"href": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"http://mysite.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"code": {
|
||||
"type": "object",
|
||||
"description": "A codeblock",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "code"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"lang": {
|
||||
"type": "string",
|
||||
"description": "A programming language"
|
||||
}
|
||||
}
|
||||
},
|
||||
"value": {
|
||||
"type": "object",
|
||||
"description": "A field that can store a range of types of value",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "value"
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"number",
|
||||
"string",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"type": "object",
|
||||
"description": "A diff",
|
||||
"required": [
|
||||
"type",
|
||||
"before",
|
||||
"after"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "diff"
|
||||
},
|
||||
"before": {
|
||||
"type": "string"
|
||||
},
|
||||
"after": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"markdown": {
|
||||
"type": "object",
|
||||
"description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "markdown"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"examples": [
|
||||
"Here is markdown `inline code` #1 [test](gitlab.com)\n\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"description": "A commit/tag/branch within the GitLab project",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "commit"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The commit SHA",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"file_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a file in the project",
|
||||
"required": [
|
||||
"type",
|
||||
"file_name",
|
||||
"line_start"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "file-location"
|
||||
},
|
||||
"file_name": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"line_start": {
|
||||
"type": "integer"
|
||||
},
|
||||
"line_end": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"module_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a binary module of the form module+relative_offset",
|
||||
"required": [
|
||||
"type",
|
||||
"module_name",
|
||||
"offset"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "module-location"
|
||||
},
|
||||
"module_name": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"compiled_binary"
|
||||
]
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"examples": [
|
||||
100
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"self": {
|
||||
"version": "15.1.1"
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"scan",
|
||||
"version",
|
||||
"vulnerabilities"
|
||||
],
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"scan": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"analyzer",
|
||||
"end_time",
|
||||
"scanner",
|
||||
"start_time",
|
||||
"status",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-01-28T03:26:02"
|
||||
]
|
||||
},
|
||||
"messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Communication intended for the initiator of a scan.",
|
||||
"required": [
|
||||
"level",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "string",
|
||||
"description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
|
||||
"enum": [
|
||||
"info",
|
||||
"warn",
|
||||
"fatal"
|
||||
],
|
||||
"examples": [
|
||||
"info"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The message to communicate.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"Permission denied, scanning aborted"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "A configuration option used for this scan.",
|
||||
"required": [
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The configuration option name.",
|
||||
"maxLength": 255,
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"DAST_FF_ENABLE_BAS",
|
||||
"DOCKER_TLS_CERTDIR",
|
||||
"DS_MAX_DEPTH",
|
||||
"SECURE_LOG_LEVEL"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "The source of this option.",
|
||||
"enum": [
|
||||
"argument",
|
||||
"file",
|
||||
"env_variable",
|
||||
"other"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"integer",
|
||||
"null",
|
||||
"string"
|
||||
],
|
||||
"description": "The value used for this scan.",
|
||||
"examples": [
|
||||
true,
|
||||
2,
|
||||
null,
|
||||
"fatal",
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"analyzer": {
|
||||
"type": "object",
|
||||
"description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"gitlab-dast"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the analyzer, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab DAST"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://.+",
|
||||
"description": "A link to more information about the analyzer.",
|
||||
"examples": [
|
||||
"https://docs.gitlab.com/ee/user/application_security/dast"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the analyzer.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"scanner": {
|
||||
"type": "object",
|
||||
"description": "Object defining the scanner used to perform the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"my-sast-scanner"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the scanner, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"My SAST Scanner"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "A link to more information about the scanner.",
|
||||
"examples": [
|
||||
"https://scanner.url"
|
||||
]
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the scanner.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-02-14T16:01:59"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"success",
|
||||
"failure"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Type of the scan.",
|
||||
"enum": [
|
||||
"dependency_scanning"
|
||||
]
|
||||
},
|
||||
"primary_identifiers": {
|
||||
"type": "array",
|
||||
"description": "An unordered array containing an exhaustive list of primary identifiers for which the analyzer may return results",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"description": "URI pointing to the validating security report schema.",
|
||||
"pattern": "^https?://.+"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the schema to which the JSON report conforms.",
|
||||
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
||||
},
|
||||
"vulnerabilities": {
|
||||
"type": "array",
|
||||
"description": "Array of vulnerability objects.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Describes the vulnerability using GitLab Flavored Markdown",
|
||||
"required": [
|
||||
"id",
|
||||
"identifiers",
|
||||
"location"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"maxLength": 255,
|
||||
"description": "The name of the vulnerability. This must not include the finding's specific information."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 1048576,
|
||||
"description": "A long text section describing the vulnerability more fully."
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
|
||||
"enum": [
|
||||
"Info",
|
||||
"Unknown",
|
||||
"Low",
|
||||
"Medium",
|
||||
"High",
|
||||
"Critical"
|
||||
]
|
||||
},
|
||||
"solution": {
|
||||
"type": "string",
|
||||
"maxLength": 7000,
|
||||
"description": "Explanation of how to fix the vulnerability."
|
||||
},
|
||||
"identifiers": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cvss_vectors": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
"description": "An ordered array of CVSS vectors, each issued by a vendor to rate the vulnerability. The first item in the array is used as the primary CVSS vector, and is used to filter and sort the vulnerability.",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 16,
|
||||
"maxLength": 128,
|
||||
"pattern": "^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 32,
|
||||
"maxLength": 128,
|
||||
"pattern": "^CVSS:3[.][01]/((AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"description": "An array of references to external documentation or articles that describe the vulnerability.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the vulnerability details link."
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the vulnerability details document.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"$ref": "#/definitions/named_list/properties/items"
|
||||
},
|
||||
"tracking": {
|
||||
"type": "object",
|
||||
"description": "Describes how this vulnerability should be tracked as the project changes.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Declares that a series of items should be tracked using source-specific tracking methods.",
|
||||
"required": [
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "source"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "An item that should be tracked using source-specific tracking methods.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"signatures"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Path to the file where the vulnerability is located."
|
||||
},
|
||||
"start_line": {
|
||||
"type": "number",
|
||||
"description": "The first line of the file that includes the vulnerability."
|
||||
},
|
||||
"end_line": {
|
||||
"type": "number",
|
||||
"description": "The last line of the file that includes the vulnerability."
|
||||
},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"description": "An array of calculated tracking signatures for this tracking item.",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"description": "A calculated tracking signature value and metadata.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"algorithm",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"description": "The algorithm used to generate the signature."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The result of this signature algorithm."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Each tracking type must declare its own type."
|
||||
}
|
||||
}
|
||||
},
|
||||
"flags": {
|
||||
"description": "Flags that can be attached to vulnerabilities.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Informational flags identified and assigned to a vulnerability.",
|
||||
"required": [
|
||||
"type",
|
||||
"origin",
|
||||
"description"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"flagged-as-likely-false-positive"
|
||||
]
|
||||
},
|
||||
"origin": {
|
||||
"minLength": 1,
|
||||
"description": "Tool that issued the flag.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"minLength": 1,
|
||||
"description": "What the flag is about.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "object",
|
||||
"description": "Identifies the vulnerability's location.",
|
||||
"required": [
|
||||
"file",
|
||||
"dependency"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
|
||||
},
|
||||
"dependency": {
|
||||
"type": "object",
|
||||
"description": "Describes the dependency of a project where the vulnerability is located.",
|
||||
"required": [
|
||||
"package",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "object",
|
||||
"description": "Provides information on the package where the vulnerability is located.",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the package where the vulnerability is located."
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Version of the vulnerable package."
|
||||
},
|
||||
"direct": {
|
||||
"type": "boolean",
|
||||
"description": "Tells whether this is a direct, top-level dependency of the scanned project."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"remediations": {
|
||||
"type": "array",
|
||||
"description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"fixes",
|
||||
"summary",
|
||||
"diff"
|
||||
],
|
||||
"properties": {
|
||||
"fixes": {
|
||||
"type": "array",
|
||||
"description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "An overview of how the vulnerabilities were fixed."
|
||||
},
|
||||
"diff": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "A base64-encoded remediation code diff, compatible with git apply."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,970 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/sast-report-format.json",
|
||||
"title": "Report format for GitLab SAST",
|
||||
"description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
|
||||
"definitions": {
|
||||
"detail_type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/table"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/text"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/url"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/code"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/value"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/diff"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/markdown"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/commit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/file_location"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/module_location"
|
||||
}
|
||||
]
|
||||
},
|
||||
"text_value": {
|
||||
"type": "string"
|
||||
},
|
||||
"named_field": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"description": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"named_list": {
|
||||
"type": "object",
|
||||
"description": "An object with named and typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "named-list"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.*$": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_field"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"type": "object",
|
||||
"description": "A list of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "list"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"type": "object",
|
||||
"description": "A table of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"rows"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "table"
|
||||
},
|
||||
"header": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
},
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"text": {
|
||||
"type": "object",
|
||||
"description": "Raw text",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "text"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"type": "object",
|
||||
"description": "A single URL",
|
||||
"required": [
|
||||
"type",
|
||||
"href"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "url"
|
||||
},
|
||||
"text": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
},
|
||||
"href": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"http://mysite.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"code": {
|
||||
"type": "object",
|
||||
"description": "A codeblock",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "code"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"lang": {
|
||||
"type": "string",
|
||||
"description": "A programming language"
|
||||
}
|
||||
}
|
||||
},
|
||||
"value": {
|
||||
"type": "object",
|
||||
"description": "A field that can store a range of types of value",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "value"
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"number",
|
||||
"string",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"type": "object",
|
||||
"description": "A diff",
|
||||
"required": [
|
||||
"type",
|
||||
"before",
|
||||
"after"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "diff"
|
||||
},
|
||||
"before": {
|
||||
"type": "string"
|
||||
},
|
||||
"after": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"markdown": {
|
||||
"type": "object",
|
||||
"description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "markdown"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"examples": [
|
||||
"Here is markdown `inline code` #1 [test](gitlab.com)\n\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"description": "A commit/tag/branch within the GitLab project",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "commit"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The commit SHA",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"file_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a file in the project",
|
||||
"required": [
|
||||
"type",
|
||||
"file_name",
|
||||
"line_start"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "file-location"
|
||||
},
|
||||
"file_name": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"line_start": {
|
||||
"type": "integer"
|
||||
},
|
||||
"line_end": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"module_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a binary module of the form module+relative_offset",
|
||||
"required": [
|
||||
"type",
|
||||
"module_name",
|
||||
"offset"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "module-location"
|
||||
},
|
||||
"module_name": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"compiled_binary"
|
||||
]
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"examples": [
|
||||
100
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"self": {
|
||||
"version": "15.1.1"
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"scan",
|
||||
"version",
|
||||
"vulnerabilities"
|
||||
],
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"scan": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"analyzer",
|
||||
"end_time",
|
||||
"scanner",
|
||||
"start_time",
|
||||
"status",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-01-28T03:26:02"
|
||||
]
|
||||
},
|
||||
"messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Communication intended for the initiator of a scan.",
|
||||
"required": [
|
||||
"level",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "string",
|
||||
"description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
|
||||
"enum": [
|
||||
"info",
|
||||
"warn",
|
||||
"fatal"
|
||||
],
|
||||
"examples": [
|
||||
"info"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The message to communicate.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"Permission denied, scanning aborted"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "A configuration option used for this scan.",
|
||||
"required": [
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The configuration option name.",
|
||||
"maxLength": 255,
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"DAST_FF_ENABLE_BAS",
|
||||
"DOCKER_TLS_CERTDIR",
|
||||
"DS_MAX_DEPTH",
|
||||
"SECURE_LOG_LEVEL"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "The source of this option.",
|
||||
"enum": [
|
||||
"argument",
|
||||
"file",
|
||||
"env_variable",
|
||||
"other"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"integer",
|
||||
"null",
|
||||
"string"
|
||||
],
|
||||
"description": "The value used for this scan.",
|
||||
"examples": [
|
||||
true,
|
||||
2,
|
||||
null,
|
||||
"fatal",
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"analyzer": {
|
||||
"type": "object",
|
||||
"description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"gitlab-dast"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the analyzer, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab DAST"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://.+",
|
||||
"description": "A link to more information about the analyzer.",
|
||||
"examples": [
|
||||
"https://docs.gitlab.com/ee/user/application_security/dast"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the analyzer.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"scanner": {
|
||||
"type": "object",
|
||||
"description": "Object defining the scanner used to perform the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"my-sast-scanner"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the scanner, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"My SAST Scanner"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "A link to more information about the scanner.",
|
||||
"examples": [
|
||||
"https://scanner.url"
|
||||
]
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the scanner.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-02-14T16:01:59"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"success",
|
||||
"failure"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Type of the scan.",
|
||||
"enum": [
|
||||
"sast"
|
||||
]
|
||||
},
|
||||
"primary_identifiers": {
|
||||
"type": "array",
|
||||
"description": "An unordered array containing an exhaustive list of primary identifiers for which the analyzer may return results",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"description": "URI pointing to the validating security report schema.",
|
||||
"pattern": "^https?://.+"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the schema to which the JSON report conforms.",
|
||||
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
||||
},
|
||||
"vulnerabilities": {
|
||||
"type": "array",
|
||||
"description": "Array of vulnerability objects.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Describes the vulnerability using GitLab Flavored Markdown",
|
||||
"required": [
|
||||
"id",
|
||||
"identifiers",
|
||||
"location"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"maxLength": 255,
|
||||
"description": "The name of the vulnerability. This must not include the finding's specific information."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 1048576,
|
||||
"description": "A long text section describing the vulnerability more fully."
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
|
||||
"enum": [
|
||||
"Info",
|
||||
"Unknown",
|
||||
"Low",
|
||||
"Medium",
|
||||
"High",
|
||||
"Critical"
|
||||
]
|
||||
},
|
||||
"solution": {
|
||||
"type": "string",
|
||||
"maxLength": 7000,
|
||||
"description": "Explanation of how to fix the vulnerability."
|
||||
},
|
||||
"identifiers": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cvss_vectors": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
"description": "An ordered array of CVSS vectors, each issued by a vendor to rate the vulnerability. The first item in the array is used as the primary CVSS vector, and is used to filter and sort the vulnerability.",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 16,
|
||||
"maxLength": 128,
|
||||
"pattern": "^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 32,
|
||||
"maxLength": 128,
|
||||
"pattern": "^CVSS:3[.][01]/((AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"description": "An array of references to external documentation or articles that describe the vulnerability.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the vulnerability details link."
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the vulnerability details document.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"$ref": "#/definitions/named_list/properties/items"
|
||||
},
|
||||
"tracking": {
|
||||
"type": "object",
|
||||
"description": "Describes how this vulnerability should be tracked as the project changes.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Declares that a series of items should be tracked using source-specific tracking methods.",
|
||||
"required": [
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "source"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "An item that should be tracked using source-specific tracking methods.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"signatures"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Path to the file where the vulnerability is located."
|
||||
},
|
||||
"start_line": {
|
||||
"type": "number",
|
||||
"description": "The first line of the file that includes the vulnerability."
|
||||
},
|
||||
"end_line": {
|
||||
"type": "number",
|
||||
"description": "The last line of the file that includes the vulnerability."
|
||||
},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"description": "An array of calculated tracking signatures for this tracking item.",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"description": "A calculated tracking signature value and metadata.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"algorithm",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"description": "The algorithm used to generate the signature."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The result of this signature algorithm."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Each tracking type must declare its own type."
|
||||
}
|
||||
}
|
||||
},
|
||||
"flags": {
|
||||
"description": "Flags that can be attached to vulnerabilities.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Informational flags identified and assigned to a vulnerability.",
|
||||
"required": [
|
||||
"type",
|
||||
"origin",
|
||||
"description"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"flagged-as-likely-false-positive"
|
||||
]
|
||||
},
|
||||
"origin": {
|
||||
"minLength": 1,
|
||||
"description": "Tool that issued the flag.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"minLength": 1,
|
||||
"description": "What the flag is about.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "object",
|
||||
"description": "Identifies the vulnerability's location.",
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Path to the file where the vulnerability is located."
|
||||
},
|
||||
"start_line": {
|
||||
"type": "number",
|
||||
"description": "The first line of the code affected by the vulnerability."
|
||||
},
|
||||
"end_line": {
|
||||
"type": "number",
|
||||
"description": "The last line of the code affected by the vulnerability."
|
||||
},
|
||||
"class": {
|
||||
"type": "string",
|
||||
"description": "Provides the name of the class where the vulnerability is located."
|
||||
},
|
||||
"method": {
|
||||
"type": "string",
|
||||
"description": "Provides the name of the method where the vulnerability is located."
|
||||
}
|
||||
}
|
||||
},
|
||||
"raw_source_code_extract": {
|
||||
"type": "string",
|
||||
"description": "Provides an unsanitized excerpt of the affected source code."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"remediations": {
|
||||
"type": "array",
|
||||
"description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"fixes",
|
||||
"summary",
|
||||
"diff"
|
||||
],
|
||||
"properties": {
|
||||
"fixes": {
|
||||
"type": "array",
|
||||
"description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "An overview of how the vulnerabilities were fixed."
|
||||
},
|
||||
"diff": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "A base64-encoded remediation code diff, compatible with git apply."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,994 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/secret-detection-report-format.json",
|
||||
"title": "Report format for GitLab Secret Detection",
|
||||
"description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
|
||||
"definitions": {
|
||||
"detail_type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/list"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/table"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/text"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/url"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/code"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/value"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/diff"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/markdown"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/commit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/file_location"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/module_location"
|
||||
}
|
||||
]
|
||||
},
|
||||
"text_value": {
|
||||
"type": "string"
|
||||
},
|
||||
"named_field": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"description": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"named_list": {
|
||||
"type": "object",
|
||||
"description": "An object with named and typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "named-list"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.*$": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/named_field"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"type": "object",
|
||||
"description": "A list of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "list"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"type": "object",
|
||||
"description": "A table of typed fields",
|
||||
"required": [
|
||||
"type",
|
||||
"rows"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "table"
|
||||
},
|
||||
"header": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
},
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/detail_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"text": {
|
||||
"type": "object",
|
||||
"description": "Raw text",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "text"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"type": "object",
|
||||
"description": "A single URL",
|
||||
"required": [
|
||||
"type",
|
||||
"href"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "url"
|
||||
},
|
||||
"text": {
|
||||
"$ref": "#/definitions/text_value"
|
||||
},
|
||||
"href": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"http://mysite.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"code": {
|
||||
"type": "object",
|
||||
"description": "A codeblock",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "code"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"lang": {
|
||||
"type": "string",
|
||||
"description": "A programming language"
|
||||
}
|
||||
}
|
||||
},
|
||||
"value": {
|
||||
"type": "object",
|
||||
"description": "A field that can store a range of types of value",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "value"
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"number",
|
||||
"string",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"type": "object",
|
||||
"description": "A diff",
|
||||
"required": [
|
||||
"type",
|
||||
"before",
|
||||
"after"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "diff"
|
||||
},
|
||||
"before": {
|
||||
"type": "string"
|
||||
},
|
||||
"after": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"markdown": {
|
||||
"type": "object",
|
||||
"description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "markdown"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "#/definitions/text_value",
|
||||
"examples": [
|
||||
"Here is markdown `inline code` #1 [test](gitlab.com)\n\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"description": "A commit/tag/branch within the GitLab project",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "commit"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The commit SHA",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"file_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a file in the project",
|
||||
"required": [
|
||||
"type",
|
||||
"file_name",
|
||||
"line_start"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "file-location"
|
||||
},
|
||||
"file_name": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"line_start": {
|
||||
"type": "integer"
|
||||
},
|
||||
"line_end": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"module_location": {
|
||||
"type": "object",
|
||||
"description": "A location within a binary module of the form module+relative_offset",
|
||||
"required": [
|
||||
"type",
|
||||
"module_name",
|
||||
"offset"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "module-location"
|
||||
},
|
||||
"module_name": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"compiled_binary"
|
||||
]
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"examples": [
|
||||
100
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"self": {
|
||||
"version": "15.1.1"
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"scan",
|
||||
"version",
|
||||
"vulnerabilities"
|
||||
],
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"scan": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"analyzer",
|
||||
"end_time",
|
||||
"scanner",
|
||||
"start_time",
|
||||
"status",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-01-28T03:26:02"
|
||||
]
|
||||
},
|
||||
"messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Communication intended for the initiator of a scan.",
|
||||
"required": [
|
||||
"level",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "string",
|
||||
"description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
|
||||
"enum": [
|
||||
"info",
|
||||
"warn",
|
||||
"fatal"
|
||||
],
|
||||
"examples": [
|
||||
"info"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The message to communicate.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"Permission denied, scanning aborted"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "A configuration option used for this scan.",
|
||||
"required": [
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The configuration option name.",
|
||||
"maxLength": 255,
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"DAST_FF_ENABLE_BAS",
|
||||
"DOCKER_TLS_CERTDIR",
|
||||
"DS_MAX_DEPTH",
|
||||
"SECURE_LOG_LEVEL"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "The source of this option.",
|
||||
"enum": [
|
||||
"argument",
|
||||
"file",
|
||||
"env_variable",
|
||||
"other"
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"integer",
|
||||
"null",
|
||||
"string"
|
||||
],
|
||||
"description": "The value used for this scan.",
|
||||
"examples": [
|
||||
true,
|
||||
2,
|
||||
null,
|
||||
"fatal",
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"analyzer": {
|
||||
"type": "object",
|
||||
"description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"gitlab-dast"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the analyzer, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab DAST"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://.+",
|
||||
"description": "A link to more information about the analyzer.",
|
||||
"examples": [
|
||||
"https://docs.gitlab.com/ee/user/application_security/dast"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the analyzer.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the analyzer.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"scanner": {
|
||||
"type": "object",
|
||||
"description": "Object defining the scanner used to perform the scan.",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"version",
|
||||
"vendor"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique id that identifies the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"my-sast-scanner"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A human readable value that identifies the scanner, not required to be unique.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"My SAST Scanner"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "A link to more information about the scanner.",
|
||||
"examples": [
|
||||
"https://scanner.url"
|
||||
]
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the scanner.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"1.0.2"
|
||||
]
|
||||
},
|
||||
"vendor": {
|
||||
"description": "The vendor/maintainer of the scanner.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the vendor.",
|
||||
"minLength": 1,
|
||||
"examples": [
|
||||
"GitLab"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string",
|
||||
"description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
|
||||
"examples": [
|
||||
"2020-02-14T16:01:59"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"success",
|
||||
"failure"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Type of the scan.",
|
||||
"enum": [
|
||||
"secret_detection"
|
||||
]
|
||||
},
|
||||
"primary_identifiers": {
|
||||
"type": "array",
|
||||
"description": "An unordered array containing an exhaustive list of primary identifiers for which the analyzer may return results",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"description": "URI pointing to the validating security report schema.",
|
||||
"pattern": "^https?://.+"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "The version of the schema to which the JSON report conforms.",
|
||||
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
||||
},
|
||||
"vulnerabilities": {
|
||||
"type": "array",
|
||||
"description": "Array of vulnerability objects.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Describes the vulnerability using GitLab Flavored Markdown",
|
||||
"required": [
|
||||
"id",
|
||||
"identifiers",
|
||||
"location"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"maxLength": 255,
|
||||
"description": "The name of the vulnerability. This must not include the finding's specific information."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 1048576,
|
||||
"description": "A long text section describing the vulnerability more fully."
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
|
||||
"enum": [
|
||||
"Info",
|
||||
"Unknown",
|
||||
"Low",
|
||||
"Medium",
|
||||
"High",
|
||||
"Critical"
|
||||
]
|
||||
},
|
||||
"solution": {
|
||||
"type": "string",
|
||||
"maxLength": 7000,
|
||||
"description": "Explanation of how to fix the vulnerability."
|
||||
},
|
||||
"identifiers": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
|
||||
"minLength": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the identifier.",
|
||||
"minLength": 1
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the identifier's documentation.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Value of the identifier, for matching purpose.",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cvss_vectors": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
"description": "An ordered array of CVSS vectors, each issued by a vendor to rate the vulnerability. The first item in the array is used as the primary CVSS vector, and is used to filter and sort the vulnerability.",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 16,
|
||||
"maxLength": 128,
|
||||
"pattern": "^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"default": "unknown"
|
||||
},
|
||||
"vector": {
|
||||
"type": "string",
|
||||
"minLength": 32,
|
||||
"maxLength": 128,
|
||||
"pattern": "^CVSS:3[.][01]/((AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"vendor",
|
||||
"vector"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"description": "An array of references to external documentation or articles that describe the vulnerability.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the vulnerability details link."
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL of the vulnerability details document.",
|
||||
"pattern": "^(https?|ftp)://.+"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"$ref": "#/definitions/named_list/properties/items"
|
||||
},
|
||||
"tracking": {
|
||||
"type": "object",
|
||||
"description": "Describes how this vulnerability should be tracked as the project changes.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Declares that a series of items should be tracked using source-specific tracking methods.",
|
||||
"required": [
|
||||
"items"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "source"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "An item that should be tracked using source-specific tracking methods.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"signatures"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Path to the file where the vulnerability is located."
|
||||
},
|
||||
"start_line": {
|
||||
"type": "number",
|
||||
"description": "The first line of the file that includes the vulnerability."
|
||||
},
|
||||
"end_line": {
|
||||
"type": "number",
|
||||
"description": "The last line of the file that includes the vulnerability."
|
||||
},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"description": "An array of calculated tracking signatures for this tracking item.",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"description": "A calculated tracking signature value and metadata.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"algorithm",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"description": "The algorithm used to generate the signature."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "The result of this signature algorithm."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Each tracking type must declare its own type."
|
||||
}
|
||||
}
|
||||
},
|
||||
"flags": {
|
||||
"description": "Flags that can be attached to vulnerabilities.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "Informational flags identified and assigned to a vulnerability.",
|
||||
"required": [
|
||||
"type",
|
||||
"origin",
|
||||
"description"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Result of the scan.",
|
||||
"enum": [
|
||||
"flagged-as-likely-false-positive"
|
||||
]
|
||||
},
|
||||
"origin": {
|
||||
"minLength": 1,
|
||||
"description": "Tool that issued the flag.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"minLength": 1,
|
||||
"description": "What the flag is about.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"required": [
|
||||
"commit"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Path to the file where the vulnerability is located"
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"description": "Represents the commit in which the vulnerability was detected",
|
||||
"required": [
|
||||
"sha"
|
||||
],
|
||||
"properties": {
|
||||
"author": {
|
||||
"type": "string"
|
||||
},
|
||||
"date": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"sha": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"start_line": {
|
||||
"type": "number",
|
||||
"description": "The first line of the code affected by the vulnerability"
|
||||
},
|
||||
"end_line": {
|
||||
"type": "number",
|
||||
"description": "The last line of the code affected by the vulnerability"
|
||||
},
|
||||
"class": {
|
||||
"type": "string",
|
||||
"description": "Provides the name of the class where the vulnerability is located"
|
||||
},
|
||||
"method": {
|
||||
"type": "string",
|
||||
"description": "Provides the name of the method where the vulnerability is located"
|
||||
}
|
||||
}
|
||||
},
|
||||
"raw_source_code_extract": {
|
||||
"type": "string",
|
||||
"description": "Provides an unsanitized excerpt of the affected source code."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"remediations": {
|
||||
"type": "array",
|
||||
"description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"fixes",
|
||||
"summary",
|
||||
"diff"
|
||||
],
|
||||
"properties": {
|
||||
"fixes": {
|
||||
"type": "array",
|
||||
"description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
|
||||
"examples": [
|
||||
"642735a5-1425-428d-8d4e-3c854885a3c9"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "An overview of how the vulnerabilities were fixed."
|
||||
},
|
||||
"diff": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "A base64-encoded remediation code diff, compatible with git apply."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,11 +111,11 @@ class UploadedFile
|
|||
|
||||
alias_method :local_path, :path
|
||||
|
||||
def method_missing(method_name, *args, &block) #:nodoc:
|
||||
def method_missing(method_name, *args, &block) # :nodoc:
|
||||
@tempfile.__send__(method_name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
|
||||
end
|
||||
|
||||
def respond_to?(method_name, include_private = false) #:nodoc:
|
||||
def respond_to?(method_name, include_private = false) # :nodoc:
|
||||
@tempfile.respond_to?(method_name, include_private) || super
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -9829,7 +9829,7 @@ msgstr ""
|
|||
msgid "CICD|Prevent CI/CD job tokens from this project from being used to access other projects unless the other project is added to the allowlist. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API. %{linkStart}Learn more%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|Prevent access to this project from other project CI/CD job tokens, unless the other project is added to the allowlist. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API. %{linkStart}Learn more.%{linkEnd}"
|
||||
msgid "CICD|Prevent access to this project from other project CI/CD job tokens, unless the other project is added to the allowlist. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API. %{linkStart}Learn more%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|The %{boldStart}Limit access %{boldEnd}%{italicAndBoldStart}from%{italicAndBoldEnd}%{boldStart} this project%{boldEnd} setting is deprecated and will be removed in the 18.0 milestone. Use the %{boldStart}Limit access %{boldEnd}%{italicAndBoldStart}to%{italicAndBoldEnd}%{boldStart} this project%{boldEnd} setting and allowlist instead. %{linkStart}How do I do this?%{linkEnd}"
|
||||
|
|
@ -17887,6 +17887,9 @@ msgstr ""
|
|||
msgid "Deployments|No deployment history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|A colleague"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Add approval comment"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -17920,6 +17923,9 @@ msgstr ""
|
|||
msgid "Deployment|Deployment ID"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Deployment approvals require a Premium or Ultimate subscription"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Failed"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -17944,6 +17950,9 @@ msgstr ""
|
|||
msgid "Deployment|Flux sync status is unknown"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Improve your continuous delivery practices with deployment approvals. Configure rules for required approvals, control which users can deploy to your environments, and collaborate throughout the delivery process."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Job"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -17962,6 +17971,9 @@ msgstr ""
|
|||
msgid "Deployment|Ready to be deployed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Ready to use deployment approvals?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Reject"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -17982,6 +17994,15 @@ msgstr[1] ""
|
|||
msgid "Deployment|Running"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Set up Deployment Approvals"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Set up deployment approvals to get more our of your deployments"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Set up deployment approvals to get started"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Skipped"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -18015,6 +18036,9 @@ msgstr ""
|
|||
msgid "Deployment|Unknown"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Upgrade to get more our of your deployments"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Waiting"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -18027,6 +18051,9 @@ msgstr ""
|
|||
msgid "Deployment|What would you like to see here?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|You"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deprecated API rate limits"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -23235,6 +23262,9 @@ msgstr ""
|
|||
msgid "GitLab Pages has moved"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLab Premium"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLab Shell"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -25917,6 +25947,9 @@ msgstr ""
|
|||
msgid "How to track time"
|
||||
msgstr ""
|
||||
|
||||
msgid "HttpDestinationValidator validates only http external audit event destinations."
|
||||
msgstr ""
|
||||
|
||||
msgid "I am sorry, I am unable to find what you are looking for."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -29956,6 +29989,9 @@ msgstr ""
|
|||
msgid "Last activity"
|
||||
msgstr ""
|
||||
|
||||
msgid "Last activity:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Last attempted number:"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -55943,6 +55979,9 @@ msgstr ""
|
|||
msgid "User created at"
|
||||
msgstr ""
|
||||
|
||||
msgid "User created:"
|
||||
msgstr ""
|
||||
|
||||
msgid "User deleted own account on %{timestamp}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -62253,6 +62292,9 @@ msgstr ""
|
|||
msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
|
||||
msgstr ""
|
||||
|
||||
msgid "should have length between 16 to 24 characters."
|
||||
msgstr ""
|
||||
|
||||
msgid "show %{count} more"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -62409,6 +62451,9 @@ msgstr ""
|
|||
msgid "uploads"
|
||||
msgstr ""
|
||||
|
||||
msgid "url is already taken."
|
||||
msgstr ""
|
||||
|
||||
msgid "user"
|
||||
msgid_plural "users"
|
||||
msgstr[0] ""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlBanner, GlTableLite, GlBadge } from '@gitlab/ui';
|
||||
import ApprovalsEmptyState from '~/deployments/components/approvals_empty_state.vue';
|
||||
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
|
||||
|
||||
describe('~/deployments/components/approvals_empty_state.vue', () => {
|
||||
let wrapper;
|
||||
let userCalloutDismissSpy;
|
||||
|
||||
const createComponent = ({ shouldShowCallout = true, propsData = {}, slots = {} } = {}) => {
|
||||
wrapper = shallowMount(ApprovalsEmptyState, {
|
||||
propsData,
|
||||
slots,
|
||||
stubs: {
|
||||
UserCalloutDismisser: makeMockUserCalloutDismisser({
|
||||
dismiss: userCalloutDismissSpy,
|
||||
shouldShowCallout,
|
||||
}),
|
||||
GlBanner,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const findBanner = () => wrapper.findComponent(GlBanner);
|
||||
const findBadge = () => wrapper.findComponent(GlBadge);
|
||||
const findTable = () => wrapper.findComponent(GlTableLite);
|
||||
|
||||
describe('when the callout is not dismissed', () => {
|
||||
it('shows the banner', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findBanner().exists()).toBe(true);
|
||||
});
|
||||
|
||||
describe('with default values', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('renders default banner props', () => {
|
||||
expect(findBanner().props()).toMatchObject({
|
||||
title: 'Upgrade to get more our of your deployments',
|
||||
buttonText: 'Learn more',
|
||||
buttonLink: '/help/ci/environments/deployment_approvals',
|
||||
});
|
||||
});
|
||||
|
||||
it('renders table header with the correct text', () => {
|
||||
expect(findBanner().text()).toContain(
|
||||
'Deployment approvals require a Premium or Ultimate subscription',
|
||||
);
|
||||
});
|
||||
|
||||
it('renders table header with the premium badge', () => {
|
||||
expect(findBadge().props()).toMatchObject({ icon: 'license', variant: 'tier' });
|
||||
expect(findBadge().text()).toBe('GitLab Premium');
|
||||
});
|
||||
|
||||
it('renders table with static data', () => {
|
||||
expect(findTable().props('fields')).toEqual([
|
||||
{ key: 'approvers', label: 'Approvers' },
|
||||
{ key: 'approvals', label: 'Approvals' },
|
||||
{ key: 'approvedBy', label: 'Approved By' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('renders CTA text in banner actions', () => {
|
||||
expect(findBanner().text()).toContain('Ready to use deployment approvals?');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with custom values', () => {
|
||||
it('renders default banner using values from props', () => {
|
||||
const bannerTitle = 'Custom title';
|
||||
const buttonText = 'Custom button text';
|
||||
const buttonLink = '/custom/link';
|
||||
|
||||
createComponent({
|
||||
propsData: { bannerTitle, buttonText, buttonLink },
|
||||
});
|
||||
|
||||
expect(findBanner().props()).toMatchObject({
|
||||
title: bannerTitle,
|
||||
buttonText,
|
||||
buttonLink,
|
||||
});
|
||||
});
|
||||
|
||||
it('renders custom table-header slot', () => {
|
||||
createComponent({
|
||||
slots: { 'table-header': '<div>Custom table-header</div>' },
|
||||
});
|
||||
|
||||
expect(findBanner().text()).toContain('Custom table-header');
|
||||
});
|
||||
|
||||
it('renders custom banner-actions slot', () => {
|
||||
createComponent({
|
||||
slots: { 'banner-actions': '<div>Custom banner-actions</div>' },
|
||||
});
|
||||
|
||||
expect(findBanner().text()).toContain('Custom banner-actions');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the callout is dismissed', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ shouldShowCallout: false });
|
||||
});
|
||||
|
||||
it("doesn't show the banner", () => {
|
||||
expect(findBanner().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -10,6 +10,8 @@ import ShowDeployment from '~/deployments/components/show_deployment.vue';
|
|||
import DeploymentHeader from '~/deployments/components/deployment_header.vue';
|
||||
import DeploymentDeployBlock from '~/deployments/components/deployment_deploy_block.vue';
|
||||
import DetailsFeedback from '~/deployments/components/details_feedback.vue';
|
||||
import DeploymentAside from '~/deployments/components/deployment_aside.vue';
|
||||
import ApprovalsEmptyState from 'ee_else_ce/deployments/components/approvals_empty_state.vue';
|
||||
import deploymentQuery from '~/deployments/graphql/queries/deployment.query.graphql';
|
||||
import environmentQuery from '~/deployments/graphql/queries/environment.query.graphql';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
|
@ -24,6 +26,7 @@ const PROJECT_PATH = 'group/project';
|
|||
const ENVIRONMENT_NAME = mockEnvironmentFixture.data.project.environment.name;
|
||||
const DEPLOYMENT_IID = mockDeploymentFixture.data.project.deployment.iid;
|
||||
const GRAPHQL_ETAG_KEY = 'project/environments';
|
||||
const PROTECTED_ENVIRONMENTS_SETTINGS_PATH = '/settings/ci_cd#js-protected-environments-settings';
|
||||
|
||||
describe('~/deployments/components/show_deployment.vue', () => {
|
||||
let wrapper;
|
||||
|
|
@ -48,6 +51,8 @@ describe('~/deployments/components/show_deployment.vue', () => {
|
|||
environmentName: ENVIRONMENT_NAME,
|
||||
deploymentIid: DEPLOYMENT_IID,
|
||||
graphqlEtagKey: GRAPHQL_ETAG_KEY,
|
||||
protectedEnvironmentsAvailable: true,
|
||||
protectedEnvironmentsSettingsPath: PROTECTED_ENVIRONMENTS_SETTINGS_PATH,
|
||||
},
|
||||
stubs: {
|
||||
GlSprintf,
|
||||
|
|
@ -58,6 +63,7 @@ describe('~/deployments/components/show_deployment.vue', () => {
|
|||
|
||||
const findHeader = () => wrapper.findComponent(DeploymentHeader);
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
const findApprovalsEmptyState = () => wrapper.findComponent(ApprovalsEmptyState);
|
||||
|
||||
describe('errors', () => {
|
||||
it('shows an error message when the deployment query fails', async () => {
|
||||
|
|
@ -87,6 +93,24 @@ describe('~/deployments/components/show_deployment.vue', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('loading', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('shows the header component in a loading state', () => {
|
||||
expect(findHeader().props('loading')).toBe(true);
|
||||
});
|
||||
|
||||
it('shows the aside component in a loading state', () => {
|
||||
expect(wrapper.findComponent(DeploymentAside).props('loading')).toBe(true);
|
||||
});
|
||||
|
||||
it("doesn't show the approvals empty state", () => {
|
||||
expect(findApprovalsEmptyState().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('page', () => {
|
||||
beforeEach(() => {
|
||||
deploymentQueryResponse.mockResolvedValue(mockDeploymentFixture);
|
||||
|
|
@ -116,6 +140,10 @@ describe('~/deployments/components/show_deployment.vue', () => {
|
|||
deployment: mockDeploymentFixture.data.project.deployment,
|
||||
});
|
||||
});
|
||||
|
||||
it('shows the approvals empty state', () => {
|
||||
expect(findApprovalsEmptyState().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('etag polling', () => {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import eventHub from '~/invite_members/event_hub';
|
|||
import ImportProjectMembersModal from '~/invite_members/components/import_project_members_modal.vue';
|
||||
import ProjectSelect from '~/invite_members/components/project_select.vue';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_CREATED } from '~/lib/utils/http_status';
|
||||
import { HTTP_STATUS_CREATED, HTTP_STATUS_UNPROCESSABLE_ENTITY } from '~/lib/utils/http_status';
|
||||
|
||||
import {
|
||||
displaySuccessfulInvitationAlert,
|
||||
|
|
@ -54,8 +54,11 @@ const triggerOpenModal = async () => {
|
|||
await nextTick();
|
||||
};
|
||||
|
||||
const createComponent = ({ props = {} } = {}) => {
|
||||
const createComponent = ({ props = {}, provide = {} } = {}) => {
|
||||
wrapper = shallowMountExtended(ImportProjectMembersModal, {
|
||||
provide: {
|
||||
...provide,
|
||||
},
|
||||
propsData: {
|
||||
projectId,
|
||||
projectName,
|
||||
|
|
@ -102,6 +105,8 @@ describe('ImportProjectMembersModal', () => {
|
|||
const findMoreInviteErrorsButton = () => wrapper.findByTestId('accordion-button');
|
||||
const findAccordion = () => wrapper.findComponent(GlCollapse);
|
||||
const findErrorsIcon = () => wrapper.findComponent(GlIcon);
|
||||
const findSeatOveragesAlert = () =>
|
||||
wrapper.findByTestId('import-project-members-seat-overages-alert');
|
||||
const findMemberErrorMessage = (element) =>
|
||||
`@${Object.keys(importProjectMembersApiResponse.EXPANDED_IMPORT_ERRORS.message)[element]}: ${
|
||||
Object.values(importProjectMembersApiResponse.EXPANDED_IMPORT_ERRORS.message)[element]
|
||||
|
|
@ -387,5 +392,40 @@ describe('ImportProjectMembersModal', () => {
|
|||
expect(findMoreInviteErrorsButton().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the import fails due to a seat overage', () => {
|
||||
const mockInvitationsApi = (code, data) => {
|
||||
mock.onPost(IMPORT_PROJECT_MEMBERS_PATH).reply(code, data);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent({ provide: { addSeatsHref: 'add_seats_url' } });
|
||||
findProjectSelect().vm.$emit('input', projectToBeImported);
|
||||
});
|
||||
|
||||
it('clears the error when the modal is closed', async () => {
|
||||
mockInvitationsApi(
|
||||
HTTP_STATUS_UNPROCESSABLE_ENTITY,
|
||||
importProjectMembersApiResponse.SEAT_OVERAGE_IMPORT_ERRORS,
|
||||
);
|
||||
|
||||
clickImportButton();
|
||||
await waitForPromises();
|
||||
|
||||
expect(formGroupInvalidFeedback()).toBe(
|
||||
'There are not enough available seats to invite this many users.',
|
||||
);
|
||||
expect(formGroupErrorState()).toBe(false);
|
||||
expect(findSeatOveragesAlert().exists()).toBe(true);
|
||||
|
||||
closeModal();
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(formGroupInvalidFeedback()).toBe('');
|
||||
expect(formGroupErrorState()).not.toBe(false);
|
||||
expect(findSeatOveragesAlert().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -110,7 +110,12 @@ const NO_COLLAPSE_IMPORT_ERRORS = {
|
|||
total_members_count: '2',
|
||||
status: 'error',
|
||||
};
|
||||
const SEAT_OVERAGE_IMPORT_ERRORS = {
|
||||
message: 'There are not enough available seats to invite this many users.',
|
||||
reason: 'seat_limit_exceeded_error',
|
||||
};
|
||||
export const importProjectMembersApiResponse = {
|
||||
EXPANDED_IMPORT_ERRORS,
|
||||
NO_COLLAPSE_IMPORT_ERRORS,
|
||||
SEAT_OVERAGE_IMPORT_ERRORS,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3945,6 +3945,7 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and
|
|||
|
||||
expect(response).to have_gitlab_http_status(:unprocessable_entity)
|
||||
expect(json_response['message']).to eq('Import failed')
|
||||
expect(json_response['reason']).to eq('import_failed_error')
|
||||
end
|
||||
|
||||
context 'when importing of members did not work for some or all members' do
|
||||
|
|
@ -3960,6 +3961,7 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and
|
|||
error_message = { project_bot.username => 'User project bots cannot be added to other groups / projects' }
|
||||
expect(json_response['message']).to eq(error_message)
|
||||
expect(json_response['total_members_count']).to eq(3)
|
||||
expect(json_response['status']).to eq('error')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -98,48 +98,6 @@ RSpec.describe Groups::CreateService, '#execute', feature_category: :groups_and_
|
|||
end
|
||||
end
|
||||
|
||||
context 'with `emails_disabled` attribute' do
|
||||
context 'when emails_disabled is false' do
|
||||
let(:extra_params) { { emails_disabled: false } }
|
||||
|
||||
it_behaves_like 'creating a group'
|
||||
|
||||
it 'sets emails_enabled to true' do
|
||||
expect(created_group.emails_enabled).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when emails_disabled is true' do
|
||||
let(:extra_params) { { emails_disabled: true } }
|
||||
|
||||
it_behaves_like 'creating a group'
|
||||
|
||||
it 'sets emails_enabled to false' do
|
||||
expect(created_group.emails_enabled).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when emails_disabled is nil' do
|
||||
let(:extra_params) { { emails_disabled: nil } }
|
||||
|
||||
it_behaves_like 'creating a group'
|
||||
|
||||
it 'sets emails_enabled to default true' do
|
||||
expect(created_group.emails_enabled).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when emails_disabled is the string "false"' do
|
||||
let(:extra_params) { { emails_disabled: "false" } }
|
||||
|
||||
it_behaves_like 'creating a group'
|
||||
|
||||
it 'sets emails_enabled to false' do
|
||||
expect(created_group.emails_enabled).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with `allow_mfa_for_subgroups` attribute' do
|
||||
let(:extra_params) { { allow_mfa_for_subgroups: false } }
|
||||
|
||||
|
|
|
|||
|
|
@ -390,56 +390,6 @@ RSpec.describe Groups::UpdateService, feature_category: :groups_and_projects do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when updating #emails_disabled' do
|
||||
context 'when emails_disabled is true' do
|
||||
let(:service) { described_class.new(internal_group, user, emails_disabled: true) }
|
||||
|
||||
it 'updates email_enabled to false' do
|
||||
internal_group.add_member(user, Gitlab::Access::OWNER)
|
||||
|
||||
service.execute
|
||||
|
||||
expect(internal_group.emails_enabled).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when emails_disabled is false' do
|
||||
let(:service) { described_class.new(internal_group, user, emails_disabled: false) }
|
||||
|
||||
it 'email_enabled is set to true' do
|
||||
internal_group.add_member(user, Gitlab::Access::OWNER)
|
||||
|
||||
service.execute
|
||||
|
||||
expect(internal_group.emails_enabled).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when emails_disabled is nil' do
|
||||
let(:service) { described_class.new(internal_group, user, emails_disabled: nil) }
|
||||
|
||||
it 'email_enabled is set to the default value of true' do
|
||||
internal_group.add_member(user, Gitlab::Access::OWNER)
|
||||
|
||||
service.execute
|
||||
|
||||
expect(internal_group.emails_enabled).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when emails_disabled is the string "true"' do
|
||||
let(:service) { described_class.new(internal_group, user, emails_disabled: "true") }
|
||||
|
||||
it 'email_enabled is set to the default value of true' do
|
||||
internal_group.add_member(user, Gitlab::Access::OWNER)
|
||||
|
||||
service.execute
|
||||
|
||||
expect(internal_group.emails_enabled).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when updating #max_artifacts_size' do
|
||||
let(:params) { { max_artifacts_size: 10 } }
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ RSpec.describe Members::ImportProjectTeamService, feature_category: :groups_and_
|
|||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.error?).to be(true)
|
||||
expect(result.message).to eq('Target project does not exist')
|
||||
expect(result.reason).to eq(:unprocessable_entity)
|
||||
expect(result.reason).to eq(:argument_error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ RSpec.describe Members::ImportProjectTeamService, feature_category: :groups_and_
|
|||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.error?).to be(true)
|
||||
expect(result.message).to eq('Source project does not exist')
|
||||
expect(result.reason).to eq(:unprocessable_entity)
|
||||
expect(result.reason).to eq(:argument_error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ RSpec.describe Members::ImportProjectTeamService, feature_category: :groups_and_
|
|||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.error?).to be(true)
|
||||
expect(result.message).to eq('Forbidden')
|
||||
expect(result.reason).to eq(:unprocessable_entity)
|
||||
expect(result.reason).to eq(:import_project_team_forbidden_error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ RSpec.describe Members::ImportProjectTeamService, feature_category: :groups_and_
|
|||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.error?).to be(true)
|
||||
expect(result.message).to eq('Forbidden')
|
||||
expect(result.reason).to eq(:unprocessable_entity)
|
||||
expect(result.reason).to eq(:import_project_team_forbidden_error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ RSpec.describe Members::ImportProjectTeamService, feature_category: :groups_and_
|
|||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.error?).to be(true)
|
||||
expect(result.message).to eq('Forbidden')
|
||||
expect(result.reason).to eq(:unprocessable_entity)
|
||||
expect(result.reason).to eq(:import_project_team_forbidden_error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ RSpec.describe Members::ImportProjectTeamService, feature_category: :groups_and_
|
|||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.error?).to be(true)
|
||||
expect(result.message).to eq('Import failed')
|
||||
expect(result.reason).to eq(:unprocessable_entity)
|
||||
expect(result.reason).to eq(:import_failed_error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue