Skip to content

Commit

Permalink
Fixes #37661 - block users properly from pushing content
Browse files Browse the repository at this point in the history
  • Loading branch information
ianballou committed Jul 26, 2024
1 parent 0033ee2 commit 7f4429d
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 14 deletions.
74 changes: 62 additions & 12 deletions lib/smart_proxy_container_gateway/container_gateway_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,28 @@ class Api < ::Sinatra::Base
end
end

put '/v2/*/manifests/*/?' do
throw_unsupported_error
end

get '/v2/*/blobs/*/?' do
repository = params[:splat][0]
digest = params[:splat][1]
handle_repo_auth(repository, auth_header, request)
pulp_response = container_gateway_main.blobs(repository, digest, translated_headers_for_proxy)
if pulp_response.code.to_i >= 400
status pulp_response.code.to_i
body pulp_response.body
else
redirection_location = pulp_response['location']
redirect to(redirection_location)
end
head_or_get_blobs
end

head '/v2/*/blobs/*/?' do
head_or_get_blobs
end

post '/v2/*/blobs/uploads/?' do
throw_unsupported_error
end

put '/v2/*/blobs/uploads/*/?' do
throw_unsupported_error
end

patch '/v2/*/blobs/uploads/*/?' do
throw_unsupported_error
end

get '/v2/*/tags/list/?' do
Expand Down Expand Up @@ -198,6 +208,46 @@ class Api < ::Sinatra::Base

private

def head_or_get_blobs
repository = params[:splat][0]
digest = params[:splat][1]
handle_repo_auth(repository, auth_header, request)
pulp_response = container_gateway_main.blobs(repository, digest, translated_headers_for_proxy)
if pulp_response.code.to_i >= 400
status pulp_response.code.to_i
body pulp_response.body
else
redirection_location = pulp_response['location']
redirect to(redirection_location)
end
end

def throw_unsupported_error
content_type :json
body ({
"errors" => [
{
"code" => "UNSUPPORTED",
"message" => "Pushing content is unsupported"
}
]
}.to_json)
halt 404
end

def throw_repo_not_found_error
content_type :json
body ({
"errors" => [
{
"code" => "NAME_UNKNOWN",
"message" => "Repository name unknown"
}
]
}.to_json)
halt 404
end

def translated_headers_for_proxy
current_headers = {}
env = request.env.select do |key, _value|
Expand All @@ -220,7 +270,7 @@ def handle_repo_auth(repository, auth_header, request)
return if container_gateway_main.authorized_for_repo?(repository, user_token_is_valid, username)

redirect_authorization_headers
halt 401, "unauthorized"
throw_repo_not_found_error
end

def redirect_authorization_headers
Expand Down
3 changes: 3 additions & 0 deletions lib/smart_proxy_container_gateway/container_gateway_main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ def update_user_repositories(username, repositories)
end
end

# Returns:
# true if the user is authorized to access the repo, or
# false if the user is not authorized to access the repo or if it does not exist
def authorized_for_repo?(repo_name, user_token_is_valid, username = nil)
repository = database.connection[:repositories][{ name: repo_name }]

Expand Down
45 changes: 43 additions & 2 deletions test/container_gateway_api_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,57 @@ def test_redirects_blob_request
assert_equal('', last_response.body)
end

def test_redirects_blob_head_request
::Proxy::ContainerGateway::Api.any_instance.expects(:handle_repo_auth).returns({})
redirect_headers = { 'location' => "#{::Proxy::ContainerGateway::Plugin.settings.pulp_endpoint}" \
"/pulp/container/library/test_repo/blobs/test_digest?validate_token=test_token" }
stub_request(:get, "#{::Proxy::ContainerGateway::Plugin.settings.pulp_endpoint}" \
"/pulpcore_registry/v2/library/test_repo/blobs/test_digest").
to_return(:status => 302, :body => '', :headers => redirect_headers)

head '/v2/library/test_repo/blobs/test_digest'
assert last_response.redirect?, "Last response was not a redirect: #{last_response.body}"
assert_equal('', last_response.body)
end

def test_unauthorized_for_manifests
@container_gateway_main.expects(:authorized_for_repo?).returns(false)
get '/v2/test_repo/manifests/test_tag'
assert_equal 401, last_response.status
assert_equal 404, last_response.status
end

def test_unauthorized_for_blobs
@container_gateway_main.expects(:authorized_for_repo?).returns(false)
get '/v2/test_repo/blobs/test_digest'
assert_equal 401, last_response.status
assert_equal 404, last_response.status
end

def test_put_manifests
put '/v2/library/test_repo/manifests/test_tag'
assert_equal 404, last_response.status
assert_equal({ "errors" => [{ "code" => "UNSUPPORTED", "message" => "Pushing content is unsupported" }] },
JSON.parse(last_response.body))
end

def test_post_blob_uploads
post '/v2/library/test_repo/blobs/uploads/'
assert_equal 404, last_response.status
assert_equal({ "errors" => [{ "code" => "UNSUPPORTED", "message" => "Pushing content is unsupported" }] },
JSON.parse(last_response.body))
end

def test_put_blob_uploads
put '/v2/library/test_repo/blobs/uploads/test_digest'
assert_equal 404, last_response.status
assert_equal({ "errors" => [{ "code" => "UNSUPPORTED", "message" => "Pushing content is unsupported" }] },
JSON.parse(last_response.body))
end

def test_patch_blob_uploads
put '/v2/library/test_repo/blobs/uploads/test_digest'
assert_equal 404, last_response.status
assert_equal({ "errors" => [{ "code" => "UNSUPPORTED", "message" => "Pushing content is unsupported" }] },
JSON.parse(last_response.body))
end

def test_put_repository_list
Expand Down

0 comments on commit 7f4429d

Please sign in to comment.