class Proxy::ContainerGateway::Api

rubocop:disable Metrics/ClassLength

Private Instance Methods

auth_header() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 413
def auth_header
  AuthorizationHeader.new(request.env['HTTP_AUTHORIZATION'])
end
cert_from_request() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 404
def cert_from_request
  request.env['HTTP_X_RHSM_SSL_CLIENT_CERT'] ||
    request.env['SSL_CLIENT_CERT'] ||
    request.env['HTTP_SSL_CLIENT_CERT'] ||
    ENV['HTTP_X_RHSM_SSL_CLIENT_CERT'] ||
    ENV['SSL_CLIENT_CERT'] ||
    ENV['HTTP_SSL_CLIENT_CERT']
end
flatpak_client?() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 298
def flatpak_client?
  request.user_agent&.downcase&.include?('flatpak')
end
handle_client_cert_auth(repository) click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 381
def handle_client_cert_auth(repository)
  client_cert = ::Cert::RhsmClient.new(cert_from_request) if valid_cert?
  valid_uuid = client_cert&.uuid&.present?
  if valid_uuid
    host = database.connection[:hosts][{ uuid: client_cert.uuid }]
    if host.nil?
      repo_response = ForemanApi.new.fetch_host_repositories(client_cert.uuid, request.params)
      container_gateway_main.update_host_repositories(client_cert.uuid,
                                                      JSON.parse(repo_response.body)['repositories'])
    end
    halt 401, "unauthorized" unless container_gateway_main.cert_authorized_for_repo?(repository, client_cert.uuid)
    return true
  end
  false
end
handle_repo_auth(repository, auth_header, request) click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 358
def handle_repo_auth(repository, auth_header, request)
  return if handle_client_cert_auth(repository)

  user_token_is_valid = false
  if auth_header.present? && auth_header.valid_user_token?
    user_token_is_valid = true
    username = auth_header.user[:name]
    # For flatpak client, header doesn't contain user name. Extract it from token.
    username ||= container_gateway_main.token_user(@value.split(' ')[1]) if flatpak_client?
  end
  username ||= request.params['account']

  return if container_gateway_main.authorized_for_repo?(repository, user_token_is_valid, username)

  handle_unauthorized_access(username)
end
handle_unauthorized_access(username) click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 375
def handle_unauthorized_access(username)
  redirect_authorization_headers
  halt 401, "unauthorized" if flatpak_client? && username.nil?
  throw_repo_not_found_error
end
head_or_get_blobs() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 306
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_uri = URI(pulp_response['location'])
    redirection_uri.host = URI(container_gateway_main.client_endpoint).host
    redirect(redirection_uri.to_s)
  end
end
redirect_authorization_headers() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 397
def redirect_authorization_headers
  response.headers['Docker-Distribution-API-Version'] = 'registry/2.0'
  response.headers['Www-Authenticate'] = "Bearer realm=\"https://#{request.host}/v2/token\"," \
                                         "service=\"#{request.host}\"," \
                                         "scope=\"repository:registry:pull,push\""
end
throw_repo_not_found_error() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 334
def throw_repo_not_found_error
  content_type :json
  body({
    "errors" => [
      {
        "code" => "NAME_UNKNOWN",
        "message" => "Repository name unknown"
      }
    ]
  }.to_json)
  halt 404
end
throw_unsupported_error() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 321
def throw_unsupported_error
  content_type :json
  body({
    "errors" => [
      {
        "code" => "UNSUPPORTED",
        "message" => "Pushing content is unsupported"
      }
    ]
  }.to_json)
  halt 404
end
translated_headers_for_proxy() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 347
def translated_headers_for_proxy
  current_headers = {}
  env = request.env.select do |key, _value|
    key.match("^HTTP_.*")
  end
  env.each do |header|
    current_headers[header[0].split('_')[1..].join('-')] = header[1]
  end
  current_headers
end
valid_cert?() click to toggle source
# File lib/smart_proxy_container_gateway/container_gateway_api.rb, line 302
def valid_cert?
  cert_from_request.present? && !cert_from_request.empty? && !cert_from_request.include?('null')
end