Commit 7a189e7b authored by Craig Smith's avatar Craig Smith

Add unimplemented CreateDastScannerProfile mutation

The commit adds an unimplemented graphql mutation
that in later commits will allow users to create
scanner profiles for on-demand scans
parent 8d281ea0
......@@ -2159,6 +2159,56 @@ enum DastScanTypeEnum {
PASSIVE
}
"""
Autogenerated input type of DastScannerProfileCreate
"""
input DastScannerProfileCreateInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
The project the scanner profile belongs to.
"""
fullPath: ID!
"""
The name of the scanner profile.
"""
profileName: String!
"""
The maximum number of seconds allowed for the spider to traverse the site.
"""
spiderTimeout: Int
"""
The maximum number of seconds allowed for the site under test to respond to a request.
"""
targetTimeout: Int
}
"""
Autogenerated return type of DastScannerProfileCreate
"""
type DastScannerProfileCreatePayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Errors encountered during execution of the mutation.
"""
errors: [String!]!
"""
ID of the scanner profile.
"""
id: ID
}
"""
Autogenerated input type of DastSiteProfileCreate
"""
......@@ -8225,6 +8275,7 @@ type Mutation {
createNote(input: CreateNoteInput!): CreateNotePayload
createRequirement(input: CreateRequirementInput!): CreateRequirementPayload
createSnippet(input: CreateSnippetInput!): CreateSnippetPayload
dastScannerProfileCreate(input: DastScannerProfileCreateInput!): DastScannerProfileCreatePayload
dastSiteProfileCreate(input: DastSiteProfileCreateInput!): DastSiteProfileCreatePayload
deleteAnnotation(input: DeleteAnnotationInput!): DeleteAnnotationPayload
designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload
......
......@@ -5785,6 +5785,142 @@
],
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "DastScannerProfileCreateInput",
"description": "Autogenerated input type of DastScannerProfileCreate",
"fields": null,
"inputFields": [
{
"name": "fullPath",
"description": "The project the scanner profile belongs to.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "profileName",
"description": "The name of the scanner profile.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "spiderTimeout",
"description": "The maximum number of seconds allowed for the spider to traverse the site.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "targetTimeout",
"description": "The maximum number of seconds allowed for the site under test to respond to a request.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DastScannerProfileCreatePayload",
"description": "Autogenerated return type of DastScannerProfileCreate",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Errors encountered during execution of the mutation.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": "ID of the scanner profile.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "DastSiteProfileCreateInput",
......@@ -23576,6 +23712,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "dastScannerProfileCreate",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "DastScannerProfileCreateInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "DastScannerProfileCreatePayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "dastSiteProfileCreate",
"description": null,
......@@ -382,6 +382,16 @@ Autogenerated return type of CreateSnippet
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `snippet` | Snippet | The snippet after mutation |
## DastScannerProfileCreatePayload
Autogenerated return type of DastScannerProfileCreate
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `id` | ID | ID of the scanner profile. |
## DastSiteProfileCreatePayload
Autogenerated return type of DastSiteProfileCreate
......
......@@ -23,6 +23,7 @@ module EE
mount_mutation ::Mutations::InstanceSecurityDashboard::RemoveProject
mount_mutation ::Mutations::Pipelines::RunDastScan
mount_mutation ::Mutations::DastSiteProfiles::Create
mount_mutation ::Mutations::DastScannerProfiles::Create
end
end
end
......
# frozen_string_literal: true
module Mutations
module DastScannerProfiles
class Create < BaseMutation
include ResolvesProject
graphql_name 'DastScannerProfileCreate'
field :id, GraphQL::ID_TYPE,
null: true,
description: 'ID of the scanner profile.'
argument :full_path, GraphQL::ID_TYPE,
required: true,
description: 'The project the scanner profile belongs to.'
argument :profile_name, GraphQL::STRING_TYPE,
required: true,
description: 'The name of the scanner profile.'
argument :spider_timeout, GraphQL::INT_TYPE,
required: false,
description: 'The maximum number of seconds allowed for the spider to traverse the site.'
argument :target_timeout, GraphQL::INT_TYPE,
required: false,
description: 'The maximum number of seconds allowed for the site under test to respond to a request.'
authorize :run_ondemand_dast_scan
def resolve(full_path:, profile_name:, spider_timeout: nil, target_timeout: nil)
project = authorized_find!(full_path: full_path)
raise_resource_not_available_error! unless Feature.enabled?(:security_on_demand_scans_feature_flag, project)
response = ServiceResponse.error(message: 'Not implemented')
{ errors: response.errors }
end
private
def find_object(full_path:)
resolve_project(full_path: full_path)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::DastScannerProfiles::Create do
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
let(:user) { create(:user) }
let(:full_path) { project.full_path }
let(:profile_name) { SecureRandom.hex }
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
describe '#resolve' do
subject do
mutation.resolve(
full_path: full_path,
profile_name: profile_name
)
end
context 'when the project does not exist' do
let(:full_path) { SecureRandom.hex }
it 'raises an exception' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when the user is not associated with the project' do
it 'raises an exception' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when the user can run a dast scan' do
before do
group.add_owner(user)
end
it 'stubs out the response' do
expect(subject[:errors]).to eq(['Not implemented'])
end
context 'when security_on_demand_scans_feature_flag is disabled' do
before do
stub_feature_flags(security_on_demand_scans_feature_flag: false)
end
it 'raises an exception' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Creating a DAST Scanner Profile' do
include GraphqlHelpers
let(:project) { create(:project, :repository, creator: current_user) }
let(:current_user) { create(:user) }
let(:full_path) { project.full_path }
let(:profile_name) { FFaker::Company.catch_phrase }
let(:mutation) do
graphql_mutation(
:dast_scanner_profile_create,
full_path: full_path,
profile_name: profile_name
)
end
def mutation_response
graphql_mutation_response(:dast_scanner_profile_create)
end
context 'when a user does not have access to the project' do
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The resource that you are attempting to access does not ' \
"exist or you don't have permission to perform this action"]
end
context 'when a user does not have access to run a dast scan on the project' do
before do
project.add_guest(current_user)
end
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The resource that you are attempting to access does not ' \
"exist or you don't have permission to perform this action"]
end
context 'when a user has access to run a DAST scan on the project' do
before do
project.add_developer(current_user)
end
it_behaves_like 'a mutation that returns errors in the response', errors: ['Not implemented']
context 'when on demand scan feature is disabled' do
before do
stub_feature_flags(security_on_demand_scans_feature_flag: false)
end
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The resource that you are attempting to access does not ' \
"exist or you don't have permission to perform this action"]
end
end
end
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