Authenticate Geo node status endpoint by Geo node token

parent 6c308a02
......@@ -2,18 +2,15 @@ module Geo
class NodeStatusService
include HTTParty
KEYS = %w(health repositories repositories_synced repositories_failed).freeze
# HTTParty timeout
default_timeout Gitlab.config.gitlab.geo_status_timeout
def call(status_url)
keys = %w(health repositories repositories_synced repositories_failed)
values =
begin
response = self.class.get(status_url,
headers: {
'Content-Type' => 'application/json',
'PRIVATE-TOKEN' => private_token
})
response = self.class.get(status_url, headers: headers)
if response.success? || response.redirection?
response.parsed_response.values_at(*keys)
......@@ -24,14 +21,13 @@ module Geo
[e.message]
end
GeoNodeStatus.new(keys.zip(values).to_h)
GeoNodeStatus.new(KEYS.zip(values).to_h)
end
private
def private_token
# TODO: should we ask admin user to be defined as part of configuration?
@private_token ||= User.find_by(admin: true).authentication_token
def headers
Gitlab::Geo::BaseRequest.new.headers
end
end
end
......@@ -33,7 +33,7 @@ module API
# Example request:
# GET /geo/status
get 'status' do
authenticated_as_admin!
authenticate_by_gitlab_geo_node_token!
require_node_to_be_secondary!
present GeoNodeStatus.new, with: Entities::GeoNodeStatus
......@@ -90,12 +90,20 @@ module API
end
helpers do
def authenticate_by_gitlab_geo_node_token!
auth_header = headers['Authorization']
unless auth_header && Gitlab::Geo::JwtRequestDecoder.new(auth_header).decode
unauthorized!
end
end
def require_node_to_be_enabled!
forbidden! 'Geo node is disabled.' unless Gitlab::Geo.current_node.enabled?
forbidden! 'Geo node is disabled.' unless Gitlab::Geo.current_node&.enabled?
end
def require_node_to_be_secondary!
forbidden! 'Geo node is disabled.' unless Gitlab::Geo.current_node.secondary?
forbidden! 'Geo node is not secondary node.' unless Gitlab::Geo.current_node&.secondary?
end
end
end
......
......@@ -2,11 +2,12 @@ require 'spec_helper'
describe API::Geo, api: true do
include ApiHelpers
let(:admin) { create(:admin) }
let(:user) { create(:user) }
let!(:geo_node) { create(:geo_node, :primary) }
let!(:primary_node) { create(:geo_node, :primary) }
let(:geo_token_header) do
{ 'X-Gitlab-Token' => geo_node.system_hook.token }
{ 'X-Gitlab-Token' => primary_node.system_hook.token }
end
before(:each) do
......@@ -27,7 +28,7 @@ describe API::Geo, api: true do
describe 'POST /geo/refresh_wikis disabled node' do
it 'responds with forbidden' do
geo_node.enabled = false
primary_node.enabled = false
post api('/geo/refresh_wikis', admin), nil
......@@ -37,7 +38,7 @@ describe API::Geo, api: true do
describe 'POST /geo/receive_events disabled node' do
it 'responds with forbidden' do
geo_node.enabled = false
primary_node.enabled = false
post api('/geo/receive_events'), nil, geo_token_header
......@@ -125,7 +126,7 @@ describe API::Geo, api: true do
let(:lfs_object) { create(:lfs_object, :with_file) }
let(:req_header) do
transfer = Gitlab::Geo::LfsTransfer.new(lfs_object)
Gitlab::Geo::TransferRequest.new(transfer.request_data).header
Gitlab::Geo::TransferRequest.new(transfer.request_data).headers
end
before do
......@@ -156,4 +157,42 @@ describe API::Geo, api: true do
end
end
end
describe 'GET /geo/status' do
let!(:secondary_node) { create(:geo_node) }
let(:request) { Gitlab::Geo::BaseRequest.new }
it 'responds with 401 with invalid auth header' do
get api('/geo/status'), nil, Authorization: 'Test'
expect(response.status).to eq 401
end
context 'when requesting secondary node with valid auth header' do
before(:each) do
allow(Gitlab::Geo).to receive(:current_node) { secondary_node }
allow(request).to receive(:requesting_node) { primary_node }
end
it 'responds with 200' do
get api('/geo/status'), nil, request.headers
expect(response.status).to eq 200
expect(response.headers['Content-Type']).to eq('application/json')
end
end
context 'when requesting primary node with valid auth header' do
before(:each) do
allow(Gitlab::Geo).to receive(:current_node) { primary_node }
allow(request).to receive(:requesting_node) { secondary_node }
end
it 'responds with 403' do
get api('/geo/status'), nil, request.headers
expect(response).to have_http_status(403)
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