Skip to content
代码片段 群组 项目
未验证 提交 215b7aea 编辑于 作者: Marcos Rocha's avatar Marcos Rocha 提交者: GitLab
浏览文件

Merge branch '433035-status-checks-update-model' into 'master'

Adds shared secret for external_status_check model

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159983



Merged-by: default avatarMarcos Rocha <mrocha@gitlab.com>
Approved-by: default avatarAlan (Maciej) Paruszewski <mparuszewski@gitlab.com>
Approved-by: default avatarMarcos Rocha <mrocha@gitlab.com>
Reviewed-by: default avatarArtur Fedorov <afedorov@gitlab.com>
Co-authored-by: default avatarArtur Fedorov <afedorov@gitlab.com>
No related branches found
No related tags found
无相关合并请求
显示
68 个添加4 个删除
...@@ -31,6 +31,7 @@ GET /projects/:id/external_status_checks ...@@ -31,6 +31,7 @@ GET /projects/:id/external_status_checks
"name": "Compliance Tool", "name": "Compliance Tool",
"project_id": 6, "project_id": 6,
"external_url": "https://gitlab.com/example/compliance-tool", "external_url": "https://gitlab.com/example/compliance-tool",
"hmac": true,
"protected_branches": [ "protected_branches": [
{ {
"id": 14, "id": 14,
...@@ -62,6 +63,7 @@ defined external service. This includes confidential merge requests. ...@@ -62,6 +63,7 @@ defined external service. This includes confidential merge requests.
| `id` | integer | yes | ID of a project | | `id` | integer | yes | ID of a project |
| `name` | string | yes | Display name of external status check service | | `name` | string | yes | Display name of external status check service |
| `external_url` | string | yes | URL of external status check service | | `external_url` | string | yes | URL of external status check service |
| `shared_secret` | string | no | HMAC secret for external status check |
| `protected_branch_ids` | `array<Integer>` | no | IDs of protected branches to scope the rule by | | `protected_branch_ids` | `array<Integer>` | no | IDs of protected branches to scope the rule by |
## Update external status check service ## Update external status check service
......
...@@ -7,6 +7,11 @@ class ExternalStatusCheck < ApplicationRecord ...@@ -7,6 +7,11 @@ class ExternalStatusCheck < ApplicationRecord
include Auditable include Auditable
include EachBatch include EachBatch
attr_encrypted :shared_secret,
mode: :per_attribute_iv,
algorithm: 'aes-256-cbc',
key: Settings.attr_encrypted_db_key_base_32
scope :with_api_entity_associations, -> { preload(:protected_branches) } scope :with_api_entity_associations, -> { preload(:protected_branches) }
scope :applicable_to_branch, ->(branch) do scope :applicable_to_branch, ->(branch) do
includes(:protected_branches) includes(:protected_branches)
...@@ -85,6 +90,10 @@ def audit_protected_branch_remove(model) ...@@ -85,6 +90,10 @@ def audit_protected_branch_remove(model)
push_audit_event(message) push_audit_event(message)
end end
def hmac?
shared_secret.present?
end
private private
def protected_branches_names def protected_branches_names
......
...@@ -36,7 +36,7 @@ def execute_on_all_protected_branches_rule ...@@ -36,7 +36,7 @@ def execute_on_all_protected_branches_rule
end end
def permitted_params def permitted_params
%i[name external_url] %i[name external_url shared_secret]
end end
end end
end end
......
...@@ -9,6 +9,7 @@ def execute(skip_authorization: false) ...@@ -9,6 +9,7 @@ def execute(skip_authorization: false)
rule = container.external_status_checks.new(name: params[:name], rule = container.external_status_checks.new(name: params[:name],
external_url: params[:external_url], external_url: params[:external_url],
shared_secret: params[:shared_secret],
protected_branch_ids: params[:protected_branch_ids]) protected_branch_ids: params[:protected_branch_ids])
if with_audit_logged(rule, 'create_status_check') { rule.save } if with_audit_logged(rule, 'create_status_check') { rule.save }
......
...@@ -8,6 +8,7 @@ class ExternalStatusCheck < Grape::Entity ...@@ -8,6 +8,7 @@ class ExternalStatusCheck < Grape::Entity
expose :project_id, documentation: { type: 'integer', example: 1 } expose :project_id, documentation: { type: 'integer', example: 1 }
expose :external_url, documentation: { type: 'string', example: 'https://www.example.com' } expose :external_url, documentation: { type: 'string', example: 'https://www.example.com' }
expose :protected_branches, using: ::API::Entities::ProtectedBranch, documentation: { is_array: true } expose :protected_branches, using: ::API::Entities::ProtectedBranch, documentation: { is_array: true }
expose :hmac?, as: :hmac, documentation: { type: 'boolean', example: 'true' }
end end
end end
end end
...@@ -24,6 +24,7 @@ def check_feature_enabled! ...@@ -24,6 +24,7 @@ def check_feature_enabled!
end end
params do params do
requires :name, type: String, desc: 'Display name of external status check', documentation: { example: 'QA' } requires :name, type: String, desc: 'Display name of external status check', documentation: { example: 'QA' }
optional :shared_secret, type: String, desc: 'HMAC shared secret', documentation: { example: 'hmac-sha256' }
requires :external_url, requires :external_url,
type: String, type: String,
desc: 'URL of external status check resource', desc: 'URL of external status check resource',
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe API::Entities::ExternalStatusCheck, feature_category: :source_code_management do
subject { described_class.new(external_status_check).as_json }
let(:external_status_check) { build(:external_status_check) }
it 'exposes correct attributes' do
is_expected.to include(:id, :name, :project_id, :hmac, :protected_branches, :external_url)
end
end
...@@ -179,6 +179,39 @@ ...@@ -179,6 +179,39 @@
it { is_expected.to eq(second_response) } it { is_expected.to eq(second_response) }
end end
describe 'hmac?' do
let_it_be(:merge_request) { create(:merge_request) }
let(:project) { merge_request.source_project }
context 'when shared secret is saved' do
let_it_be(:rule) { create(:external_status_check, shared_secret: 'shared_secret') }
subject { rule.hmac? }
it { is_expected.to eq(true) }
end
context 'when shared secret is not saved' do
let_it_be(:rule) { create(:external_status_check) }
subject { rule.hmac? }
it { is_expected.to eq(false) }
end
context 'when shared secret had invalid value' do
['', ' ', nil].each do |value|
context "with invalid value #{value}" do
let_it_be(:rule) { create(:external_status_check, shared_secret: value) }
subject { rule.hmac? }
it { is_expected.to eq(false) }
end
end
end
end
describe 'callbacks', :request_store do describe 'callbacks', :request_store do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:master_branch) { create(:protected_branch, project: project, name: 'master') } let_it_be(:master_branch) { create(:protected_branch, project: project, name: 'master') }
......
...@@ -215,7 +215,7 @@ ...@@ -215,7 +215,7 @@
let_it_be(:protected_branch) { create(:protected_branch, project: project) } let_it_be(:protected_branch) { create(:protected_branch, project: project) }
let(:params) do let(:params) do
{ name: 'New rule', external_url: 'https://gitlab.com/test/example.json', protected_branch_ids: protected_branch.id } { name: 'New rule', external_url: 'https://gitlab.com/test/example.json', protected_branch_ids: protected_branch.id, shared_secret: 'shared_secret' }
end end
subject do subject do
...@@ -239,6 +239,7 @@ ...@@ -239,6 +239,7 @@
expect(json_response['id']).not_to be_nil expect(json_response['id']).not_to be_nil
expect(json_response['name']).to eq('New rule') expect(json_response['name']).to eq('New rule')
expect(json_response['hmac']).to eq(true)
expect(json_response['external_url']).to eq('https://gitlab.com/test/example.json') expect(json_response['external_url']).to eq('https://gitlab.com/test/example.json')
expect(json_response['protected_branches'].size).to eq(1) expect(json_response['protected_branches'].size).to eq(1)
end end
...@@ -502,6 +503,7 @@ ...@@ -502,6 +503,7 @@
expect(json_response['id']).not_to be_nil expect(json_response['id']).not_to be_nil
expect(json_response['name']).to eq('New rule') expect(json_response['name']).to eq('New rule')
expect(json_response['hmac']).to eq(false)
expect(json_response['external_url']).to eq('https://gitlab.com/test/example.json') expect(json_response['external_url']).to eq('https://gitlab.com/test/example.json')
expect(json_response['protected_branches'].size).to eq(1) expect(json_response['protected_branches'].size).to eq(1)
end end
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
let(:create_service) { ExternalStatusChecks::CreateService } let(:create_service) { ExternalStatusChecks::CreateService }
let(:create_service_instance) { instance_double(update_service) } let(:create_service_instance) { instance_double(update_service) }
let(:status_check_name) { 'Test' } let(:status_check_name) { 'Test' }
let(:params) { { name: status_check_name, external_url: 'https://external_url.text/hello.json' } } let(:params) { { name: status_check_name, external_url: 'https://external_url.text/hello.json', shared_secret: 'shared_secret' } }
subject(:execute) { described_class.new(branch_rule, user, params).execute } subject(:execute) { described_class.new(branch_rule, user, params).execute }
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
{ {
name: 'Test', name: 'Test',
external_url: 'https://external_url.text/hello.json', external_url: 'https://external_url.text/hello.json',
protected_branch_ids: [protected_branch.id] protected_branch_ids: [protected_branch.id],
shared_secret: 'shared_secret'
} }
end end
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
expect(rule.project).to eq(project) expect(rule.project).to eq(project)
expect(rule.external_url).to eq('https://external_url.text/hello.json') expect(rule.external_url).to eq('https://external_url.text/hello.json')
expect(rule.name).to eq 'Test' expect(rule.name).to eq 'Test'
expect(rule.shared_secret).to eq 'shared_secret'
expect(rule.protected_branches).to contain_exactly(protected_branch) expect(rule.protected_branches).to contain_exactly(protected_branch)
end end
end end
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册