diff options
Diffstat (limited to 'app/assets/javascripts/security_configuration/components')
4 files changed, 313 insertions, 0 deletions
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js index 3cdcac4c0b4..142dade914b 100644 --- a/app/assets/javascripts/security_configuration/components/constants.js +++ b/app/assets/javascripts/security_configuration/components/constants.js @@ -18,18 +18,27 @@ import { * Translations & helpPagePaths for Static Security Configuration Page */ export const SAST_NAME = __('Static Application Security Testing (SAST)'); +export const SAST_SHORT_NAME = s__('ciReport|SAST'); export const SAST_DESCRIPTION = __('Analyze your source code for known vulnerabilities.'); export const SAST_HELP_PATH = helpPagePath('user/application_security/sast/index'); +export const SAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/sast/index', { + anchor: 'configuration', +}); export const DAST_NAME = __('Dynamic Application Security Testing (DAST)'); +export const DAST_SHORT_NAME = s__('ciReport|DAST'); export const DAST_DESCRIPTION = __('Analyze a review version of your web application.'); export const DAST_HELP_PATH = helpPagePath('user/application_security/dast/index'); +export const DAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/dast/index', { + anchor: 'enable-dast', +}); 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_HELP_PATH = helpPagePath('user/application_security/dast/index'); +export const DAST_PROFILES_CONFIG_TEXT = s__('SecurityConfiguration|Manage scans'); export const SECRET_DETECTION_NAME = __('Secret Detection'); export const SECRET_DETECTION_DESCRIPTION = __( @@ -38,6 +47,10 @@ export const SECRET_DETECTION_DESCRIPTION = __( export const SECRET_DETECTION_HELP_PATH = helpPagePath( 'user/application_security/secret_detection/index', ); +export const SECRET_DETECTION_CONFIG_HELP_PATH = helpPagePath( + 'user/application_security/secret_detection/index', + { anchor: 'configuration' }, +); export const DEPENDENCY_SCANNING_NAME = __('Dependency Scanning'); export const DEPENDENCY_SCANNING_DESCRIPTION = __( @@ -46,6 +59,10 @@ export const DEPENDENCY_SCANNING_DESCRIPTION = __( export const DEPENDENCY_SCANNING_HELP_PATH = helpPagePath( 'user/application_security/dependency_scanning/index', ); +export const DEPENDENCY_SCANNING_CONFIG_HELP_PATH = helpPagePath( + 'user/application_security/dependency_scanning/index', + { anchor: 'configuration' }, +); export const CONTAINER_SCANNING_NAME = __('Container Scanning'); export const CONTAINER_SCANNING_DESCRIPTION = __( @@ -54,6 +71,10 @@ export const CONTAINER_SCANNING_DESCRIPTION = __( export const CONTAINER_SCANNING_HELP_PATH = helpPagePath( 'user/application_security/container_scanning/index', ); +export const CONTAINER_SCANNING_CONFIG_HELP_PATH = helpPagePath( + 'user/application_security/container_scanning/index', + { anchor: 'configuration' }, +); export const COVERAGE_FUZZING_NAME = __('Coverage Fuzzing'); export const COVERAGE_FUZZING_DESCRIPTION = __( @@ -136,6 +157,83 @@ export const scanners = [ }, ]; +export const securityFeatures = [ + { + name: SAST_NAME, + shortName: SAST_SHORT_NAME, + description: SAST_DESCRIPTION, + helpPath: SAST_HELP_PATH, + configurationHelpPath: SAST_CONFIG_HELP_PATH, + type: REPORT_TYPE_SAST, + // This field is currently hardcoded because SAST is always available. + // It will eventually come from the Backend, the progress is tracked in + // https://gitlab.com/gitlab-org/gitlab/-/issues/331622 + 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: DAST_NAME, + shortName: DAST_SHORT_NAME, + description: DAST_DESCRIPTION, + helpPath: DAST_HELP_PATH, + configurationHelpPath: DAST_CONFIG_HELP_PATH, + type: REPORT_TYPE_DAST, + secondary: { + type: REPORT_TYPE_DAST_PROFILES, + name: DAST_PROFILES_NAME, + description: DAST_PROFILES_DESCRIPTION, + configurationText: DAST_PROFILES_CONFIG_TEXT, + }, + }, + { + name: DEPENDENCY_SCANNING_NAME, + description: DEPENDENCY_SCANNING_DESCRIPTION, + helpPath: DEPENDENCY_SCANNING_HELP_PATH, + configurationHelpPath: DEPENDENCY_SCANNING_CONFIG_HELP_PATH, + type: REPORT_TYPE_DEPENDENCY_SCANNING, + }, + { + name: CONTAINER_SCANNING_NAME, + description: CONTAINER_SCANNING_DESCRIPTION, + helpPath: CONTAINER_SCANNING_HELP_PATH, + configurationHelpPath: CONTAINER_SCANNING_CONFIG_HELP_PATH, + type: REPORT_TYPE_CONTAINER_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, + available: true, + }, + { + name: API_FUZZING_NAME, + description: API_FUZZING_DESCRIPTION, + helpPath: API_FUZZING_HELP_PATH, + type: REPORT_TYPE_API_FUZZING, + }, + { + name: COVERAGE_FUZZING_NAME, + description: COVERAGE_FUZZING_DESCRIPTION, + helpPath: COVERAGE_FUZZING_HELP_PATH, + type: REPORT_TYPE_COVERAGE_FUZZING, + }, +]; + +export const complianceFeatures = [ + { + name: LICENSE_COMPLIANCE_NAME, + description: LICENSE_COMPLIANCE_DESCRIPTION, + helpPath: LICENSE_COMPLIANCE_HELP_PATH, + type: REPORT_TYPE_LICENSE_COMPLIANCE, + }, +]; + export const featureToMutationMap = { [REPORT_TYPE_SAST]: { mutationId: 'configureSast', diff --git a/app/assets/javascripts/security_configuration/components/redesigned_app.vue b/app/assets/javascripts/security_configuration/components/redesigned_app.vue new file mode 100644 index 00000000000..d8a12f4a792 --- /dev/null +++ b/app/assets/javascripts/security_configuration/components/redesigned_app.vue @@ -0,0 +1,147 @@ +<script> +import { GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui'; +import { __, s__ } from '~/locale'; +import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.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'), + securityTesting: s__('SecurityConfiguration|Security testing'), + securityTestingDescription: 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.`, + ), + securityConfiguration: __('Security Configuration'), +}; + +export default { + i18n, + components: { + GlTab, + GlLink, + GlTabs, + GlSprintf, + FeatureCard, + SectionLayout, + UpgradeBanner, + UserCalloutDismisser, + }, + props: { + augmentedSecurityFeatures: { + type: Array, + required: true, + }, + augmentedComplianceFeatures: { + type: Array, + required: true, + }, + gitlabCiPresent: { + type: Boolean, + required: false, + default: false, + }, + gitlabCiHistoryPath: { + type: String, + required: false, + default: '', + }, + latestPipelinePath: { + type: String, + required: false, + default: '', + }, + }, + computed: { + canUpgrade() { + return [...this.augmentedSecurityFeatures, ...this.augmentedComplianceFeatures].some( + ({ available }) => !available, + ); + }, + canViewCiHistory() { + return Boolean(this.gitlabCiPresent && this.gitlabCiHistoryPath); + }, + }, +}; +</script> + +<template> + <article> + <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" /> + </template> + </user-callout-dismisser> + + <gl-tabs content-class="gl-pt-6"> + <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> + <p v-if="canViewCiHistory"> + <gl-link data-testid="security-view-history-link" :href="gitlabCiHistoryPath">{{ + $options.i18n.configurationHistory + }}</gl-link> + </p> + </template> + + <template #features> + <feature-card + v-for="feature in augmentedSecurityFeatures" + :key="feature.type" + :feature="feature" + class="gl-mb-6" + /> + </template> + </section-layout> + </gl-tab> + <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> + <p v-if="canViewCiHistory"> + <gl-link data-testid="compliance-view-history-link" :href="gitlabCiHistoryPath">{{ + $options.i18n.configurationHistory + }}</gl-link> + </p> + </template> + <template #features> + <feature-card + v-for="feature in augmentedComplianceFeatures" + :key="feature.type" + :feature="feature" + class="gl-mb-6" + /> + </template> + </section-layout> + </gl-tab> + </gl-tabs> + </article> +</template> diff --git a/app/assets/javascripts/security_configuration/components/section_layout.vue b/app/assets/javascripts/security_configuration/components/section_layout.vue new file mode 100644 index 00000000000..1e1f83a6d99 --- /dev/null +++ b/app/assets/javascripts/security_configuration/components/section_layout.vue @@ -0,0 +1,23 @@ +<script> +export default { + name: 'SectionLayout', + props: { + heading: { + type: String, + required: true, + }, + }, +}; +</script> + +<template> + <div class="row"> + <div class="col-lg-5"> + <h2 class="gl-font-size-h2 gl-mt-0">{{ heading }}</h2> + <slot name="description"></slot> + </div> + <div class="col-lg-7"> + <slot name="features"></slot> + </div> + </div> +</template> diff --git a/app/assets/javascripts/security_configuration/components/upgrade_banner.vue b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue new file mode 100644 index 00000000000..ca0f9e5c85a --- /dev/null +++ b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue @@ -0,0 +1,45 @@ +<script> +import { GlBanner } from '@gitlab/ui'; +import { s__ } from '~/locale'; + +export default { + components: { + GlBanner, + }, + inject: ['upgradePath'], + i18n: { + title: s__('SecurityConfiguration|Secure your project with Ultimate'), + bodyStart: s__( + `SecurityConfiguration|GitLab Ultimate checks your application for security vulnerabilities + that may lead to unauthorized access, data leaks, and denial of service + attacks. Its features include:`, + ), + bodyListItems: [ + s__('SecurityConfiguration|Vulnerability details and statistics in the merge request.'), + s__('SecurityConfiguration|High-level vulnerability statistics across projects and groups.'), + s__('SecurityConfiguration|Runtime security metrics for application environments.'), + ], + bodyEnd: s__( + 'SecurityConfiguration|With the information provided, you can immediately begin risk analysis and remediation within GitLab.', + ), + buttonText: s__('SecurityConfiguration|Upgrade or start a free trial'), + }, +}; +</script> + +<template> + <gl-banner + :title="$options.i18n.title" + :button-text="$options.i18n.buttonText" + :button-link="upgradePath" + v-on="$listeners" + > + <p>{{ $options.i18n.bodyStart }}</p> + <ul> + <li v-for="bodyListItem in $options.i18n.bodyListItems" :key="bodyListItem"> + {{ bodyListItem }} + </li> + </ul> + <p>{{ $options.i18n.bodyEnd }}</p> + </gl-banner> +</template> |