Commit 4882066f authored by Luke Duncalfe's avatar Luke Duncalfe

Merge branch 'mc_rocha-add-scan-method-to-graphl-327070' into 'master'

Add graphql support for dast_site_profile scan method

See merge request gitlab-org/gitlab!79896
parents af408f37 40fa9ce8
......@@ -1858,6 +1858,7 @@ Input type: `DastSiteProfileCreateInput`
| <a id="mutationdastsiteprofilecreatefullpath"></a>`fullPath` | [`ID!`](#id) | Project the site profile belongs to. |
| <a id="mutationdastsiteprofilecreateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
| <a id="mutationdastsiteprofilecreaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
| <a id="mutationdastsiteprofilecreatescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method by the scanner. Is not saved or updated if `dast_api_scanner` feature flag is disabled. |
| <a id="mutationdastsiteprofilecreatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
| <a id="mutationdastsiteprofilecreatetargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
......@@ -1903,6 +1904,7 @@ Input type: `DastSiteProfileUpdateInput`
| <a id="mutationdastsiteprofileupdateid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be updated. |
| <a id="mutationdastsiteprofileupdateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
| <a id="mutationdastsiteprofileupdatescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method by the scanner. Is not saved or updated if `dast_api_scanner` feature flag is disabled. |
| <a id="mutationdastsiteprofileupdatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
| <a id="mutationdastsiteprofileupdatetargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
......@@ -9861,6 +9863,7 @@ Represents a DAST Site Profile.
| <a id="dastsiteprofileprofilename"></a>`profileName` | [`String`](#string) | Name of the site profile. |
| <a id="dastsiteprofilereferencedinsecuritypolicies"></a>`referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
| <a id="dastsiteprofilerequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
| <a id="dastsiteprofilescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method used by the scanner. Always returns `null` if `dast_api_scanner` feature flag is disabled. |
| <a id="dastsiteprofiletargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
| <a id="dastsiteprofiletargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
| <a id="dastsiteprofileuserpermissions"></a>`userPermissions` | [`DastSiteProfilePermissions!`](#dastsiteprofilepermissions) | Permissions for the current user on the resource. |
......@@ -17241,6 +17244,17 @@ Unit for the duration of Dast Profile Cadence.
| <a id="dastprofilecadenceunitweek"></a>`WEEK` | DAST Profile Cadence duration in weeks. |
| <a id="dastprofilecadenceunityear"></a>`YEAR` | DAST Profile Cadence duration in years. |
### `DastScanMethodType`
Scan method to be used by the scanner.
| Value | Description |
| ----- | ----------- |
| <a id="dastscanmethodtypehar"></a>`HAR` | HAR scan method. |
| <a id="dastscanmethodtypeopenapi"></a>`OPENAPI` | OpenAPI scan method. |
| <a id="dastscanmethodtypepostman_collection"></a>`POSTMAN_COLLECTION` | Postman scan method. |
| <a id="dastscanmethodtypewebsite"></a>`WEBSITE` | Website scan method. |
### `DastScanTypeEnum`
| Value | Description |
......@@ -22,6 +22,11 @@ module Mutations
required: false,
description: 'Type of target to be scanned.'
argument :scan_method, Types::Dast::ScanMethodTypeEnum,
required: false,
description: 'Scan method by the scanner. Is not saved or updated ' \
'if `dast_api_scanner` feature flag is disabled.'
argument :request_headers, GraphQL::Types::String,
required: false,
description: 'Comma-separated list of request header names and values to be ' \
......
......@@ -42,6 +42,10 @@ module Mutations
auth_password: auth_params[:password]
}.compact
if Feature.enabled?(:dast_api_scanner, project, default_enabled: :yaml)
dast_site_profile_params[:scan_method] = params[:scan_method]
end
result = ::AppSec::Dast::SiteProfiles::CreateService.new(project, current_user).execute(**dast_site_profile_params)
{ id: result.payload.try(:to_global_id), errors: result.errors }
......
......@@ -49,6 +49,10 @@ module Mutations
auth_password: auth_params[:password]
}.compact
if Feature.enabled?(:dast_api_scanner, dast_site_profile.project, default_enabled: :yaml)
dast_site_profile_params[:scan_method] = params[:scan_method]
end
result = ::AppSec::Dast::SiteProfiles::UpdateService.new(dast_site_profile.project, current_user).execute(**dast_site_profile_params)
{ id: result.payload.try(:to_global_id), errors: result.errors }
......
# frozen_string_literal: true
module Types
module Dast
class ScanMethodTypeEnum < BaseEnum
graphql_name 'DastScanMethodType'
description 'Scan method to be used by the scanner.'
value 'WEBSITE', description: 'Website scan method.', value: 'site'
value 'OPENAPI', description: 'OpenAPI scan method.', value: 'openapi'
value 'HAR', description: 'HAR scan method.', value: 'har'
value 'POSTMAN_COLLECTION', description: 'Postman scan method.', value: 'postman'
end
end
end
......@@ -50,6 +50,10 @@ module Types
calls_gitaly: true,
description: 'List of security policy names that are referencing given project.'
field :scan_method, Types::Dast::ScanMethodTypeEnum, null: true,
description: 'Scan method used by the scanner. Always returns `null` ' \
'if `dast_api_scanner` feature flag is disabled.'
def target_url
object.dast_site.url
end
......@@ -72,5 +76,11 @@ module Types
object
)
end
def scan_method
return unless Feature.enabled?(:dast_api_scanner, object.project, default_enabled: :yaml)
object.scan_method
end
end
end
......@@ -14,6 +14,7 @@ RSpec.describe Mutations::DastSiteProfiles::Create do
let_it_be(:request_headers) { 'Authorization: token' }
let_it_be(:target_type) { 'api' }
let_it_be(:scan_method) { 'openapi' }
let(:auth) do
{
......@@ -45,7 +46,8 @@ RSpec.describe Mutations::DastSiteProfiles::Create do
target_type: target_type,
excluded_urls: excluded_urls,
request_headers: request_headers,
auth: auth
auth: auth,
scan_method: scan_method
)
end
......@@ -63,6 +65,28 @@ RSpec.describe Mutations::DastSiteProfiles::Create do
project.add_developer(user)
end
context 'when the feature flag dast_api_scanner is disabled' do
before do
stub_feature_flags(dast_api_scanner: false)
end
context 'when the target_type is api' do
it 'creates a dast_site_profile with the default value for the scan_method' do
dast_site_profile = subject[:id].find
expect(dast_site_profile.scan_method).to eq('openapi')
end
end
context 'when the target_type is website' do
let_it_be(:target_type) { 'website' }
it 'creates a dast_site_profile with the default value for the scan_method' do
dast_site_profile = subject[:id].find
expect(dast_site_profile.scan_method).to eq('site')
end
end
end
it 'creates a dast_site_profile and dast_site_profile_secret_variables', :aggregate_failures do
dast_site_profile = subject[:id].find
......@@ -75,7 +99,8 @@ RSpec.describe Mutations::DastSiteProfiles::Create do
auth_password_field: auth[:password_field],
auth_username: auth[:username],
dast_site: have_attributes(url: target_url),
target_type: target_type
target_type: target_type,
scan_method: scan_method
)
password_variable = dast_site_profile.secret_variables.find_by!(key: Dast::SiteProfileSecretVariable::PASSWORD)
......@@ -99,6 +124,7 @@ RSpec.describe Mutations::DastSiteProfiles::Create do
target_type: target_type,
excluded_urls: excluded_urls,
request_headers: request_headers,
scan_method: scan_method,
auth_enabled: auth[:enabled],
auth_url: auth[:url],
auth_username_field: auth[:username_field],
......
......@@ -13,6 +13,7 @@ RSpec.describe Mutations::DastSiteProfiles::Update do
let(:new_excluded_urls) { ["#{new_target_url}/signout"] }
let(:new_request_headers) { "Authorization: Bearer #{SecureRandom.hex}" }
let(:new_target_type) { 'api' }
let(:new_scan_method) { 'postman' }
let(:new_auth) do
{
......@@ -42,6 +43,7 @@ RSpec.describe Mutations::DastSiteProfiles::Update do
target_type: new_target_type,
excluded_urls: new_excluded_urls,
request_headers: new_request_headers,
scan_method: new_scan_method,
auth: new_auth
)
end
......@@ -63,6 +65,7 @@ RSpec.describe Mutations::DastSiteProfiles::Update do
target_type: new_target_type,
excluded_urls: new_excluded_urls,
request_headers: new_request_headers,
scan_method: new_scan_method,
auth_enabled: new_auth[:enabled],
auth_url: new_auth[:url],
auth_username_field: new_auth[:username_field],
......@@ -88,6 +91,7 @@ RSpec.describe Mutations::DastSiteProfiles::Update do
auth_username_field: new_auth[:username_field],
auth_password_field: new_auth[:password_field],
auth_username: new_auth[:username],
scan_method: new_scan_method,
dast_site: have_attributes(url: new_target_url)
)
......@@ -143,6 +147,18 @@ RSpec.describe Mutations::DastSiteProfiles::Update do
expect(subject).to include(errors: ['Oops'])
end
end
context 'when the feature flag dast_api_scanner is disabled' do
before do
stub_feature_flags(dast_api_scanner: false)
end
it 'does not update the scan_method and uses the default value according to the target_type' do
dast_site_profile = subject[:id].find
expect(dast_site_profile.scan_method).to eq('openapi')
end
end
end
end
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['DastScanMethodType'] do
it 'exposes all alert field names' do
expect(described_class.values.keys).to match_array(%w(WEBSITE OPENAPI HAR POSTMAN_COLLECTION))
end
end
......@@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['DastSiteProfile'] do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user, developer_projects: [project]) }
let_it_be(:object, reload: true) { create(:dast_site_profile, project: project) }
let_it_be(:fields) { %i[id profileName targetUrl targetType editPath excludedUrls requestHeaders validationStatus userPermissions normalizedTargetUrl auth referencedInSecurityPolicies] }
let_it_be(:fields) { %i[id profileName targetUrl targetType editPath excludedUrls requestHeaders validationStatus userPermissions normalizedTargetUrl auth referencedInSecurityPolicies scanMethod] }
before do
stub_licensed_features(security_on_demand_scans: true)
......@@ -105,6 +105,22 @@ RSpec.describe GitlabSchema.types['DastSiteProfile'] do
end
end
describe 'scan_method field' do
context 'when the feature flag is disabled' do
it 'resolves nil' do
stub_feature_flags(dast_api_scanner: false)
expect(resolve_field(:scan_method, object, current_user: user)).to eq(nil)
end
end
context 'when the feature flag is enabled' do
it 'is the scan method' do
expect(resolve_field(:scan_method, object, current_user: user)).to eq('site')
end
end
end
describe 'dast_site_profiles' do
subject(:response) do
GitlabSchema.execute(
......
......@@ -20,6 +20,7 @@ RSpec.describe 'Creating a DAST Site Profile' do
profile_name: profile_name,
target_url: target_url,
target_type: 'API',
scan_method: 'OPENAPI',
excluded_urls: ["#{target_url}/logout"],
request_headers: 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0',
auth: {
......
......@@ -22,6 +22,7 @@ RSpec.describe 'Creating a DAST Site Profile' do
profile_name: new_profile_name,
target_url: new_target_url,
target_type: 'API',
scan_method: 'OPENAPI',
excluded_urls: ["#{new_target_url}/signout"],
request_headers: 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0',
auth: {
......
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