Commit 1643cf25 authored by Mark Florian's avatar Mark Florian

Merge branch 'djadmin-site-profile-auth-integrate' into 'master'

Display new fields added to DAST site profiles

See merge request gitlab-org/gitlab!46848
parents 2c4280cf 86ecf315
---
name: security_dast_site_profiles_additional_fields
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46848
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292897
milestone: '13.7'
type: development
group: group::dynamic analysis
default_enabled: false
...@@ -24,6 +24,7 @@ import { ...@@ -24,6 +24,7 @@ import {
ERROR_MESSAGES, ERROR_MESSAGES,
SCANNER_PROFILES_QUERY, SCANNER_PROFILES_QUERY,
SITE_PROFILES_QUERY, SITE_PROFILES_QUERY,
SITE_PROFILES_EXTENDED_QUERY,
} from '../settings'; } from '../settings';
import dastOnDemandScanCreateMutation from '../graphql/dast_on_demand_scan_create.mutation.graphql'; import dastOnDemandScanCreateMutation from '../graphql/dast_on_demand_scan_create.mutation.graphql';
import ProfileSelectorSummaryCell from './profile_selector/summary_cell.vue'; import ProfileSelectorSummaryCell from './profile_selector/summary_cell.vue';
...@@ -74,11 +75,15 @@ export default { ...@@ -74,11 +75,15 @@ export default {
'selectedScannerProfileId', 'selectedScannerProfileId',
SCANNER_PROFILES_QUERY, SCANNER_PROFILES_QUERY,
), ),
siteProfiles: createProfilesApolloOptions( siteProfiles() {
'siteProfiles', return createProfilesApolloOptions(
'selectedSiteProfileId', 'siteProfiles',
SITE_PROFILES_QUERY, 'selectedSiteProfileId',
), this.glFeatures.securityDastSiteProfilesAdditionalFields
? SITE_PROFILES_EXTENDED_QUERY
: SITE_PROFILES_QUERY,
);
},
}, },
props: { props: {
helpPagePath: { helpPagePath: {
...@@ -313,6 +318,42 @@ export default { ...@@ -313,6 +318,42 @@ export default {
:value="selectedSiteProfile.targetUrl" :value="selectedSiteProfile.targetUrl"
/> />
</div> </div>
<template v-if="glFeatures.securityDastSiteProfilesAdditionalFields">
<template v-if="selectedSiteProfile.auth.enabled">
<div class="row">
<profile-selector-summary-cell
:label="s__('DastProfiles|Authentication URL')"
:value="selectedSiteProfile.auth.url"
/>
</div>
<div class="row">
<profile-selector-summary-cell
:label="s__('DastProfiles|Username')"
:value="selectedSiteProfile.auth.username"
/>
</div>
<div class="row">
<profile-selector-summary-cell
:label="s__('DastProfiles|Username form field')"
:value="selectedSiteProfile.auth.usernameField"
/>
<profile-selector-summary-cell
:label="s__('DastProfiles|Password form field')"
:value="selectedSiteProfile.auth.passwordField"
/>
</div>
</template>
<div class="row">
<profile-selector-summary-cell
:label="s__('DastProfiles|Excluded URLs')"
:value="selectedSiteProfile.excludedUrls"
/>
<profile-selector-summary-cell
:label="s__('DastProfiles|Request headers')"
:value="selectedSiteProfile.requestHeaders"
/>
</div>
</template>
</template> </template>
</site-profile-selector> </site-profile-selector>
......
...@@ -17,8 +17,8 @@ export default { ...@@ -17,8 +17,8 @@ export default {
<template> <template>
<div class="col-md-6"> <div class="col-md-6">
<div class="row gl-my-2"> <div class="row gl-my-2">
<div class="col-md-3">{{ label }}:</div> <div class="col-md-4">{{ label }}:</div>
<div class="col-md-9"> <div class="col-md-8">
<strong>{{ value }}</strong> <strong>{{ value }}</strong>
</div> </div>
</div> </div>
......
import dastScannerProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_scanner_profiles.query.graphql'; import dastScannerProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_scanner_profiles.query.graphql';
import dastSiteProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql'; import dastSiteProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql';
import dastSiteProfilesExtendedQuery from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles_extended.query.graphql';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
export const ERROR_RUN_SCAN = 'ERROR_RUN_SCAN'; export const ERROR_RUN_SCAN = 'ERROR_RUN_SCAN';
...@@ -27,3 +28,8 @@ export const SITE_PROFILES_QUERY = { ...@@ -27,3 +28,8 @@ export const SITE_PROFILES_QUERY = {
fetchQuery: dastSiteProfilesQuery, fetchQuery: dastSiteProfilesQuery,
fetchError: ERROR_FETCH_SITE_PROFILES, fetchError: ERROR_FETCH_SITE_PROFILES,
}; };
export const SITE_PROFILES_EXTENDED_QUERY = {
...SITE_PROFILES_QUERY,
fetchQuery: dastSiteProfilesExtendedQuery,
};
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
query DastSiteProfiles($fullPath: ID!, $after: String, $before: String, $first: Int, $last: Int) {
project(fullPath: $fullPath) {
siteProfiles: dastSiteProfiles(after: $after, before: $before, first: $first, last: $last)
@connection(key: "dastSiteProfiles") {
pageInfo {
...PageInfo
}
edges {
cursor
node {
id
profileName
normalizedTargetUrl
targetUrl
editPath
validationStatus
auth {
enabled
url
usernameField
passwordField
username
}
excludedUrls
requestHeaders
}
}
}
}
}
...@@ -5,6 +5,7 @@ module Projects ...@@ -5,6 +5,7 @@ module Projects
before_action do before_action do
authorize_read_on_demand_scans! authorize_read_on_demand_scans!
push_frontend_feature_flag(:security_on_demand_scans_site_validation, @project) push_frontend_feature_flag(:security_on_demand_scans_site_validation, @project)
push_frontend_feature_flag(:security_dast_site_profiles_additional_fields, @project, default_enabled: :yaml)
end end
feature_category :dynamic_application_security_testing feature_category :dynamic_application_security_testing
......
...@@ -339,4 +339,39 @@ describe('OnDemandScansForm', () => { ...@@ -339,4 +339,39 @@ describe('OnDemandScansForm', () => {
expect(subject.find(selector).attributes('value')).toBe(profile.id); expect(subject.find(selector).attributes('value')).toBe(profile.id);
}); });
}); });
describe('site profile summary', () => {
const [authEnabledProfile] = siteProfiles;
const selectSiteProfile = profile => {
subject.find(SiteProfileSelector).vm.$emit('input', profile.id);
return subject.vm.$nextTick();
};
beforeEach(() => {
mountSubject({
provide: {
glFeatures: {
securityDastSiteProfilesAdditionalFields: true,
},
},
data: {
siteProfiles,
},
});
});
it('renders all fields correctly', async () => {
await selectSiteProfile(authEnabledProfile);
const summary = subject.find(SiteProfileSelector).text();
expect(summary).toMatch(authEnabledProfile.targetUrl);
expect(summary).toMatch(authEnabledProfile.excludedUrls);
expect(summary).toMatch(authEnabledProfile.requestHeaders);
expect(summary).toMatch(authEnabledProfile.auth.url);
expect(summary).toMatch(authEnabledProfile.auth.username);
expect(summary).toMatch(authEnabledProfile.auth.usernameField);
expect(summary).toMatch(authEnabledProfile.auth.passwordField);
});
});
}); });
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`OnDemandScansProfileSummaryCell renders properly 1`] = ` exports[`OnDemandScansProfileSummaryCell renders properly 1`] = `
"<div class=\\"col-md-6\\"> <div
<div class=\\"row gl-my-2\\"> class="col-md-6"
<div class=\\"col-md-3\\">Row Label:</div> >
<div class=\\"col-md-9\\"><strong>Row Value</strong></div> <div
class="row gl-my-2"
>
<div
class="col-md-4"
>
Row Label:
</div>
<div
class="col-md-8"
>
<strong>
Row Value
</strong>
</div>
</div> </div>
</div>" </div>
`; `;
...@@ -32,7 +32,10 @@ describe('OnDemandScansSiteProfileSelector', () => { ...@@ -32,7 +32,10 @@ describe('OnDemandScansSiteProfileSelector', () => {
provide: { provide: {
siteProfilesLibraryPath: TEST_LIBRARY_PATH, siteProfilesLibraryPath: TEST_LIBRARY_PATH,
newSiteProfilePath: TEST_NEW_PATH, newSiteProfilePath: TEST_NEW_PATH,
glFeatures: { securityOnDemandScansSiteValidation: true }, glFeatures: {
securityOnDemandScansSiteValidation: true,
securityDastSiteProfilesAdditionalFields: true,
},
}, },
slots: { slots: {
summary: `<div>${profiles[0].profileName}'s summary</div>`, summary: `<div>${profiles[0].profileName}'s summary</div>`,
...@@ -93,12 +96,15 @@ describe('OnDemandScansSiteProfileSelector', () => { ...@@ -93,12 +96,15 @@ describe('OnDemandScansSiteProfileSelector', () => {
expect(sel.attributes()).toMatchObject(TEST_ATTRS); expect(sel.attributes()).toMatchObject(TEST_ATTRS);
}); });
describe('feature flag disabled', () => { describe('feature flags disabled', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ createComponent({
propsData: { profiles }, propsData: { profiles },
provide: { provide: {
glFeatures: { securityOnDemandScansSiteValidation: false }, glFeatures: {
securityOnDemandScansSiteValidation: false,
securityDastSiteProfilesAdditionalFields: false,
},
}, },
}); });
}); });
......
...@@ -20,6 +20,6 @@ describe('OnDemandScansProfileSummaryCell', () => { ...@@ -20,6 +20,6 @@ describe('OnDemandScansProfileSummaryCell', () => {
it('renders properly', () => { it('renders properly', () => {
createFullComponent(); createFullComponent();
expect(wrapper.html()).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
}); });
...@@ -29,6 +29,15 @@ export const siteProfiles = [ ...@@ -29,6 +29,15 @@ export const siteProfiles = [
normalizedTargetUrl: 'https://foo.com:443', normalizedTargetUrl: 'https://foo.com:443',
editPath: '/site_profiles/edit/1', editPath: '/site_profiles/edit/1',
validationStatus: 'PENDING_VALIDATION', validationStatus: 'PENDING_VALIDATION',
auth: {
enabled: true,
url: 'https://foo.com/login',
usernameField: 'username',
passwordField: 'password',
username: 'admin',
},
excludedUrls: 'https://foo.com/logout,https://foo.com/send_mail',
requestHeaders: 'log-identifier: dast-active-scan',
}, },
{ {
id: 'gid://gitlab/DastSiteProfile/2', id: 'gid://gitlab/DastSiteProfile/2',
...@@ -37,5 +46,10 @@ export const siteProfiles = [ ...@@ -37,5 +46,10 @@ export const siteProfiles = [
normalizedTargetUrl: 'https://bar.com:443', normalizedTargetUrl: 'https://bar.com:443',
editPath: '/site_profiles/edit/2', editPath: '/site_profiles/edit/2',
validationStatus: 'PASSED_VALIDATION', validationStatus: 'PASSED_VALIDATION',
auth: {
enabled: false,
},
excludedUrls: 'https://bar.com/logout',
requestHeaders: 'auth: gitlab-dast',
}, },
]; ];
...@@ -8683,6 +8683,9 @@ msgstr "" ...@@ -8683,6 +8683,9 @@ msgstr ""
msgid "DastProfiles|Error Details" msgid "DastProfiles|Error Details"
msgstr "" msgstr ""
msgid "DastProfiles|Excluded URLs"
msgstr ""
msgid "DastProfiles|Hide debug messages" msgid "DastProfiles|Hide debug messages"
msgstr "" msgstr ""
...@@ -8731,6 +8734,9 @@ msgstr "" ...@@ -8731,6 +8734,9 @@ msgstr ""
msgid "DastProfiles|Profile name" msgid "DastProfiles|Profile name"
msgstr "" msgstr ""
msgid "DastProfiles|Request headers"
msgstr ""
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site." msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
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