Commit fd49457c authored by Marius Bobin's avatar Marius Bobin

Restrict external pipeline validation to a single not acceptable code

Restrict external pipeline validation to a single not acceptable code
parent bb8f7f7c
---
name: ci_external_validation_service
introduced_by_url: TODO
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323935
milestone: '13.11'
type: development
group: group::continuous integration
default_enabled: false
......@@ -22,7 +22,7 @@ invalidated.
Response Code Legend:
- `200` - Accepted
- `4xx` - Not Accepted
- `406` - Not Accepted
- Other Codes - Accepted and Logged
## Configuration
......
......@@ -13,6 +13,8 @@ module Gitlab
VALIDATION_REQUEST_TIMEOUT = 5
def perform!
return unless ::Feature.enabled?(:ci_external_validation_service, @pipeline.project, default_enabled: :yaml)
pipeline_authorized = validate_external
log_message = pipeline_authorized ? 'authorized' : 'not authorized'
......@@ -31,19 +33,19 @@ module Gitlab
return true unless validation_service_url
# 200 - accepted
# 4xx - not accepted
# 406 - not accepted
# everything else - accepted and logged
response_code = validate_service_request.code
case response_code
when 200
true
when 400..499
when 406
false
else
raise InvalidResponseCode, "Unsupported response code received from Validation Service: #{response_code}"
end
rescue => ex
Gitlab::ErrorTracking.track_exception(ex)
Gitlab::ErrorTracking.track_exception(ex, project_id: @pipeline.project.id)
true
end
......
......@@ -51,11 +51,13 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
describe '#perform!' do
subject(:perform!) { step.perform! }
context 'when validation returns true' do
let(:validation_service_url) { 'https://validation-service.external/' }
before do
allow(step).to receive(:validate_external).and_return(true)
stub_env('EXTERNAL_VALIDATION_SERVICE_URL', validation_service_url)
end
shared_examples 'successful external authorization' do
it 'does not drop the pipeline' do
perform!
......@@ -76,9 +78,74 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
end
context 'when validation return false' do
context 'when validation returns 200 OK' do
before do
stub_request(:post, validation_service_url).to_return(status: 200, body: "{}")
end
it_behaves_like 'successful external authorization'
end
context 'when validation returns 404 Not Found' do
before do
stub_request(:post, validation_service_url).to_return(status: 404, body: "{}")
end
it_behaves_like 'successful external authorization'
end
context 'when validation returns 500 Internal Server Error' do
before do
stub_request(:post, validation_service_url).to_return(status: 500, body: "{}")
end
it_behaves_like 'successful external authorization'
end
context 'when validation raises exceptions' do
before do
stub_request(:post, validation_service_url).to_raise(Net::OpenTimeout)
end
it_behaves_like 'successful external authorization'
it 'logs exceptions' do
expect(Gitlab::ErrorTracking).to receive(:track_exception)
.with(instance_of(Net::OpenTimeout), { project_id: project.id })
perform!
end
end
context 'when the feature flag is disabled' do
before do
stub_feature_flags(ci_external_validation_service: false)
stub_request(:post, validation_service_url)
end
it 'does not drop the pipeline' do
perform!
expect(pipeline.status).not_to eq('failed')
expect(pipeline.errors).to be_empty
end
it 'does not break the chain' do
perform!
expect(step.break?).to be false
end
it 'does not make requests' do
perform!
expect(WebMock).not_to have_requested(:post, validation_service_url)
end
end
context 'when validation returns 406 Not Acceptable' do
before do
allow(step).to receive(:validate_external).and_return(false)
stub_request(:post, validation_service_url).to_return(status: 406, body: "{}")
end
it 'drops the pipeline' do
......
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