Skip to content
代码片段 群组 项目
提交 437256c4 编辑于 作者: Igor Frenkel's avatar Igor Frenkel 提交者: charlie ablett
浏览文件

Add graphql mutation for continuous vuln scans

Add mutation to enable or disable Continuous Vulnerability
Scans for a project.

Changelog: added
EE: true
上级 d9691b56
No related branches found
No related tags found
无相关合并请求
显示
196 个添加5 个删除
......@@ -5616,6 +5616,28 @@ Input type: `ProjectSetComplianceFrameworkInput`
| <a id="mutationprojectsetcomplianceframeworkerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationprojectsetcomplianceframeworkproject"></a>`project` | [`Project`](#project) | Project after mutation. |
 
### `Mutation.projectSetContinuousVulnerabilityScanning`
Enable/disable Continuous Vulnerability Scanning for the given project.
Input type: `ProjectSetContinuousVulnerabilityScanningInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationprojectsetcontinuousvulnerabilityscanningclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationprojectsetcontinuousvulnerabilityscanningenable"></a>`enable` | [`Boolean!`](#boolean) | Desired status for Continuous Vulnerability Scanning feature. |
| <a id="mutationprojectsetcontinuousvulnerabilityscanningprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationprojectsetcontinuousvulnerabilityscanningclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationprojectsetcontinuousvulnerabilityscanningcontinuousvulnerabilityscanningenabled"></a>`continuousVulnerabilityScanningEnabled` | [`Boolean!`](#boolean) | Whether feature is enabled. |
| <a id="mutationprojectsetcontinuousvulnerabilityscanningerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.projectSetLocked`
 
Input type: `ProjectSetLockedInput`
mutation ProjectSetContinuousVulnerabilityScanning(
$input: ProjectSetContinuousVulnerabilityScanningInput!
) {
projectSetContinuousVulnerabilityScanning(input: $input) {
continuousVulnerabilityScanningEnabled
errors
}
}
......@@ -128,6 +128,7 @@ module MutationType
mount_mutation ::Mutations::AuditEvents::Streaming::InstanceHeaders::Destroy
mount_mutation ::Mutations::AuditEvents::Streaming::InstanceEventTypeFilters::Create
mount_mutation ::Mutations::AuditEvents::Streaming::InstanceEventTypeFilters::Destroy
mount_mutation ::Mutations::Security::CiConfiguration::ProjectSetContinuousVulnerabilityScanning
prepend(Types::DeprecatedMutations)
end
......
# frozen_string_literal: true
module Mutations
module Security
module CiConfiguration
class ProjectSetContinuousVulnerabilityScanning < BaseMutation
graphql_name 'ProjectSetContinuousVulnerabilityScanning'
include FindsProject
description <<~DESC
Enable/disable Continuous Vulnerability Scanning for the given project.
DESC
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Full path of the project.'
argument :enable, GraphQL::Types::Boolean,
required: true,
description: 'Desired status for Continuous Vulnerability Scanning feature.'
field :continuous_vulnerability_scanning_enabled, GraphQL::Types::Boolean,
null: false,
description: 'Whether feature is enabled.'
authorize :enable_continuous_vulnerability_scans
def resolve(project_path:, enable:)
project = authorized_find!(project_path)
enabled = ::Security::Configuration::ProjectSetContinuousVulnerabilityScanningService
.execute(project: project, enable: enable)
{ continuous_vulnerability_scanning_enabled: enabled, errors: [] }
end
end
end
end
end
......@@ -23,9 +23,7 @@ def auto_fix_enabled_types
end
end
# TODO: the caller for this method is a graphql mutation implemented as part of
# https://gitlab.com/gitlab-org/gitlab/-/issues/424374
def set_continuous_vulnerability_scans!(enabled:)
update!(continuous_vulnerability_scans_enabled: enabled)
enabled if update!(continuous_vulnerability_scans_enabled: enabled)
end
end
......@@ -570,6 +570,10 @@ module ProjectPolicy
.default_project_deletion_protection
end
condition(:continuous_vulnerability_scanning_available) do
::Feature.enabled?(:dependency_scanning_on_advisory_ingestion)
end
rule { needs_new_sso_session }.policy do
prevent :read_project
end
......@@ -700,6 +704,10 @@ module ProjectPolicy
rule do
(maintainer | owner | admin) & pages_multiple_versions_available
end.enable :pages_multiple_versions
rule { continuous_vulnerability_scanning_available & can?(:developer_access) }.policy do
enable :enable_continuous_vulnerability_scans
end
end
override :lookup_access_level!
......
# frozen_string_literal: true
module Security
module Configuration
class ProjectSetContinuousVulnerabilityScanningService
def self.execute(project:, enable:)
project.security_setting.set_continuous_vulnerability_scans!(enabled: enable)
end
end
end
end
......@@ -67,8 +67,8 @@
with_them do
let(:setting) { create(:project_security_setting, continuous_vulnerability_scans_enabled: value_before) }
specify do
setting.set_continuous_vulnerability_scans!(enabled: enabled)
it 'updates the attribute and returns the new value' do
expect(setting.set_continuous_vulnerability_scans!(enabled: enabled)).to eq(value_after)
expect(setting.reload.continuous_vulnerability_scans_enabled).to eq(value_after)
end
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Setting Project Continuous Vulnerability Scanning', feature_category: :software_composition_analysis do
using RSpec::Parameterized::TableSyntax
include GraphqlHelpers
let(:current_user) { create(:user) }
let(:security_setting) { create(:project_security_setting, continuous_vulnerability_scans_enabled: value_before) }
let(:project) { security_setting.project }
let(:mutation_name) { :project_set_continuous_vulnerability_scanning }
let(:mutation) do
graphql_mutation(
mutation_name,
project_path: project.full_path,
enable: enable
)
end
let(:value_before) { false }
let(:enable) { true }
context 'when the user does not have permission' do
it_behaves_like 'a mutation that returns a top-level access error'
it 'does not enable cvs' do
expect { post_graphql_mutation(mutation, current_user: current_user) }
.not_to change { security_setting.reload.continuous_vulnerability_scans_enabled }
end
end
context 'when the user has permission' do
before do
project.add_developer(current_user)
end
context 'and feature is enabled' do
before do
stub_feature_flags(dependency_scanning_on_advisory_ingestion: true)
end
where(:value_before, :enable, :value_after) do
true | false | false
true | true | true
false | true | true
false | false | false
end
with_them do
it 'updates the project setting and returns the new value' do
post_graphql_mutation(mutation, current_user: current_user)
response = graphql_mutation_response(mutation_name)
expect(response).to include({ 'continuousVulnerabilityScanningEnabled' => value_after, 'errors' => [] })
expect(security_setting.reload.continuous_vulnerability_scans_enabled).to eq(value_after)
end
end
end
context 'and feature is disabled' do
before do
stub_feature_flags(dependency_scanning_on_advisory_ingestion: false)
end
it_behaves_like 'a mutation that returns a top-level access error'
it 'does not enable cvs' do
expect { post_graphql_mutation(mutation, current_user: current_user) }
.not_to change { security_setting.reload.continuous_vulnerability_scans_enabled }
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Security::Configuration::ProjectSetContinuousVulnerabilityScanningService, feature_category: :software_composition_analysis do
describe '#execute' do
let_it_be(:security_setting) { create(:project_security_setting, continuous_vulnerability_scans_enabled: false) }
let_it_be(:project) { security_setting.project }
it 'returns attribute value' do
expect(described_class.execute(project: project, enable: true)).to eq(true)
expect(described_class.execute(project: project, enable: false)).to eq(false)
end
it 'changes the attribute' do
expect { described_class.execute(project: project, enable: true) }
.to change { security_setting.reload.continuous_vulnerability_scans_enabled }
.from(false).to(true)
expect { described_class.execute(project: project, enable: true) }
.not_to change { security_setting.reload.continuous_vulnerability_scans_enabled }
expect { described_class.execute(project: project, enable: false) }
.to change { security_setting.reload.continuous_vulnerability_scans_enabled }
.from(true).to(false)
expect { described_class.execute(project: project, enable: false) }
.not_to change { security_setting.reload.continuous_vulnerability_scans_enabled }
end
end
end
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册