Commit bdc467e2 authored by Dheeraj Joshi's avatar Dheeraj Joshi Committed by Kushal Pandya

Add new options in DAST Scanner Profile

This would allow users to choose scan type,
and option to enable ajax spider and debug
messages for On-demand Scan Profiles
parent 26cfa3c1
<script>
import { SCAN_TYPE_OPTIONS } from 'ee/security_configuration/dast_scanner_profiles/constants';
import ProfileSelector from './profile_selector.vue';
import SummaryCell from './summary_cell.vue';
import { __, s__ } from '~/locale';
export default {
name: 'OnDemandScansScannerProfileSelector',
......@@ -23,6 +25,19 @@ export default {
default: '',
},
},
methods: {
getScanModeText(scanType) {
return SCAN_TYPE_OPTIONS.find(({ value }) => scanType === value)?.text;
},
getAjaxSpiderText(isEnabled) {
return isEnabled ? __('On') : __('Off');
},
getDebugMessageText(isEnabled) {
return isEnabled
? s__('DastProfiles|Show debug messages')
: s__('DastProfiles|Hide debug messages');
},
},
};
</script>
......@@ -44,7 +59,10 @@ export default {
<template #new-profile>{{ s__('OnDemandScans|Create a new scanner profile') }}</template>
<template #summary="{ profile }">
<div class="row">
<summary-cell :label="s__('DastProfiles|Scan mode')" :value="s__('DastProfiles|Passive')" />
<summary-cell
:label="s__('DastProfiles|Scan mode')"
:value="getScanModeText(profile.scanType)"
/>
</div>
<div class="row">
<summary-cell
......@@ -56,6 +74,16 @@ export default {
:value="n__('%d second', '%d seconds', profile.targetTimeout)"
/>
</div>
<div class="row">
<summary-cell
:label="s__('DastProfiles|AJAX spider')"
:value="getAjaxSpiderText(profile.useAjaxSpider)"
/>
<summary-cell
:label="s__('DastProfiles|Debug messages')"
:value="getDebugMessageText(profile.showDebugMessages)"
/>
</div>
</template>
</profile-selector>
</template>
......@@ -16,7 +16,7 @@ export default {
<template>
<div class="col-md-6">
<div class="row">
<div class="row gl-my-2">
<div class="col-md-3">{{ label }}:</div>
<div class="col-md-9">
<strong>{{ value }}</strong>
......
......@@ -24,6 +24,9 @@ query DastScannerProfiles(
profileName
spiderTimeout
targetTimeout
scanType
useAjaxSpider
showDebugMessages
editPath
}
}
......
......@@ -12,14 +12,17 @@ import {
GlIcon,
GlTooltipDirective,
GlInputGroupText,
GlFormCheckbox,
GlFormRadioGroup,
} from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
import { serializeFormObject, isEmptyValue } from '~/lib/utils/forms';
import dastScannerProfileCreateMutation from '../graphql/dast_scanner_profile_create.mutation.graphql';
import dastScannerProfileUpdateMutation from '../graphql/dast_scanner_profile_update.mutation.graphql';
import { SCAN_TYPE, SCAN_TYPE_OPTIONS } from '../constants';
const initField = (value, isRequired = false) => ({
const initField = (value, isRequired = true) => ({
value,
required: isRequired,
state: null,
......@@ -43,6 +46,8 @@ export default {
GlModal,
GlIcon,
GlInputGroupText,
GlFormCheckbox,
GlFormRadioGroup,
},
directives: {
GlTooltip: GlTooltipDirective,
......@@ -63,12 +68,22 @@ export default {
},
},
data() {
const { name = '', spiderTimeout = '', targetTimeout = '' } = this.profile;
const {
name = '',
spiderTimeout = '',
targetTimeout = '',
scanType = SCAN_TYPE.PASSIVE,
useAjaxSpider = false,
showDebugMessages = false,
} = this.profile;
const form = {
profileName: initField(name, true),
spiderTimeout: initField(spiderTimeout, true),
targetTimeout: initField(targetTimeout, true),
profileName: initField(name),
spiderTimeout: initField(spiderTimeout),
targetTimeout: initField(targetTimeout),
scanType: initField(scanType),
useAjaxSpider: initField(useAjaxSpider),
showDebugMessages: initField(showDebugMessages),
};
return {
......@@ -86,6 +101,7 @@ export default {
min: TARGET_TIMEOUT_MIN,
max: TARGET_TIMEOUT_MAX,
},
SCAN_TYPE_OPTIONS,
computed: {
isEdit() {
return Boolean(this.profile.id);
......@@ -113,6 +129,15 @@ export default {
targetTimeout: s__(
'DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request.',
),
scanMode: s__(
'DastProfiles|Active scan will make active attacks against the target site while Passive scan will not',
),
ajaxSpider: s__(
'DastProfiles|Enable it to run the AJAX spider (in addition to the traditional spider) to crawl the target site',
),
debugMessage: s__(
'DastProfiles|Enable it to include the debug messages in DAST console output',
),
},
};
},
......@@ -237,11 +262,29 @@ export default {
/>
</gl-form-group>
<hr />
<hr class="gl-border-gray-100" />
<gl-form-group>
<template #label>
{{ s__('DastProfiles|Scan mode') }}
<gl-icon
v-gl-tooltip.hover
name="information-o"
class="gl-vertical-align-text-bottom gl-text-gray-400 gl-ml-2"
:title="i18n.tooltips.scanMode"
/>
</template>
<gl-form-radio-group
v-model="form.scanType.value"
:options="$options.SCAN_TYPE_OPTIONS"
data-testid="scan-type-option"
/>
</gl-form-group>
<div class="row">
<gl-form-group
class="col-md-6"
class="col-md-6 mb-0"
:state="form.spiderTimeout.state"
:invalid-feedback="form.spiderTimeout.feedback"
>
......@@ -273,7 +316,7 @@ export default {
</gl-form-group>
<gl-form-group
class="col-md-6"
class="col-md-6 mb-0"
:state="form.targetTimeout.state"
:invalid-feedback="form.targetTimeout.feedback"
>
......@@ -305,7 +348,41 @@ export default {
</gl-form-group>
</div>
<hr />
<hr class="gl-border-gray-100" />
<div class="row">
<gl-form-group class="col-md-6 mb-0">
<template #label>
{{ s__('DastProfiles|AJAX spider') }}
<gl-icon
v-gl-tooltip.hover
name="information-o"
class="gl-vertical-align-text-bottom gl-text-gray-400 gl-ml-2"
:title="i18n.tooltips.ajaxSpider"
/>
</template>
<gl-form-checkbox v-model="form.useAjaxSpider.value">{{
s__('DastProfiles|Turn on AJAX spider')
}}</gl-form-checkbox>
</gl-form-group>
<gl-form-group class="col-md-6 mb-0">
<template #label>
{{ s__('DastProfiles|Debug messages') }}
<gl-icon
v-gl-tooltip.hover
name="information-o"
class="gl-vertical-align-text-bottom gl-text-gray-400 gl-ml-2"
:title="i18n.tooltips.debugMessage"
/>
</template>
<gl-form-checkbox v-model="form.showDebugMessages.value">{{
s__('DastProfiles|Show debug messages')
}}</gl-form-checkbox>
</gl-form-group>
</div>
<hr class="gl-border-gray-100" />
<gl-button
type="submit"
......
import { s__ } from '~/locale';
export const SCAN_TYPE = {
ACTIVE: 'ACTIVE',
PASSIVE: 'PASSIVE',
};
export const SCAN_TYPE_OPTIONS = [
{
value: SCAN_TYPE.ACTIVE,
text: s__('DastProfiles|Active'),
},
{
value: SCAN_TYPE.PASSIVE,
text: s__('DastProfiles|Passive'),
},
];
......@@ -3,6 +3,9 @@ mutation dastScannerProfileCreate(
$profileName: String!
$spiderTimeout: Int!
$targetTimeout: Int!
$scanType: DastScanTypeEnum!
$useAjaxSpider: Boolean!
$showDebugMessages: Boolean!
) {
dastScannerProfileCreate(
input: {
......@@ -10,6 +13,9 @@ mutation dastScannerProfileCreate(
profileName: $profileName
spiderTimeout: $spiderTimeout
targetTimeout: $targetTimeout
scanType: $scanType
useAjaxSpider: $useAjaxSpider
showDebugMessages: $showDebugMessages
}
) {
errors
......
......@@ -4,6 +4,9 @@ mutation dastScannerProfileUpdate(
$profileName: String!
$spiderTimeout: Int!
$targetTimeout: Int!
$scanType: DastScanTypeEnum!
$useAjaxSpider: Boolean!
$showDebugMessages: Boolean!
) {
dastScannerProfileUpdate(
input: {
......@@ -12,6 +15,9 @@ mutation dastScannerProfileUpdate(
profileName: $profileName
spiderTimeout: $spiderTimeout
targetTimeout: $targetTimeout
scanType: $scanType
useAjaxSpider: $useAjaxSpider
showDebugMessages: $showDebugMessages
}
) {
id
......
......@@ -5,4 +5,7 @@
.js-dast-scanner-profile-form{ data: { project_full_path: @project.path_with_namespace,
profiles_library_path: project_security_configuration_dast_profiles_path(@project, anchor: 'scanner-profiles'),
scanner_profile: { id: @scanner_profile.to_global_id.to_s, name: @scanner_profile.name, spider_timeout: @scanner_profile.spider_timeout, target_timeout: @scanner_profile.target_timeout }.to_json } }
scanner_profile: { id: @scanner_profile.to_global_id.to_s, name: @scanner_profile.name,
spider_timeout: @scanner_profile.spider_timeout, target_timeout: @scanner_profile.target_timeout,
scan_type: @scanner_profile.scan_type.upcase, use_ajax_spider: @scanner_profile.use_ajax_spider,
show_debug_messages: @scanner_profile.show_debug_messages }.to_json } }
---
title: Add more options in DAST On-demand Scanner Profile
merge_request: 43660
author:
type: added
......@@ -195,7 +195,7 @@ exports[`OnDemandScansScannerProfileSelector renders properly with profiles 1`]
class="col-md-6"
>
<div
class="row"
class="row gl-my-2"
>
<div
class="col-md-3"
......@@ -221,7 +221,7 @@ exports[`OnDemandScansScannerProfileSelector renders properly with profiles 1`]
class="col-md-6"
>
<div
class="row"
class="row gl-my-2"
>
<div
class="col-md-3"
......@@ -243,7 +243,7 @@ exports[`OnDemandScansScannerProfileSelector renders properly with profiles 1`]
class="col-md-6"
>
<div
class="row"
class="row gl-my-2"
>
<div
class="col-md-3"
......@@ -261,6 +261,54 @@ exports[`OnDemandScansScannerProfileSelector renders properly with profiles 1`]
</div>
</div>
</div>
<div
class="row"
>
<div
class="col-md-6"
>
<div
class="row gl-my-2"
>
<div
class="col-md-3"
>
AJAX spider:
</div>
<div
class="col-md-9"
>
<strong>
Off
</strong>
</div>
</div>
</div>
<div
class="col-md-6"
>
<div
class="row gl-my-2"
>
<div
class="col-md-3"
>
Debug messages:
</div>
<div
class="col-md-9"
>
<strong>
Hide debug messages
</strong>
</div>
</div>
</div>
</div>
</div>
<!---->
<!---->
......
......@@ -195,7 +195,7 @@ exports[`OnDemandScansSiteProfileSelector renders properly with profiles 1`] = `
class="col-md-6"
>
<div
class="row"
class="row gl-my-2"
>
<div
class="col-md-3"
......
......@@ -2,7 +2,7 @@
exports[`OnDemandScansProfileSummaryCell renders properly 1`] = `
"<div class=\\"col-md-6\\">
<div class=\\"row\\">
<div class=\\"row gl-my-2\\">
<div class=\\"col-md-3\\">Row Label:</div>
<div class=\\"col-md-9\\"><strong>Row Value</strong></div>
</div>
......
......@@ -4,12 +4,18 @@ export const scannerProfiles = [
profileName: 'Scanner profile #1',
spiderTimeout: 5,
targetTimeout: 10,
scanType: 'PASSIVE',
useAjaxSpider: false,
showDebugMessages: false,
},
{
id: 'gid://gitlab/DastScannerProfile/2',
profileName: 'Scanner profile #2',
spiderTimeout: 20,
targetTimeout: 150,
scanType: 'ACTIVE',
useAjaxSpider: true,
showDebugMessages: true,
},
];
......
......@@ -6,6 +6,8 @@ import { TEST_HOST } from 'helpers/test_constants';
import DastScannerProfileForm from 'ee/security_configuration/dast_scanner_profiles/components/dast_scanner_profile_form.vue';
import dastScannerProfileCreateMutation from 'ee/security_configuration/dast_scanner_profiles/graphql/dast_scanner_profile_create.mutation.graphql';
import dastScannerProfileUpdateMutation from 'ee/security_configuration/dast_scanner_profiles/graphql/dast_scanner_profile_update.mutation.graphql';
import { SCAN_TYPE } from 'ee/security_configuration/dast_scanner_profiles/constants';
import { scannerProfiles } from 'ee_jest/on_demand_scans/mock_data';
import { redirectTo } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility', () => ({
......@@ -14,9 +16,16 @@ jest.mock('~/lib/utils/url_utility', () => ({
const projectFullPath = 'group/project';
const profilesLibraryPath = `${TEST_HOST}/${projectFullPath}/-/security/configuration/dast_profiles`;
const profileName = 'My DAST scanner profile';
const spiderTimeout = 12;
const targetTimeout = 20;
const defaultProfile = scannerProfiles[0];
const {
profileName,
spiderTimeout,
targetTimeout,
scanType,
useAjaxSpider,
showDebugMessages,
} = defaultProfile;
const defaultProps = {
profilesLibraryPath,
......@@ -27,18 +36,19 @@ describe('DAST Scanner Profile', () => {
let wrapper;
const withinComponent = () => within(wrapper.element);
const findByTestId = testId => wrapper.find(`[data-testid="${testId}"`);
const findForm = () => wrapper.find(GlForm);
const findProfileNameInput = () => wrapper.find('[data-testid="profile-name-input"]');
const findSpiderTimeoutInput = () => wrapper.find('[data-testid="spider-timeout-input"]');
const findTargetTimeoutInput = () => wrapper.find('[data-testid="target-timeout-input"]');
const findSubmitButton = () =>
wrapper.find('[data-testid="dast-scanner-profile-form-submit-button"]');
const findCancelButton = () =>
wrapper.find('[data-testid="dast-scanner-profile-form-cancel-button"]');
const findProfileNameInput = () => findByTestId('profile-name-input');
const findSpiderTimeoutInput = () => findByTestId('spider-timeout-input');
const findTargetTimeoutInput = () => findByTestId('target-timeout-input');
const findSubmitButton = () => findByTestId('dast-scanner-profile-form-submit-button');
const findCancelButton = () => findByTestId('dast-scanner-profile-form-cancel-button');
const findScanType = () => findByTestId('scan-type-option');
const findCancelModal = () => wrapper.find(GlModal);
const submitForm = () => findForm().vm.$emit('submit', { preventDefault: () => {} });
const findAlert = () => wrapper.find(GlAlert);
const submitForm = () => findForm().vm.$emit('submit', { preventDefault: () => {} });
const componentFactory = (mountFn = shallowMount) => options => {
wrapper = mountFn(
......@@ -136,9 +146,9 @@ describe('DAST Scanner Profile', () => {
});
describe.each`
title | profile | mutation | mutationVars | mutationKind
${'New scanner profile'} | ${{}} | ${dastScannerProfileCreateMutation} | ${{}} | ${'dastScannerProfileCreate'}
${'Edit scanner profile'} | ${{ id: 1, name: 'foo', spiderTimeout: 2, targetTimeout: 12 }} | ${dastScannerProfileUpdateMutation} | ${{ id: 1 }} | ${'dastScannerProfileUpdate'}
title | profile | mutation | mutationVars | mutationKind
${'New scanner profile'} | ${{}} | ${dastScannerProfileCreateMutation} | ${{}} | ${'dastScannerProfileCreate'}
${'Edit scanner profile'} | ${defaultProfile} | ${dastScannerProfileUpdateMutation} | ${{ id: defaultProfile.id }} | ${'dastScannerProfileUpdate'}
`('$title', ({ profile, title, mutation, mutationVars, mutationKind }) => {
beforeEach(() => {
createFullComponent({
......@@ -152,8 +162,9 @@ describe('DAST Scanner Profile', () => {
expect(withinComponent().getByRole('heading', { name: title })).not.toBeNull();
});
it('populates the fields with the data passed in via the profile prop', () => {
it('populates the fields with the data passed in via the profile prop or default values', () => {
expect(findProfileNameInput().element.value).toBe(profile?.name ?? '');
expect(findScanType().vm.$attrs.checked).toBe(profile?.scanType ?? SCAN_TYPE.PASSIVE);
});
describe('submission', () => {
......@@ -182,6 +193,9 @@ describe('DAST Scanner Profile', () => {
spiderTimeout,
targetTimeout,
projectFullPath,
scanType,
useAjaxSpider,
showDebugMessages,
...mutationVars,
},
});
......
......@@ -8022,6 +8022,15 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
msgid "DastProfiles|AJAX spider"
msgstr ""
msgid "DastProfiles|Active"
msgstr ""
msgid "DastProfiles|Active scan will make active attacks against the target site while Passive scan will not"
msgstr ""
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
......@@ -8061,6 +8070,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
msgid "DastProfiles|Debug messages"
msgstr ""
msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
......@@ -8079,9 +8091,18 @@ msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
msgid "DastProfiles|Enable it to include the debug messages in DAST console output"
msgstr ""
msgid "DastProfiles|Enable it to run the AJAX spider (in addition to the traditional spider) to crawl the target site"
msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Hide debug messages"
msgstr ""
msgid "DastProfiles|Manage Profiles"
msgstr ""
......@@ -8133,6 +8154,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
msgid "DastProfiles|Show debug messages"
msgstr ""
msgid "DastProfiles|Site Profile"
msgstr ""
......@@ -8172,6 +8196,9 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|Validate"
msgstr ""
......@@ -17886,6 +17913,9 @@ msgstr ""
msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
msgstr ""
msgid "On"
msgstr ""
msgid "On track"
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