Commit f6fad46c authored by Jacques Erasmus's avatar Jacques Erasmus

Merge branch '235545-remove-scanner-profiles-feature-flag' into 'master'

Remove security_on_demand_scans_scanner_profiles feature flag

See merge request gitlab-org/gitlab!41892
parents 7f281773 7e4169dd
...@@ -674,11 +674,6 @@ To delete an existing site profile: ...@@ -674,11 +674,6 @@ To delete an existing site profile:
## Scanner profile ## Scanner profile
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222767) in GitLab 13.4. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222767) in GitLab 13.4.
> - [Deployed behind a feature flag](../../feature_flags.md), enabled by default.
> - Enabled on GitLab.com.
> - Can be enabled or disabled per-project.
> - Recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can [disable this feature](#enable-or-disable-dast-scanner-profiles).
A scanner profile defines the scanner settings used to run an on-demand scan: A scanner profile defines the scanner settings used to run an on-demand scan:
...@@ -713,29 +708,6 @@ To delete a scanner profile: ...@@ -713,29 +708,6 @@ To delete a scanner profile:
1. Click **Manage** in the **DAST Profiles** row. 1. Click **Manage** in the **DAST Profiles** row.
1. Click **{remove}** in the scanner profile's row. 1. Click **{remove}** in the scanner profile's row.
### Enable or disable DAST scanner profiles
The scanner profile feature is ready for production use. It's deployed behind a feature flag that
is **enabled by default**. [GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) can opt to disable it.
To disable it:
```ruby
# Instance-wide
Feature.disable(:security_on_demand_scans_scanner_profiles)
# or by project
Feature.disable(:security_on_demand_scans_scanner_profiles, Project.find(<project id>))
```
To enable it:
```ruby
# Instance-wide
Feature.enable(:security_on_demand_scans_scanner_profiles)
# or by project
Feature.enable(:security_on_demand_scans_scanner_profiles, Project.find(<project ID>))
```
## On-demand scans ## On-demand scans
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.2. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.2.
......
...@@ -6,7 +6,6 @@ import { ...@@ -6,7 +6,6 @@ import {
GlCard, GlCard,
GlForm, GlForm,
GlFormGroup, GlFormGroup,
GlIcon,
GlLink, GlLink,
GlDropdown, GlDropdown,
GlDropdownItem, GlDropdownItem,
...@@ -48,7 +47,6 @@ export default { ...@@ -48,7 +47,6 @@ export default {
GlCard, GlCard,
GlForm, GlForm,
GlFormGroup, GlFormGroup,
GlIcon,
GlLink, GlLink,
GlDropdown, GlDropdown,
GlDropdownItem, GlDropdownItem,
...@@ -75,9 +73,6 @@ export default { ...@@ -75,9 +73,6 @@ export default {
Sentry.captureException(e); Sentry.captureException(e);
this.showErrors(ERROR_FETCH_SCANNER_PROFILES); this.showErrors(ERROR_FETCH_SCANNER_PROFILES);
}, },
skip() {
return !this.glFeatures.securityOnDemandScansScannerProfiles;
},
}, },
siteProfiles: { siteProfiles: {
query: dastSiteProfilesQuery, query: dastSiteProfilesQuery,
...@@ -129,9 +124,7 @@ export default { ...@@ -129,9 +124,7 @@ export default {
scannerProfiles: [], scannerProfiles: [],
siteProfiles: [], siteProfiles: [],
form: { form: {
...(this.glFeatures.securityOnDemandScansScannerProfiles dastScannerProfileId: initField(null),
? { dastScannerProfileId: initField(null) }
: {}),
dastSiteProfileId: initField(null), dastSiteProfileId: initField(null),
}, },
loading: false, loading: false,
...@@ -295,7 +288,7 @@ export default { ...@@ -295,7 +288,7 @@ export default {
{{ s__('OnDemandScans|Scanner settings') }} {{ s__('OnDemandScans|Scanner settings') }}
</h3> </h3>
</div> </div>
<div v-if="glFeatures.securityOnDemandScansScannerProfiles" class="col-5 gl-text-right"> <div class="col-5 gl-text-right">
<gl-button <gl-button
:href="scannerProfiles.length ? scannerProfilesLibraryPath : null" :href="scannerProfiles.length ? scannerProfilesLibraryPath : null"
:disabled="!scannerProfiles.length" :disabled="!scannerProfiles.length"
...@@ -310,7 +303,6 @@ export default { ...@@ -310,7 +303,6 @@ export default {
</div> </div>
</template> </template>
<template v-if="glFeatures.securityOnDemandScansScannerProfiles">
<gl-form-group v-if="scannerProfiles.length"> <gl-form-group v-if="scannerProfiles.length">
<template #label> <template #label>
{{ s__('OnDemandScans|Use existing scanner profile') }} {{ s__('OnDemandScans|Use existing scanner profile') }}
...@@ -386,34 +378,6 @@ export default { ...@@ -386,34 +378,6 @@ export default {
{{ s__('OnDemandScans|Create a new scanner profile') }} {{ s__('OnDemandScans|Create a new scanner profile') }}
</gl-button> </gl-button>
</template> </template>
</template>
<template v-else>
<gl-form-group class="gl-mt-4">
<template #label>
{{ s__('OnDemandScans|Scan mode') }}
<gl-icon
v-gl-tooltip.hover
name="information-o"
class="gl-vertical-align-text-bottom gl-text-gray-600"
:title="s__('OnDemandScans|Only a passive scan can be performed on demand.')"
/>
</template>
{{ s__('OnDemandScans|Passive') }}
</gl-form-group>
<gl-form-group class="gl-mt-7 gl-mb-2">
<template #label>
{{ s__('OnDemandScans|Attached branch') }}
<gl-icon
v-gl-tooltip.hover
name="information-o"
class="gl-vertical-align-text-bottom gl-text-gray-600"
:title="s__('OnDemandScans|Attached branch is where the scan job runs.')"
/>
</template>
{{ defaultBranch }}
</gl-form-group>
</template>
</gl-card> </gl-card>
<gl-card> <gl-card>
......
...@@ -4,7 +4,6 @@ import { GlDropdown, GlDropdownItem, GlTab, GlTabs } from '@gitlab/ui'; ...@@ -4,7 +4,6 @@ import { GlDropdown, GlDropdownItem, GlTab, GlTabs } from '@gitlab/ui';
import { camelCase, kebabCase } from 'lodash'; import { camelCase, kebabCase } from 'lodash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { getLocationHash } from '~/lib/utils/url_utility'; import { getLocationHash } from '~/lib/utils/url_utility';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ProfilesList from './dast_profiles_list.vue'; import ProfilesList from './dast_profiles_list.vue';
import * as cacheUtils from '../graphql/cache_utils'; import * as cacheUtils from '../graphql/cache_utils';
import { getProfileSettings } from '../settings/profiles'; import { getProfileSettings } from '../settings/profiles';
...@@ -17,7 +16,6 @@ export default { ...@@ -17,7 +16,6 @@ export default {
GlTabs, GlTabs,
ProfilesList, ProfilesList,
}, },
mixins: [glFeatureFlagMixin()],
props: { props: {
createNewProfilePaths: { createNewProfilePaths: {
type: Object, type: Object,
...@@ -37,14 +35,11 @@ export default { ...@@ -37,14 +35,11 @@ export default {
}, },
computed: { computed: {
profileSettings() { profileSettings() {
const { glFeatures, createNewProfilePaths } = this; const { createNewProfilePaths } = this;
return getProfileSettings( return getProfileSettings({
{
createNewProfilePaths, createNewProfilePaths,
}, });
glFeatures,
);
}, },
tabIndex: { tabIndex: {
get() { get() {
......
...@@ -5,16 +5,7 @@ import dastScannerProfilesDelete from 'ee/security_configuration/dast_profiles/g ...@@ -5,16 +5,7 @@ import dastScannerProfilesDelete from 'ee/security_configuration/dast_profiles/g
import { dastProfilesDeleteResponse } from 'ee/security_configuration/dast_profiles/graphql/cache_utils'; import { dastProfilesDeleteResponse } from 'ee/security_configuration/dast_profiles/graphql/cache_utils';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
const hasNoFeatureFlagOrIsEnabled = glFeatures => ([, { featureFlag }]) => { export const getProfileSettings = ({ createNewProfilePaths }) => ({
if (!featureFlag) {
return true;
}
return Boolean(glFeatures[featureFlag]);
};
export const getProfileSettings = ({ createNewProfilePaths }, glFeatures) => {
const settings = {
siteProfiles: { siteProfiles: {
profileType: 'siteProfiles', profileType: 'siteProfiles',
createNewProfilePath: createNewProfilePaths.siteProfile, createNewProfilePath: createNewProfilePaths.siteProfile,
...@@ -56,7 +47,6 @@ export const getProfileSettings = ({ createNewProfilePaths }, glFeatures) => { ...@@ -56,7 +47,6 @@ export const getProfileSettings = ({ createNewProfilePaths }, glFeatures) => {
}), }),
}, },
}, },
featureFlag: 'securityOnDemandScansScannerProfiles',
tableFields: ['profileName'], tableFields: ['profileName'],
i18n: { i18n: {
createNewLinkText: s__('DastProfiles|Scanner Profile'), createNewLinkText: s__('DastProfiles|Scanner Profile'),
...@@ -72,9 +62,4 @@ export const getProfileSettings = ({ createNewProfilePaths }, glFeatures) => { ...@@ -72,9 +62,4 @@ export const getProfileSettings = ({ createNewProfilePaths }, glFeatures) => {
}, },
}, },
}, },
}; });
return Object.fromEntries(
Object.entries(settings).filter(hasNoFeatureFlagOrIsEnabled(glFeatures)),
);
};
...@@ -2,10 +2,7 @@ ...@@ -2,10 +2,7 @@
module Projects module Projects
class OnDemandScansController < Projects::ApplicationController class OnDemandScansController < Projects::ApplicationController
before_action do before_action :authorize_read_on_demand_scans!
authorize_read_on_demand_scans!
push_frontend_feature_flag(:security_on_demand_scans_scanner_profiles, project, default_enabled: true)
end
def index def index
end end
......
...@@ -4,9 +4,6 @@ module Projects ...@@ -4,9 +4,6 @@ module Projects
module Security module Security
class DastProfilesController < Projects::ApplicationController class DastProfilesController < Projects::ApplicationController
before_action :authorize_read_on_demand_scans! before_action :authorize_read_on_demand_scans!
before_action do
push_frontend_feature_flag(:security_on_demand_scans_scanner_profiles, project, default_enabled: true)
end
def show def show
end end
......
---
name: security_on_demand_scans_scanner_profiles
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39250
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235545
group: group::dynamic analysis
type: development
default_enabled: true
...@@ -67,7 +67,6 @@ describe('OnDemandScansApp', () => { ...@@ -67,7 +67,6 @@ describe('OnDemandScansApp', () => {
}, },
}, },
provide: { provide: {
glFeatures: { securityOnDemandScansScannerProfiles: true },
scannerProfilesLibraryPath, scannerProfilesLibraryPath,
siteProfilesLibraryPath, siteProfilesLibraryPath,
newScannerProfilePath, newScannerProfilePath,
...@@ -203,41 +202,6 @@ describe('OnDemandScansApp', () => { ...@@ -203,41 +202,6 @@ describe('OnDemandScansApp', () => {
}); });
}); });
describe('scanner profiles with feature flag disabled', () => {
beforeEach(() => {
createComponent({
provide: {
glFeatures: { securityOnDemandScansScannerProfiles: false },
},
});
});
it('shows static scanner settings and no scanner profiles component', () => {
expect(findScannerProfilesDropdown().exists()).toBe(false);
expect(findManageScannerProfilesButton().exists()).toBe(false);
expect(findCreateNewScannerProfileLink().exists()).toBe(false);
expect(wrapper.text()).toContain('Passive');
expect(wrapper.text()).toContain('master');
});
it('when submitting the form, GraphQL query does not include scanner data', async () => {
wrapper.vm.siteProfiles = siteProfiles;
await wrapper.vm.$nextTick();
jest
.spyOn(wrapper.vm.$apollo, 'mutate')
.mockResolvedValue({ data: { dastOnDemandScanCreate: { pipelineUrl, errors: [] } } });
findSiteProfilesDropdown().vm.$emit('input', siteProfiles[0]);
submitForm();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: dastOnDemandScanCreate,
variables: {
dastSiteProfileId: siteProfiles[0],
fullPath: projectPath,
},
});
});
});
describe.each` describe.each`
profileType | manageProfilesButtonFinder | manageProfilesPath | createNewProfileButtonFinder | newProfilePath | dropdownFinder profileType | manageProfilesButtonFinder | manageProfilesPath | createNewProfileButtonFinder | newProfilePath | dropdownFinder
${'scanner'} | ${findManageScannerProfilesButton} | ${scannerProfilesLibraryPath} | ${findCreateNewScannerProfileLink} | ${newScannerProfilePath} | ${findScannerProfilesDropdown} ${'scanner'} | ${findManageScannerProfilesButton} | ${scannerProfilesLibraryPath} | ${findCreateNewScannerProfileLink} | ${newScannerProfilePath} | ${findScannerProfilesDropdown}
......
...@@ -36,12 +36,6 @@ describe('EE - DastProfiles', () => { ...@@ -36,12 +36,6 @@ describe('EE - DastProfiles', () => {
}, },
}; };
const defaultProvide = {
glFeatures: {
securityOnDemandScansScannerProfiles: true,
},
};
wrapper = mountFn( wrapper = mountFn(
DastProfiles, DastProfiles,
merge( merge(
...@@ -49,7 +43,6 @@ describe('EE - DastProfiles', () => { ...@@ -49,7 +43,6 @@ describe('EE - DastProfiles', () => {
{ {
propsData: defaultProps, propsData: defaultProps,
mocks: defaultMocks, mocks: defaultMocks,
provide: defaultProvide,
}, },
options, options,
), ),
...@@ -59,24 +52,6 @@ describe('EE - DastProfiles', () => { ...@@ -59,24 +52,6 @@ describe('EE - DastProfiles', () => {
const createComponent = createComponentFactory(); const createComponent = createComponentFactory();
const createFullComponent = createComponentFactory(mount); const createFullComponent = createComponentFactory(mount);
const withFeatureFlag = (featureFlagName, { enabled, disabled }) => {
it.each([true, false])(`with ${featureFlagName} enabled: "%s"`, featureFlagStatus => {
createComponent({
provide: {
glFeatures: {
[featureFlagName]: featureFlagStatus,
},
},
});
if (featureFlagStatus) {
enabled();
} else {
disabled();
}
});
};
const withinComponent = () => within(wrapper.element); const withinComponent = () => within(wrapper.element);
const getProfilesComponent = profileType => wrapper.find(`[data-testid="${profileType}List"]`); const getProfilesComponent = profileType => wrapper.find(`[data-testid="${profileType}List"]`);
const getDropdownComponent = () => wrapper.find(GlDropdown); const getDropdownComponent = () => wrapper.find(GlDropdown);
...@@ -116,17 +91,10 @@ describe('EE - DastProfiles', () => { ...@@ -116,17 +91,10 @@ describe('EE - DastProfiles', () => {
); );
}); });
describe(`shows a "Scanner Profile" dropdown item that links to ${TEST_NEW_DAST_SCANNER_PROFILE_PATH}`, () => { it(`shows a "Scanner Profile" dropdown item that links to ${TEST_NEW_DAST_SCANNER_PROFILE_PATH}`, () => {
withFeatureFlag('securityOnDemandScansScannerProfiles', {
enabled: () => {
expect(getSiteProfilesDropdownItem('Scanner Profile').getAttribute('href')).toBe( expect(getSiteProfilesDropdownItem('Scanner Profile').getAttribute('href')).toBe(
TEST_NEW_DAST_SCANNER_PROFILE_PATH, TEST_NEW_DAST_SCANNER_PROFILE_PATH,
); );
},
disabled: () => {
expect(getSiteProfilesDropdownItem('Scanner Profile')).toBe(null);
},
});
}); });
}); });
......
...@@ -17679,12 +17679,6 @@ msgstr "" ...@@ -17679,12 +17679,6 @@ msgstr ""
msgid "On track" msgid "On track"
msgstr "" msgstr ""
msgid "OnDemandScans|Attached branch"
msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
msgstr ""
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later." msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr "" msgstr ""
...@@ -17721,18 +17715,9 @@ msgstr "" ...@@ -17721,18 +17715,9 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}" msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr "" msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
msgid "OnDemandScans|Passive"
msgstr ""
msgid "OnDemandScans|Run scan" msgid "OnDemandScans|Run scan"
msgstr "" msgstr ""
msgid "OnDemandScans|Scan mode"
msgstr ""
msgid "OnDemandScans|Scanner profile" msgid "OnDemandScans|Scanner profile"
msgstr "" msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment