Commit 66a61e1c authored by Philip Cunningham's avatar Philip Cunningham Committed by Stan Hu

Add explicit authorization schema for DAST secrets

parent 7a406c41
...@@ -26,16 +26,14 @@ module Dast ...@@ -26,16 +26,14 @@ module Dast
where(project_id: project_id) where(project_id: project_id)
end end
delegate :secret_ci_variables, to: :dast_site_profile
def branch def branch
return unless project.repository.exists? return unless project.repository.exists?
Dast::Branch.new(self) Dast::Branch.new(self)
end end
def secret_ci_variables
::Gitlab::Ci::Variables::Collection.new(secret_variables)
end
private private
def project_ids_match def project_ids_match
......
...@@ -52,8 +52,12 @@ class DastSiteProfile < ApplicationRecord ...@@ -52,8 +52,12 @@ class DastSiteProfile < ApplicationRecord
collection.compact collection.compact
end end
def secret_ci_variables def secret_ci_variables(user)
::Gitlab::Ci::Variables::Collection.new(secret_variables) collection = ::Gitlab::Ci::Variables::Collection.new
return collection unless Ability.allowed?(user, :read_on_demand_scans, self)
collection.concat(secret_variables)
end end
def status def status
......
...@@ -52,7 +52,7 @@ module EE ...@@ -52,7 +52,7 @@ module EE
# Subject to change. Please see gitlab-org/gitlab#330950 for more info. # Subject to change. Please see gitlab-org/gitlab#330950 for more info.
profile = pipeline.dast_profile || pipeline.dast_site_profile profile = pipeline.dast_profile || pipeline.dast_site_profile
collection.concat(profile.secret_ci_variables) collection.concat(profile.secret_ci_variables(pipeline.user))
end end
end end
end end
......
...@@ -151,14 +151,19 @@ RSpec.describe Ci::Build do ...@@ -151,14 +151,19 @@ RSpec.describe Ci::Build do
context 'when there is a dast_profile associated with the pipeline' do context 'when there is a dast_profile associated with the pipeline' do
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, developer_projects: [project]) }
let_it_be(:dast_profile) { create(:dast_profile, project: project) } let_it_be(:dast_profile) { create(:dast_profile, project: project) }
let_it_be(:dast_site_profile_secret_variable) { create(:dast_site_profile_secret_variable, key: 'DAST_PASSWORD_BASE64', dast_site_profile: dast_profile.dast_site_profile) } let_it_be(:dast_site_profile_secret_variable) { create(:dast_site_profile_secret_variable, key: 'DAST_PASSWORD_BASE64', dast_site_profile: dast_profile.dast_site_profile) }
let(:pipeline) { create(:ci_pipeline, pipeline_params.merge!(project: project, dast_profile: dast_profile) ) } let(:pipeline) { create(:ci_pipeline, pipeline_params.merge!(project: project, dast_profile: dast_profile, user: user) ) }
let(:key) { dast_site_profile_secret_variable.key } let(:key) { dast_site_profile_secret_variable.key }
let(:value) { dast_site_profile_secret_variable.value } let(:value) { dast_site_profile_secret_variable.value }
before do
stub_licensed_features(security_on_demand_scans: true)
end
shared_examples 'a pipeline with no dast on-demand variables' do shared_examples 'a pipeline with no dast on-demand variables' do
it 'does not include variables associated with the profile' do it 'does not include variables associated with the profile' do
keys = subject.to_runner_variables.map { |var| var[:key] } keys = subject.to_runner_variables.map { |var| var[:key] }
...@@ -181,6 +186,24 @@ RSpec.describe Ci::Build do ...@@ -181,6 +186,24 @@ RSpec.describe Ci::Build do
it 'includes variables associated with the profile' do it 'includes variables associated with the profile' do
expect(subject.to_runner_variables).to include(key: key, value: value, public: false, masked: true) expect(subject.to_runner_variables).to include(key: key, value: value, public: false, masked: true)
end end
context 'when user cannot read secrets' do
before do
stub_licensed_features(security_on_demand_scans: false)
end
it 'does not include variables associated with the profile' do
expect(subject.to_runner_variables).not_to include(key: key, value: value, public: false, masked: true)
end
end
context 'when there is no user associated with the pipeline' do
let_it_be(:user) { nil }
it 'does not include variables associated with the profile' do
expect(subject.to_runner_variables).not_to include(key: key, value: value, public: false, masked: true)
end
end
end end
end end
end end
......
...@@ -123,19 +123,7 @@ RSpec.describe Dast::Profile, type: :model do ...@@ -123,19 +123,7 @@ RSpec.describe Dast::Profile, type: :model do
end end
describe '#secret_ci_variables' do describe '#secret_ci_variables' do
context 'when there are no secret_variables' do it { is_expected.to delegate_method(:secret_ci_variables).to(:dast_site_profile) }
it 'returns an empty collection' do
expect(subject.secret_ci_variables.size).to be_zero
end
end
context 'when there are secret_variables' do
it 'returns a collection containing that variable' do
variable = create(:dast_site_profile_secret_variable, dast_site_profile: subject.dast_site_profile)
expect(subject.secret_ci_variables.to_runner_variables).to include(key: variable.key, value: variable.value, public: false, masked: true)
end
end
end end
end end
end end
...@@ -249,17 +249,47 @@ RSpec.describe DastSiteProfile, type: :model do ...@@ -249,17 +249,47 @@ RSpec.describe DastSiteProfile, type: :model do
end end
describe '#secret_ci_variables' do describe '#secret_ci_variables' do
context 'when there are no secret_variables' do let_it_be(:user) { create(:user, developer_projects: [project]) }
it 'returns an empty collection' do
expect(subject.secret_ci_variables.size).to be_zero context 'when user can read secrets' do
before do
stub_licensed_features(security_on_demand_scans: true)
end
it 'works with policy' do
expect(Ability.allowed?(user, :read_on_demand_scans, subject)).to be_truthy
end
it 'checks the policy' do
expect(Ability).to receive(:allowed?).with(user, :read_on_demand_scans, subject).and_call_original
subject.secret_ci_variables(user)
end
context 'when there are no secret_variables' do
it 'returns an empty collection' do
expect(subject.secret_ci_variables(user).size).to be_zero
end
end
context 'when there are secret_variables' do
it 'returns a collection containing that variable' do
variable = create(:dast_site_profile_secret_variable, dast_site_profile: subject)
expect(subject.secret_ci_variables(user).to_runner_variables).to include(key: variable.key, value: variable.value, public: false, masked: true)
end
end end
end end
context 'when there are secret_variables' do context 'when user cannot read secrets' do
it 'returns a collection containing that variable' do before do
variable = create(:dast_site_profile_secret_variable, dast_site_profile: subject) stub_licensed_features(security_on_demand_scans: false)
end
it 'returns an empty collection' do
create(:dast_site_profile_secret_variable, dast_site_profile: subject)
expect(subject.secret_ci_variables.to_runner_variables).to include(key: variable.key, value: variable.value, public: false, masked: true) expect(subject.secret_ci_variables(user).size).to be_zero
end end
end end
end end
......
...@@ -11,9 +11,11 @@ RSpec.shared_examples 'a dast on-demand scan policy' do ...@@ -11,9 +11,11 @@ RSpec.shared_examples 'a dast on-demand scan policy' do
stub_licensed_features(security_on_demand_scans: true) stub_licensed_features(security_on_demand_scans: true)
end end
describe 'create_on_demand_dast_scan' do describe 'dast on-demand policies' do
let(:policies) { [:create_on_demand_dast_scan, :read_on_demand_scans] }
context 'when a user does not have access to the project' do context 'when a user does not have access to the project' do
it { is_expected.to be_disallowed(:create_on_demand_dast_scan) } it { is_expected.to be_disallowed(*policies) }
end end
context 'when the user is a guest' do context 'when the user is a guest' do
...@@ -21,7 +23,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do ...@@ -21,7 +23,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do
project.add_guest(user) project.add_guest(user)
end end
it { is_expected.to be_disallowed(:create_on_demand_dast_scan) } it { is_expected.to be_disallowed(*policies) }
end end
context 'when the user is a reporter' do context 'when the user is a reporter' do
...@@ -29,7 +31,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do ...@@ -29,7 +31,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do
project.add_reporter(user) project.add_reporter(user)
end end
it { is_expected.to be_disallowed(:create_on_demand_dast_scan) } it { is_expected.to be_disallowed(*policies) }
end end
context 'when the user is a developer' do context 'when the user is a developer' do
...@@ -37,7 +39,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do ...@@ -37,7 +39,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do
project.add_developer(user) project.add_developer(user)
end end
it { is_expected.to be_allowed(:create_on_demand_dast_scan) } it { is_expected.to be_allowed(*policies) }
end end
context 'when the user is a maintainer' do context 'when the user is a maintainer' do
...@@ -45,7 +47,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do ...@@ -45,7 +47,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do
project.add_maintainer(user) project.add_maintainer(user)
end end
it { is_expected.to be_allowed(:create_on_demand_dast_scan) } it { is_expected.to be_allowed(*policies) }
end end
context 'when the user is an owner' do context 'when the user is an owner' do
...@@ -53,7 +55,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do ...@@ -53,7 +55,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do
group.add_owner(user) group.add_owner(user)
end end
it { is_expected.to be_allowed(:create_on_demand_dast_scan) } it { is_expected.to be_allowed(*policies) }
end end
context 'when the user is allowed' do context 'when the user is allowed' do
...@@ -68,7 +70,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do ...@@ -68,7 +70,7 @@ RSpec.shared_examples 'a dast on-demand scan policy' do
stub_licensed_features(security_on_demand_scans: false) stub_licensed_features(security_on_demand_scans: false)
end end
it { is_expected.to be_disallowed(:create_on_demand_dast_scan) } it { is_expected.to be_disallowed(*policies) }
end end
end 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