summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/security_configuration
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 09:55:51 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 09:55:51 +0000
commite8d2c2579383897a1dd7f9debd359abe8ae8373d (patch)
treec42be41678c2586d49a75cabce89322082698334 /app/assets/javascripts/security_configuration
parentfc845b37ec3a90aaa719975f607740c22ba6a113 (diff)
downloadgitlab-ce-e8d2c2579383897a1dd7f9debd359abe8ae8373d.tar.gz
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'app/assets/javascripts/security_configuration')
-rw-r--r--app/assets/javascripts/security_configuration/components/auto_dev_ops_alert.vue41
-rw-r--r--app/assets/javascripts/security_configuration/components/configuration_table.vue2
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js58
-rw-r--r--app/assets/javascripts/security_configuration/components/feature_card.vue3
-rw-r--r--app/assets/javascripts/security_configuration/components/redesigned_app.vue82
-rw-r--r--app/assets/javascripts/security_configuration/components/section_layout.vue6
-rw-r--r--app/assets/javascripts/security_configuration/graphql/configure_secret_detection.mutation.graphql6
-rw-r--r--app/assets/javascripts/security_configuration/index.js81
-rw-r--r--app/assets/javascripts/security_configuration/utils.js4
9 files changed, 219 insertions, 64 deletions
diff --git a/app/assets/javascripts/security_configuration/components/auto_dev_ops_alert.vue b/app/assets/javascripts/security_configuration/components/auto_dev_ops_alert.vue
new file mode 100644
index 00000000000..ce6a1b4888b
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/auto_dev_ops_alert.vue
@@ -0,0 +1,41 @@
+<script>
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+export default {
+ components: {
+ GlSprintf,
+ GlAlert,
+ GlLink,
+ },
+ inject: ['autoDevopsHelpPagePath', 'autoDevopsPath'],
+ i18n: {
+ primaryButtonText: s__('SecurityConfiguration|Enable Auto DevOps'),
+ body: s__(
+ 'SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}',
+ ),
+ },
+ methods: {
+ dismissMethod() {
+ this.$emit('dismiss');
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-alert
+ variant="info"
+ :primary-button-link="autoDevopsPath"
+ :primary-button-text="$options.i18n.primaryButtonText"
+ @dismiss="dismissMethod"
+ >
+ <gl-sprintf :message="$options.i18n.body">
+ <template #link="{ content }">
+ <gl-link :href="autoDevopsHelpPagePath">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/security_configuration/components/configuration_table.vue b/app/assets/javascripts/security_configuration/components/configuration_table.vue
index 2110af1522b..7f250bf1365 100644
--- a/app/assets/javascripts/security_configuration/components/configuration_table.vue
+++ b/app/assets/javascripts/security_configuration/components/configuration_table.vue
@@ -8,6 +8,7 @@ import {
REPORT_TYPE_DAST_PROFILES,
REPORT_TYPE_DEPENDENCY_SCANNING,
REPORT_TYPE_CONTAINER_SCANNING,
+ REPORT_TYPE_CLUSTER_IMAGE_SCANNING,
REPORT_TYPE_COVERAGE_FUZZING,
REPORT_TYPE_API_FUZZING,
REPORT_TYPE_LICENSE_COMPLIANCE,
@@ -46,6 +47,7 @@ export default {
[REPORT_TYPE_DAST_PROFILES]: Upgrade,
[REPORT_TYPE_DEPENDENCY_SCANNING]: Upgrade,
[REPORT_TYPE_CONTAINER_SCANNING]: Upgrade,
+ [REPORT_TYPE_CLUSTER_IMAGE_SCANNING]: Upgrade,
[REPORT_TYPE_COVERAGE_FUZZING]: Upgrade,
[REPORT_TYPE_API_FUZZING]: Upgrade,
[REPORT_TYPE_LICENSE_COMPLIANCE]: Upgrade,
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index 142dade914b..5cb9277040d 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -1,7 +1,6 @@
import { helpPagePath } from '~/helpers/help_page_helper';
import { __, s__ } from '~/locale';
-import configureSastMutation from '~/security_configuration/graphql/configure_sast.mutation.graphql';
import {
REPORT_TYPE_SAST,
REPORT_TYPE_DAST,
@@ -9,11 +8,15 @@ import {
REPORT_TYPE_SECRET_DETECTION,
REPORT_TYPE_DEPENDENCY_SCANNING,
REPORT_TYPE_CONTAINER_SCANNING,
+ REPORT_TYPE_CLUSTER_IMAGE_SCANNING,
REPORT_TYPE_COVERAGE_FUZZING,
REPORT_TYPE_API_FUZZING,
REPORT_TYPE_LICENSE_COMPLIANCE,
} from '~/vue_shared/security_reports/constants';
+import configureSastMutation from '../graphql/configure_sast.mutation.graphql';
+import configureSecretDetectionMutation from '../graphql/configure_secret_detection.mutation.graphql';
+
/**
* Translations & helpPagePaths for Static Security Configuration Page
*/
@@ -34,8 +37,8 @@ export const DAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/das
});
export const DAST_PROFILES_NAME = __('DAST Scans');
-export const DAST_PROFILES_DESCRIPTION = __(
- 'Saved scan settings and target site settings which are reusable.',
+export const DAST_PROFILES_DESCRIPTION = s__(
+ 'SecurityConfiguration|Manage profiles for use by DAST scans.',
);
export const DAST_PROFILES_HELP_PATH = helpPagePath('user/application_security/dast/index');
export const DAST_PROFILES_CONFIG_TEXT = s__('SecurityConfiguration|Manage scans');
@@ -76,6 +79,18 @@ export const CONTAINER_SCANNING_CONFIG_HELP_PATH = helpPagePath(
{ anchor: 'configuration' },
);
+export const CLUSTER_IMAGE_SCANNING_NAME = s__('ciReport|Cluster Image Scanning');
+export const CLUSTER_IMAGE_SCANNING_DESCRIPTION = __(
+ 'Check your Kubernetes cluster images for known vulnerabilities.',
+);
+export const CLUSTER_IMAGE_SCANNING_HELP_PATH = helpPagePath(
+ 'user/application_security/cluster_image_scanning/index',
+);
+export const CLUSTER_IMAGE_SCANNING_CONFIG_HELP_PATH = helpPagePath(
+ 'user/application_security/cluster_image_scanning/index',
+ { anchor: 'configuration' },
+);
+
export const COVERAGE_FUZZING_NAME = __('Coverage Fuzzing');
export const COVERAGE_FUZZING_DESCRIPTION = __(
'Find bugs in your code with coverage-guided fuzzing.',
@@ -132,6 +147,12 @@ export const scanners = [
type: REPORT_TYPE_CONTAINER_SCANNING,
},
{
+ name: CLUSTER_IMAGE_SCANNING_NAME,
+ description: CLUSTER_IMAGE_SCANNING_DESCRIPTION,
+ helpPath: CLUSTER_IMAGE_SCANNING_HELP_PATH,
+ type: REPORT_TYPE_CLUSTER_IMAGE_SCANNING,
+ },
+ {
name: SECRET_DETECTION_NAME,
description: SECRET_DETECTION_DESCRIPTION,
helpPath: SECRET_DETECTION_HELP_PATH,
@@ -195,6 +216,10 @@ export const securityFeatures = [
helpPath: DEPENDENCY_SCANNING_HELP_PATH,
configurationHelpPath: DEPENDENCY_SCANNING_CONFIG_HELP_PATH,
type: REPORT_TYPE_DEPENDENCY_SCANNING,
+
+ // This field will eventually come from the backend, the progress is
+ // tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/331621
+ canEnableByMergeRequest: window.gon.features?.secDependencyScanningUiEnable,
},
{
name: CONTAINER_SCANNING_NAME,
@@ -204,12 +229,28 @@ export const securityFeatures = [
type: REPORT_TYPE_CONTAINER_SCANNING,
},
{
+ name: CLUSTER_IMAGE_SCANNING_NAME,
+ description: CLUSTER_IMAGE_SCANNING_DESCRIPTION,
+ helpPath: CLUSTER_IMAGE_SCANNING_HELP_PATH,
+ configurationHelpPath: CLUSTER_IMAGE_SCANNING_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_CLUSTER_IMAGE_SCANNING,
+ },
+ {
name: SECRET_DETECTION_NAME,
description: SECRET_DETECTION_DESCRIPTION,
helpPath: SECRET_DETECTION_HELP_PATH,
configurationHelpPath: SECRET_DETECTION_CONFIG_HELP_PATH,
type: REPORT_TYPE_SECRET_DETECTION,
+
+ // This field is currently hardcoded because Secret Detection is always
+ // available. It will eventually come from the Backend, the progress is
+ // tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/333113
available: true,
+
+ // This field is currently hardcoded because SAST can always be enabled via MR
+ // It will eventually come from the Backend, the progress is tracked in
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/331621
+ canEnableByMergeRequest: true,
},
{
name: API_FUZZING_NAME,
@@ -247,4 +288,15 @@ export const featureToMutationMap = {
},
}),
},
+ [REPORT_TYPE_SECRET_DETECTION]: {
+ mutationId: 'configureSecretDetection',
+ getMutationPayload: (projectPath) => ({
+ mutation: configureSecretDetectionMutation,
+ variables: {
+ input: {
+ projectPath,
+ },
+ },
+ }),
+ },
};
diff --git a/app/assets/javascripts/security_configuration/components/feature_card.vue b/app/assets/javascripts/security_configuration/components/feature_card.vue
index 518a6ede3de..23cffde1f83 100644
--- a/app/assets/javascripts/security_configuration/components/feature_card.vue
+++ b/app/assets/javascripts/security_configuration/components/feature_card.vue
@@ -46,8 +46,7 @@ export default {
return button;
},
showManageViaMr() {
- const { available, configured, canEnableByMergeRequest } = this.feature;
- return canEnableByMergeRequest && available && !configured;
+ return ManageViaMr.canRender(this.feature);
},
cardClasses() {
return { 'gl-bg-gray-10': !this.available };
diff --git a/app/assets/javascripts/security_configuration/components/redesigned_app.vue b/app/assets/javascripts/security_configuration/components/redesigned_app.vue
index d8a12f4a792..915da378a4f 100644
--- a/app/assets/javascripts/security_configuration/components/redesigned_app.vue
+++ b/app/assets/javascripts/security_configuration/components/redesigned_app.vue
@@ -2,18 +2,22 @@
import { GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
+import AutoDevOpsAlert from './auto_dev_ops_alert.vue';
import FeatureCard from './feature_card.vue';
import SectionLayout from './section_layout.vue';
import UpgradeBanner from './upgrade_banner.vue';
export const i18n = {
compliance: s__('SecurityConfiguration|Compliance'),
+ configurationHistory: s__('SecurityConfiguration|Configuration history'),
securityTesting: s__('SecurityConfiguration|Security testing'),
- securityTestingDescription: s__(
+ latestPipelineDescription: s__(
`SecurityConfiguration|The status of the tools only applies to the
- default branch and is based on the %{linkStart}latest pipeline%{linkEnd}.
- Once you've enabled a scan for the default branch, any subsequent feature
- branch you create will include the scan.`,
+ default branch and is based on the %{linkStart}latest pipeline%{linkEnd}.`,
+ ),
+ description: s__(
+ `SecurityConfiguration|Once you've enabled a scan for the default branch,
+ any subsequent feature branch you create will include the scan.`,
),
securityConfiguration: __('Security Configuration'),
};
@@ -28,6 +32,7 @@ export default {
FeatureCard,
SectionLayout,
UpgradeBanner,
+ AutoDevOpsAlert,
UserCalloutDismisser,
},
props: {
@@ -44,6 +49,16 @@ export default {
required: false,
default: false,
},
+ autoDevopsEnabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ canEnableAutoDevops: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
gitlabCiHistoryPath: {
type: String,
required: false,
@@ -64,16 +79,26 @@ export default {
canViewCiHistory() {
return Boolean(this.gitlabCiPresent && this.gitlabCiHistoryPath);
},
+ shouldShowDevopsAlert() {
+ return !this.autoDevopsEnabled && !this.gitlabCiPresent && this.canEnableAutoDevops;
+ },
},
};
</script>
<template>
<article>
+ <user-callout-dismisser
+ v-if="shouldShowDevopsAlert"
+ feature-name="security_configuration_devops_alert"
+ >
+ <template #default="{ dismiss, shouldShowCallout }">
+ <auto-dev-ops-alert v-if="shouldShowCallout" class="gl-mt-3" @dismiss="dismiss" />
+ </template>
+ </user-callout-dismisser>
<header>
<h1 class="gl-font-size-h1">{{ $options.i18n.securityConfiguration }}</h1>
</header>
-
<user-callout-dismisser v-if="canUpgrade" feature-name="security_configuration_upgrade_banner">
<template #default="{ dismiss, shouldShowCallout }">
<upgrade-banner v-if="shouldShowCallout" @close="dismiss" />
@@ -84,16 +109,19 @@ export default {
<gl-tab data-testid="security-testing-tab" :title="$options.i18n.securityTesting">
<section-layout :heading="$options.i18n.securityTesting">
<template #description>
- <p
- v-if="latestPipelinePath"
- data-testid="latest-pipeline-info-security"
- class="gl-line-height-20"
- >
- <gl-sprintf :message="$options.i18n.securityTestingDescription">
- <template #link="{ content }">
- <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
+ <p>
+ <span data-testid="latest-pipeline-info-security">
+ <gl-sprintf
+ v-if="latestPipelinePath"
+ :message="$options.i18n.latestPipelineDescription"
+ >
+ <template #link="{ content }">
+ <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+
+ {{ $options.i18n.description }}
</p>
<p v-if="canViewCiHistory">
<gl-link data-testid="security-view-history-link" :href="gitlabCiHistoryPath">{{
@@ -106,6 +134,7 @@ export default {
<feature-card
v-for="feature in augmentedSecurityFeatures"
:key="feature.type"
+ data-testid="security-testing-card"
:feature="feature"
class="gl-mb-6"
/>
@@ -115,16 +144,19 @@ export default {
<gl-tab data-testid="compliance-testing-tab" :title="$options.i18n.compliance">
<section-layout :heading="$options.i18n.compliance">
<template #description>
- <p
- v-if="latestPipelinePath"
- class="gl-line-height-20"
- data-testid="latest-pipeline-info-compliance"
- >
- <gl-sprintf :message="$options.i18n.securityTestingDescription">
- <template #link="{ content }">
- <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
+ <p>
+ <span data-testid="latest-pipeline-info-compliance">
+ <gl-sprintf
+ v-if="latestPipelinePath"
+ :message="$options.i18n.latestPipelineDescription"
+ >
+ <template #link="{ content }">
+ <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+
+ {{ $options.i18n.description }}
</p>
<p v-if="canViewCiHistory">
<gl-link data-testid="compliance-view-history-link" :href="gitlabCiHistoryPath">{{
diff --git a/app/assets/javascripts/security_configuration/components/section_layout.vue b/app/assets/javascripts/security_configuration/components/section_layout.vue
index 1e1f83a6d99..e351f9b9d8d 100644
--- a/app/assets/javascripts/security_configuration/components/section_layout.vue
+++ b/app/assets/javascripts/security_configuration/components/section_layout.vue
@@ -11,12 +11,12 @@ export default {
</script>
<template>
- <div class="row">
- <div class="col-lg-5">
+ <div class="row gl-line-height-20">
+ <div class="col-lg-4">
<h2 class="gl-font-size-h2 gl-mt-0">{{ heading }}</h2>
<slot name="description"></slot>
</div>
- <div class="col-lg-7">
+ <div class="col-lg-8">
<slot name="features"></slot>
</div>
</div>
diff --git a/app/assets/javascripts/security_configuration/graphql/configure_secret_detection.mutation.graphql b/app/assets/javascripts/security_configuration/graphql/configure_secret_detection.mutation.graphql
new file mode 100644
index 00000000000..e42a8de64f3
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/graphql/configure_secret_detection.mutation.graphql
@@ -0,0 +1,6 @@
+mutation configureSecretDetection($input: ConfigureSecretDetectionInput!) {
+ configureSecretDetection(input: $input) {
+ successPath
+ errors
+ }
+}
diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js
index e1dc6f24737..f05bd79258e 100644
--- a/app/assets/javascripts/security_configuration/index.js
+++ b/app/assets/javascripts/security_configuration/index.js
@@ -7,11 +7,7 @@ import { securityFeatures, complianceFeatures } from './components/constants';
import RedesignedSecurityConfigurationApp from './components/redesigned_app.vue';
import { augmentFeatures } from './utils';
-export const initStaticSecurityConfiguration = (el) => {
- if (!el) {
- return null;
- }
-
+export const initRedesignedSecurityConfiguration = (el) => {
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
@@ -24,35 +20,60 @@ export const initStaticSecurityConfiguration = (el) => {
features,
latestPipelinePath,
gitlabCiHistoryPath,
+ autoDevopsHelpPagePath,
+ autoDevopsPath,
} = el.dataset;
- if (gon.features.securityConfigurationRedesign) {
- const { augmentedSecurityFeatures, augmentedComplianceFeatures } = augmentFeatures(
- securityFeatures,
- complianceFeatures,
- features ? JSON.parse(features) : [],
- );
+ const { augmentedSecurityFeatures, augmentedComplianceFeatures } = augmentFeatures(
+ securityFeatures,
+ complianceFeatures,
+ features ? JSON.parse(features) : [],
+ );
+
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: {
+ projectPath,
+ upgradePath,
+ autoDevopsHelpPagePath,
+ autoDevopsPath,
+ },
+ render(createElement) {
+ return createElement(RedesignedSecurityConfigurationApp, {
+ props: {
+ augmentedComplianceFeatures,
+ augmentedSecurityFeatures,
+ latestPipelinePath,
+ gitlabCiHistoryPath,
+ ...parseBooleanDataAttributes(el, [
+ 'gitlabCiPresent',
+ 'autoDevopsEnabled',
+ 'canEnableAutoDevops',
+ ]),
+ },
+ });
+ },
+ });
+};
+
+export const initCESecurityConfiguration = (el) => {
+ if (!el) {
+ return null;
+ }
- return new Vue({
- el,
- apolloProvider,
- provide: {
- projectPath,
- upgradePath,
- },
- render(createElement) {
- return createElement(RedesignedSecurityConfigurationApp, {
- props: {
- augmentedComplianceFeatures,
- augmentedSecurityFeatures,
- latestPipelinePath,
- gitlabCiHistoryPath,
- ...parseBooleanDataAttributes(el, ['gitlabCiPresent']),
- },
- });
- },
- });
+ if (gon.features?.securityConfigurationRedesign) {
+ return initRedesignedSecurityConfiguration(el);
}
+
+ Vue.use(VueApollo);
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ const { projectPath, upgradePath } = el.dataset;
+
return new Vue({
el,
apolloProvider,
diff --git a/app/assets/javascripts/security_configuration/utils.js b/app/assets/javascripts/security_configuration/utils.js
index 071ebff4f21..ec6b93c6193 100644
--- a/app/assets/javascripts/security_configuration/utils.js
+++ b/app/assets/javascripts/security_configuration/utils.js
@@ -1,6 +1,8 @@
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
export const augmentFeatures = (securityFeatures, complianceFeatures, features = []) => {
const featuresByType = features.reduce((acc, feature) => {
- acc[feature.type] = feature;
+ acc[feature.type] = convertObjectPropsToCamelCase(feature, { deep: true });
return acc;
}, {});