Commit d172a2b7 authored by Philip Cunningham's avatar Philip Cunningham

Add header validation to DastSiteValidationWorker

Add ability to validate a DastSiteValidation using a header.
parent 93758584
# frozen_string_literal: true # frozen_string_literal: true
class DastSiteValidation < ApplicationRecord class DastSiteValidation < ApplicationRecord
HEADER = 'Gitlab-On-Demand-DAST'.freeze
belongs_to :dast_site_token belongs_to :dast_site_token
has_many :dast_sites has_many :dast_sites
...@@ -13,7 +15,7 @@ class DastSiteValidation < ApplicationRecord ...@@ -13,7 +15,7 @@ class DastSiteValidation < ApplicationRecord
before_create :set_normalized_url_base before_create :set_normalized_url_base
enum validation_strategy: { text_file: 0 } enum validation_strategy: { text_file: 0, header: 1 }
delegate :project, to: :dast_site_token, allow_nil: true delegate :project, to: :dast_site_token, allow_nil: true
......
...@@ -38,11 +38,20 @@ module DastSiteValidations ...@@ -38,11 +38,20 @@ module DastSiteValidations
end end
def token_found?(response) def token_found?(response)
response.body.include?(dast_site_validation.dast_site_token.token) token = dast_site_validation.dast_site_token.token
case dast_site_validation.validation_strategy
when 'text_file'
response.body.include?(token)
when 'header'
response.headers[DastSiteValidation::HEADER] == token
else
false
end
end end
def validate!(response) def validate!(response)
raise TokenNotFound.new('Could not find token in response body') unless token_found?(response) raise TokenNotFound.new('Could not find token') unless token_found?(response)
dast_site_validation.pass dast_site_validation.pass
end end
......
---
title: Add header validation to DastSiteValidationWorker
merge_request: 44314
author:
type: added
...@@ -51,7 +51,7 @@ RSpec.describe DastSiteValidation, type: :model do ...@@ -51,7 +51,7 @@ RSpec.describe DastSiteValidation, type: :model do
describe 'enums' do describe 'enums' do
let(:validation_strategies) do let(:validation_strategies) do
{ text_file: 0 } { text_file: 0, header: 1 }
end end
it { is_expected.to define_enum_for(:validation_strategy).with_values(validation_strategies) } it { is_expected.to define_enum_for(:validation_strategy).with_values(validation_strategies) }
......
...@@ -4,6 +4,7 @@ require 'spec_helper' ...@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe DastSiteValidations::ValidateService do RSpec.describe DastSiteValidations::ValidateService do
let(:dast_site_validation) { create(:dast_site_validation) } let(:dast_site_validation) { create(:dast_site_validation) }
let(:token) { dast_site_validation.dast_site_token.token }
subject do subject do
described_class.new( described_class.new(
...@@ -35,11 +36,7 @@ RSpec.describe DastSiteValidations::ValidateService do ...@@ -35,11 +36,7 @@ RSpec.describe DastSiteValidations::ValidateService do
before do before do
stub_licensed_features(security_on_demand_scans: true) stub_licensed_features(security_on_demand_scans: true)
stub_feature_flags(security_on_demand_scans_site_validation: true) stub_feature_flags(security_on_demand_scans_site_validation: true)
stub_request(:get, dast_site_validation.validation_url).to_return(body: response_body) stub_request(:get, dast_site_validation.validation_url).to_return(body: token)
end
let(:response_body) do
dast_site_validation.dast_site_token.token
end end
it 'validates the url before making an http request' do it 'validates the url before making an http request' do
...@@ -47,13 +44,26 @@ RSpec.describe DastSiteValidations::ValidateService do ...@@ -47,13 +44,26 @@ RSpec.describe DastSiteValidations::ValidateService do
aggregate_failures do aggregate_failures do
expect(Gitlab::UrlBlocker).to receive(:validate!).and_return([uri, nil]) expect(Gitlab::UrlBlocker).to receive(:validate!).and_return([uri, nil])
expect(Gitlab::HTTP).to receive(:get).with(uri).and_return(double('response', body: dast_site_validation.dast_site_token.token)) expect(Gitlab::HTTP).to receive(:get).with(uri).and_return(double('response', body: token))
end
subject
end end
context 'when validation has already been attempted' do
let_it_be(:dast_site_validation) { create(:dast_site_validation, state: :failed) }
it 'marks the validation as a retry' do
freeze_time do
subject subject
expect(dast_site_validation.reload.validation_last_retried_at).to eq(Time.now.utc)
end
end
end end
context 'when the request body contains the token' do shared_examples 'a validation' do
context 'when the token is found' do
it 'calls dast_site_validation#start' do it 'calls dast_site_validation#start' do
expect(dast_site_validation).to receive(:start) expect(dast_site_validation).to receive(:start)
...@@ -73,7 +83,9 @@ RSpec.describe DastSiteValidations::ValidateService do ...@@ -73,7 +83,9 @@ RSpec.describe DastSiteValidations::ValidateService do
end end
context 'when validation has already started' do context 'when validation has already started' do
let(:dast_site_validation) { create(:dast_site_validation, state: :inprogress) } before do
dast_site_validation.update_column(:state, :inprogress)
end
it 'does not call dast_site_validation#pass' do it 'does not call dast_site_validation#pass' do
expect(dast_site_validation).not_to receive(:start) expect(dast_site_validation).not_to receive(:start)
...@@ -83,7 +95,9 @@ RSpec.describe DastSiteValidations::ValidateService do ...@@ -83,7 +95,9 @@ RSpec.describe DastSiteValidations::ValidateService do
end end
context 'when validation is already complete' do context 'when validation is already complete' do
let(:dast_site_validation) { create(:dast_site_validation, state: :passed) } before do
dast_site_validation.update_column(:state, :passed)
end
it 'does not re-validate' do it 'does not re-validate' do
expect(Gitlab::HTTP).not_to receive(:get) expect(Gitlab::HTTP).not_to receive(:get)
...@@ -93,8 +107,8 @@ RSpec.describe DastSiteValidations::ValidateService do ...@@ -93,8 +107,8 @@ RSpec.describe DastSiteValidations::ValidateService do
end end
end end
context 'when the request body does not contain the token' do context 'when the token is not found' do
let(:response_body) do let(:token) do
SecureRandom.hex SecureRandom.hex
end end
...@@ -102,17 +116,28 @@ RSpec.describe DastSiteValidations::ValidateService do ...@@ -102,17 +116,28 @@ RSpec.describe DastSiteValidations::ValidateService do
expect { subject }.to raise_error(DastSiteValidations::ValidateService::TokenNotFound) expect { subject }.to raise_error(DastSiteValidations::ValidateService::TokenNotFound)
end end
end end
end
context 'when validation has already been attempted' do context 'when validation_strategy=text_file' do
let_it_be(:dast_site_validation) { create(:dast_site_validation, state: :failed) } let(:dast_site_validation) { create(:dast_site_validation, validation_strategy: :text_file) }
it 'marks the validation as a retry' do before do
freeze_time do stub_request(:get, dast_site_validation.validation_url).to_return(body: token)
subject end
expect(dast_site_validation.reload.validation_last_retried_at).to eq(Time.now.utc) it_behaves_like 'a validation'
end end
context 'when validation_strategy=header' do
let(:dast_site_validation) { create(:dast_site_validation, validation_strategy: :header) }
before do
headers = { DastSiteValidation::HEADER => token }
stub_request(:get, dast_site_validation.validation_url).to_return(headers: headers)
end end
it_behaves_like 'a validation'
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