From 2bc933fbdac11d9b075a1f668957093bd59ba707 Mon Sep 17 00:00:00 2001 From: Mark Florian <mflorian@gitlab.com> Date: Thu, 17 Jun 2021 13:03:41 +0100 Subject: [PATCH] Document Security Configuration page redesign This change also tweaks the appearance of the redesigned Security Configuration page: - Adds static text to left column - Limits the width of the page content - Adjusts column fractions to 4:8 - Fixes a bug where the configuration history link wasn't displaying - Moves a line-height class to the SectionLayout component - Changes the description of DAST Scans to better reflect the feature Part of https://gitlab.com/gitlab-org/gitlab/-/issues/331614. --- .../components/constants.js | 4 +- .../components/redesigned_app.vue | 57 +++++++++++-------- .../components/section_layout.vue | 6 +- .../security/configuration/show.html.haml | 2 + .../configuration/index.md | 46 +++++++++++++++ locale/gitlab.pot | 14 +++-- .../components/redesigned_app_spec.js | 37 +++++++++--- 7 files changed, 126 insertions(+), 40 deletions(-) diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js index 142dade914b32..f4e060fbcdc07 100644 --- a/app/assets/javascripts/security_configuration/components/constants.js +++ b/app/assets/javascripts/security_configuration/components/constants.js @@ -34,8 +34,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'); diff --git a/app/assets/javascripts/security_configuration/components/redesigned_app.vue b/app/assets/javascripts/security_configuration/components/redesigned_app.vue index d8a12f4a792f6..64d908392b5d8 100644 --- a/app/assets/javascripts/security_configuration/components/redesigned_app.vue +++ b/app/assets/javascripts/security_configuration/components/redesigned_app.vue @@ -8,12 +8,15 @@ 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'), }; @@ -84,16 +87,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">{{ @@ -115,16 +121,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 1e1f83a6d9919..e351f9b9d8da7 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/views/projects/security/configuration/show.html.haml b/app/views/projects/security/configuration/show.html.haml index 4d6feb9de6da3..9eb842d101589 100644 --- a/app/views/projects/security/configuration/show.html.haml +++ b/app/views/projects/security/configuration/show.html.haml @@ -1,4 +1,6 @@ - breadcrumb_title _("Security Configuration") - page_title _("Security Configuration") +- redesign_enabled = ::Feature.enabled?(:security_configuration_redesign, default_enabled: :yaml) +- @content_class = "limit-container-width" unless fluid_layout || !redesign_enabled #js-security-configuration-static{ data: { project_path: @project.full_path, upgrade_path: security_upgrade_path } } diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md index 8c34303ca0069..f2fb11da66e84 100644 --- a/doc/user/application_security/configuration/index.md +++ b/doc/user/application_security/configuration/index.md @@ -25,6 +25,27 @@ For each security control the page displays: - **Security Control:** Name, description, and a documentation link. - **Manage:** A management option or a documentation link. +## UI redesign + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326926) in 14.0 for GitLab Free and Premium, behind a feature flag, disabled by default. +> - Enabled on GitLab.com. +> - Recommended for production use. +> - It can be enabled or disabled for a single project. +> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-ui-redesign). **(FREE SELF)** + +WARNING: +This feature might not be available to you. Check the **version history** note above for details. + +The Security Configuration page has been redesigned in GitLab Free and Premium. +The same functionality exists as before, but presented in a more extensible +way. + +For each security control the page displays: + +- Its name, description and a documentation link. +- Whether or not it is available. +- A configuration button or a link to its configuration guide. + ## Status **(ULTIMATE)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. @@ -52,3 +73,28 @@ You can configure the following security controls: - Secret Detection - Select **Configure via Merge Request** to create a merge request with the changes required to enable Secret Detection. For more details, see [Enable Secret Detection via an automatic merge request](../secret_detection/index.md#enable-secret-detection-via-an-automatic-merge-request). + +## Enable or disable UI redesign **(FREE SELF)** + +The Security Configuration redesign is under development, but is ready for +production use. It is deployed behind a feature flag that is **disabled by +default**. +[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) can enable it. + +To enable it: + +```ruby +# For the instance +Feature.enable(:security_configuration_redesign) +# For a single project +Feature.enable(:security_configuration_redesign, Project.find(<project id>)) +``` + +To disable it: + +```ruby +# For the instance +Feature.disable(:security_configuration_redesign) +# For a single project +Feature.disable(:security_configuration_redesign, Project.find(<project id>)) +``` diff --git a/locale/gitlab.pot b/locale/gitlab.pot index bd43054fda51c..aad534d813580 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -28306,9 +28306,6 @@ msgstr "" msgid "Save space and find images in the container Registry. remove unneeded tags and keep only the ones you want. %{linkStart}How does cleanup work?%{linkEnd}" msgstr "" -msgid "Saved scan settings and target site settings which are reusable." -msgstr "" - msgid "Saving" msgstr "" @@ -28706,6 +28703,9 @@ msgstr "" msgid "SecurityConfiguration|Configuration guide" msgstr "" +msgid "SecurityConfiguration|Configuration history" +msgstr "" + msgid "SecurityConfiguration|Configure" msgstr "" @@ -28754,6 +28754,9 @@ msgstr "" msgid "SecurityConfiguration|Manage" msgstr "" +msgid "SecurityConfiguration|Manage profiles for use by DAST scans." +msgstr "" + msgid "SecurityConfiguration|Manage scans" msgstr "" @@ -28763,6 +28766,9 @@ msgstr "" msgid "SecurityConfiguration|Not enabled" msgstr "" +msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan." +msgstr "" + msgid "SecurityConfiguration|Runtime security metrics for application environments." msgstr "" @@ -28787,7 +28793,7 @@ msgstr "" msgid "SecurityConfiguration|Testing & Compliance" msgstr "" -msgid "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." +msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}." msgstr "" msgid "SecurityConfiguration|Upgrade or start a free trial" diff --git a/spec/frontend/security_configuration/components/redesigned_app_spec.js b/spec/frontend/security_configuration/components/redesigned_app_spec.js index 7e27a3e11082a..69c79082f5a68 100644 --- a/spec/frontend/security_configuration/components/redesigned_app_spec.js +++ b/spec/frontend/security_configuration/components/redesigned_app_spec.js @@ -23,6 +23,7 @@ import { } from '~/vue_shared/security_reports/constants'; const upgradePath = '/upgrade'; +const gitlabCiHistoryPath = 'test/historyPath'; describe('redesigned App component', () => { let wrapper; @@ -52,8 +53,28 @@ describe('redesigned App component', () => { const findTabs = () => wrapper.findAllComponents(GlTab); const findByTestId = (id) => wrapper.findByTestId(id); const findFeatureCards = () => wrapper.findAllComponents(FeatureCard); - const findComplianceViewHistoryLink = () => findByTestId('compliance-view-history-link'); - const findSecurityViewHistoryLink = () => findByTestId('security-view-history-link'); + const findLink = ({ href, text, container = wrapper }) => { + const selector = `a[href="${href}"]`; + const link = container.find(selector); + + if (link.exists() && link.text() === text) { + return link; + } + + return wrapper.find(`${selector} does not exist`); + }; + const findSecurityViewHistoryLink = () => + findLink({ + href: gitlabCiHistoryPath, + text: i18n.configurationHistory, + container: findByTestId('security-testing-tab'), + }); + const findComplianceViewHistoryLink = () => + findLink({ + href: gitlabCiHistoryPath, + text: i18n.configurationHistory, + container: findByTestId('compliance-testing-tab'), + }); const findUpgradeBanner = () => wrapper.findComponent(UpgradeBanner); const securityFeaturesMock = [ @@ -119,6 +140,10 @@ describe('redesigned App component', () => { expect(cards.at(1).props()).toEqual({ feature: complianceFeaturesMock[0] }); }); + it('renders a basic description', () => { + expect(wrapper.text()).toContain(i18n.description); + }); + it('should not show latest pipeline link when latestPipelinePath is not defined', () => { expect(findByTestId('latest-pipeline-info').exists()).toBe(false); }); @@ -193,9 +218,8 @@ describe('redesigned App component', () => { it('should show latest pipeline info on the security tab with correct link when latestPipelinePath is defined', () => { const latestPipelineInfoSecurity = findByTestId('latest-pipeline-info-security'); - expect(latestPipelineInfoSecurity.exists()).toBe(true); expect(latestPipelineInfoSecurity.text()).toMatchInterpolatedText( - i18n.securityTestingDescription, + i18n.latestPipelineDescription, ); expect(latestPipelineInfoSecurity.find('a').attributes('href')).toBe('test/path'); }); @@ -203,9 +227,8 @@ describe('redesigned App component', () => { it('should show latest pipeline info on the compliance tab with correct link when latestPipelinePath is defined', () => { const latestPipelineInfoCompliance = findByTestId('latest-pipeline-info-compliance'); - expect(latestPipelineInfoCompliance.exists()).toBe(true); expect(latestPipelineInfoCompliance.text()).toMatchInterpolatedText( - i18n.securityTestingDescription, + i18n.latestPipelineDescription, ); expect(latestPipelineInfoCompliance.find('a').attributes('href')).toBe('test/path'); }); @@ -217,7 +240,7 @@ describe('redesigned App component', () => { augmentedSecurityFeatures: securityFeaturesMock, augmentedComplianceFeatures: complianceFeaturesMock, gitlabCiPresent: true, - gitlabCiHistoryPath: 'test/historyPath', + gitlabCiHistoryPath, }); }); -- GitLab