Skip to content
Snippets Groups Projects
Commit 14359872 authored by Mark Chao's avatar Mark Chao :two: Committed by GitLab Release Tools Bot
Browse files

Pass SSO session data to Sidekiq

Merge branch 'security-452548-sso-2-17-1' into '17-1-stable-ee'

See merge request gitlab-org/security/gitlab!4197

Changelog: security
parent 8c41be0b
No related branches found
No related tags found
No related merge requests found
......@@ -30,7 +30,9 @@ def deserialize_message(message_hash, options)
end
def perform_for(message, options = {})
with_ip_address_state.perform_async(serialize_message(message), options)
session_id = ::Gitlab::Session.current&.id&.private_id
# We want to set it even if it is nil, so session will be set and policy check won't be skipped
with_ip_address_state.set(set_session_id: session_id).perform_async(serialize_message(message), options)
end
end
......
# frozen_string_literal: true
module EE
module Gitlab
module SidekiqMiddleware
extend ActiveSupport::Concern
class_methods do
extend ::Gitlab::Utils::Override
override :server_configurator
def server_configurator(metrics: true, arguments_logger: true, skip_jobs: true)
->(chain) do
super.call(chain)
chain.add ::Gitlab::SidekiqMiddleware::SetSession::Server
end
end
override :client_configurator
def client_configurator
->(chain) do
super.call(chain)
end
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module SidekiqMiddleware
module SetSession
class Server
def call(_worker, job, _queue)
if job.key?('set_session_id')
session_id = job['set_session_id']
session = ActiveSession.sessions_from_ids([job['set_session_id']]).first if session_id
session ||= {}
session = session.with_indifferent_access
::Gitlab::Session.with_session(session) do
yield
end
else
yield
end
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::SidekiqMiddleware, feature_category: :shared do
let(:job_args) { [0.01] }
let(:disabled_sidekiq_middlewares) { [] }
let(:chain) { Sidekiq::Middleware::Chain.new(Sidekiq) }
let(:queue) { 'test' }
let(:enabled_sidekiq_middlewares) { all_sidekiq_middlewares - disabled_sidekiq_middlewares }
let(:worker_class) do
Class.new do
def self.name
'TestWorker'
end
include ApplicationWorker
def perform(*_args); end
end
end
before do
stub_const('TestWorker', worker_class)
end
shared_examples "a middleware chain" do
before do
configurator.call(chain)
stub_feature_flags("drop_sidekiq_jobs_#{worker_class.name}": false) # not dropping the job
end
it "passes through the right middlewares", :aggregate_failures do
enabled_sidekiq_middlewares.each do |middleware|
expect_next_instances_of(middleware, 1, true) do |middleware_instance|
expect(middleware_instance).to receive(:call).with(*middleware_expected_args).once.and_call_original
end
end
expect { |b| chain.invoke(*worker_args, &b) }.to yield_control.once
end
end
describe '.server_configurator' do
let(:configurator) { described_class.server_configurator }
let(:worker_args) { [worker_class.new, { 'args' => job_args }, queue] }
let(:middleware_expected_args) { [a_kind_of(worker_class), hash_including({ 'args' => job_args }), queue] }
let(:all_sidekiq_middlewares) do
[
::Gitlab::SidekiqMiddleware::SetSession::Server
]
end
it_behaves_like "a middleware chain"
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::SidekiqMiddleware::SetSession::Server, feature_category: :shared do
let(:worker) { instance_double(ApplicationWorker) }
let(:job) { {} }
let(:queue) { 'default' }
let(:server) { described_class.new }
describe '#call' do
def call!(&block)
block ||= -> {}
subject.call(worker, job, queue, &block)
end
context 'when job has set_session_id' do
let(:session_id) { 'session_id' }
let(:session) { { 'key' => 'value' } }
let(:job) { { 'set_session_id' => session_id } }
it 'sets the session and yields' do
expect(ActiveSession).to receive(:sessions_from_ids).with([session_id]).and_return([session])
expect(Gitlab::Session).to receive(:with_session).with(session).and_yield
call!
end
it 'when session is not found' do
expect(ActiveSession).to receive(:sessions_from_ids).with([session_id]).and_return([])
expect(Gitlab::Session).to receive(:with_session).with({}).and_yield
call!
end
context 'when set_session_id is nil' do
let(:session_id) { nil }
it 'sets empty session and yields' do
expect(ActiveSession).not_to receive(:sessions_from_ids)
expect(Gitlab::Session).to receive(:with_session).with({}).and_yield
call!
end
end
end
context 'when set_session_id key is absent' do
it 'yields without setting the session' do
expect(Gitlab::Session).not_to receive(:with_session)
call!
end
end
end
end
......@@ -53,9 +53,11 @@
describe '.perform_for' do
let(:ip_address) { '1.1.1.1' }
it 'sets set_ip_address to true' do
before do
allow(::Gitlab::IpAddressState).to receive(:current).and_return(ip_address)
end
it 'sets set_ip_address to true' do
described_class.perform_for(prompt_message, options)
job = described_class.jobs.first
......@@ -68,5 +70,44 @@
]
)
end
context 'when Session is present' do
let(:rack_session) { Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d') }
let(:session) { instance_double(ActionDispatch::Request::Session, id: rack_session) }
it 'sets set_session_id' do
::Gitlab::Session.with_session(session) do
described_class.perform_for(prompt_message, options)
end
job = described_class.jobs.first
expect(job).to include(
'ip_address_state' => ip_address,
'set_session_id' => rack_session.private_id,
'args' => [
hash_including("ai_action" => ai_action_name.to_s),
options
]
)
end
end
context 'when sessionless' do
it 'sets set_session_id to nil' do
described_class.perform_for(prompt_message, options)
job = described_class.jobs.first
expect(job).to include(
'ip_address_state' => ip_address,
'set_session_id' => nil,
'args' => [
hash_including("ai_action" => ai_action_name.to_s),
options
]
)
end
end
end
end
......@@ -71,3 +71,5 @@ def self.client_configurator
end
end
end
Gitlab::SidekiqMiddleware.prepend_mod
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment