Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion middleware/security_context_setter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def call(env)
security_context_configurer = @security_context_configurer

if request_path && request_path.match(UPLOADS_PATH_REGEX)
upload_start_time = Rack::Request.new(env).params['upload_start_time'].to_i
upload_start_time = upload_start_time_from_nginx(env)
if upload_start_time
relaxed_token_decoder = VCAP::CloudController::UaaTokenDecoder.new(VCAP::CloudController::Config.config.get(:uaa), alternate_reference_time: upload_start_time)
security_context_configurer = VCAP::CloudController::Security::SecurityContextConfigurer.new(relaxed_token_decoder)
Expand Down Expand Up @@ -56,6 +56,16 @@ def call(env)

private

def upload_start_time_from_nginx(env)
raw_value = Rack::Request.new(env).POST['upload_start_time']
return false if raw_value.blank?

upload_start_time = raw_value.to_i
return false unless upload_start_time.positive?

[upload_start_time, Time.now.to_i].min
end

def id_from_token
VCAP::CloudController::SecurityContext.token['user_id'] || VCAP::CloudController::SecurityContext.token['client_id']
end
Expand Down
79 changes: 79 additions & 0 deletions spec/unit/middleware/security_context_setter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,85 @@ module Middleware
expect { middleware.call(env) }.to raise_error(error)
end
end

context 'when the request targets an upload endpoint' do
let(:path_info) { '/v3/packages/0b6a2f0e-9c5a-4c1d-8e2f-1a2b3c4d5e6f/upload' }
let(:upload_env) do
{
'HTTP_AUTHORIZATION' => 'auth-token',
'PATH_INFO' => path_info,
'REQUEST_PATH' => path_info,
'REQUEST_METHOD' => 'POST',
'QUERY_STRING' => query_string,
'CONTENT_TYPE' => content_type,
'rack.input' => StringIO.new(request_body)
}
end
let(:query_string) { '' }
let(:content_type) { 'application/x-www-form-urlencoded' }
let(:request_body) { '' }

context 'when upload_start_time is absent from the POST body' do
it 'uses the strict token decoder' do
expect(VCAP::CloudController::UaaTokenDecoder).not_to receive(:new)

middleware.call(upload_env)
end
end

context 'when upload_start_time is passed as a query parameter (client-supplied, ignored)' do
let(:query_string) { 'upload_start_time=123' }

it 'ignores it and uses the strict token decoder' do
expect(VCAP::CloudController::UaaTokenDecoder).not_to receive(:new)

middleware.call(upload_env)
end
end

context 'when upload_start_time is in the POST body (as injected by nginx upload module)' do
let(:request_body) { 'upload_start_time=123' }

it 'uses a relaxed token decoder with the given reference time' do
expect(VCAP::CloudController::UaaTokenDecoder).to receive(:new).
with(anything, alternate_reference_time: 123).and_return(token_decoder)

middleware.call(upload_env)
end
end

context 'when upload_start_time in the POST body is in the future' do
let(:request_body) { 'upload_start_time=9999999999' }

it 'clamps the reference time to now' do
Timecop.freeze do
expect(VCAP::CloudController::UaaTokenDecoder).to receive(:new).
with(anything, alternate_reference_time: Time.now.to_i).and_return(token_decoder)
middleware.call(upload_env)
end
end
end

context 'when upload_start_time in the POST body is not a positive integer' do
let(:request_body) { 'upload_start_time=abc' }

it 'uses the strict token decoder' do
expect(VCAP::CloudController::UaaTokenDecoder).not_to receive(:new)

middleware.call(upload_env)
end
end

context 'when upload_start_time in the POST body is empty' do
let(:request_body) { 'upload_start_time=' }

it 'uses the strict token decoder' do
expect(VCAP::CloudController::UaaTokenDecoder).not_to receive(:new)

middleware.call(upload_env)
end
end
end
end
end
end
Expand Down
Loading