smart_proxy_container_gateway 3.1.1 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 129561beba74e2d626b09ec8236defd0d7fc01b9f2a3a55f18c8da358f9b22d7
4
- data.tar.gz: e7ad6221d17625f4dfd236ae5299a18d19b2d97f92fb13fcb1d2246394f1b48a
3
+ metadata.gz: 1965b68bd7795a23fafce6976458a33bf58f8ef67ccab714ab52edcd69558e4e
4
+ data.tar.gz: f025588bd31da08bbf6fc2bfd9b58924a4d99d86571b689f6bbfdfc2a7e458dd
5
5
  SHA512:
6
- metadata.gz: cf49a821ff8e81465ec017be198c8b7a3217a236c223a33934ee7fc3e530daf2761e628710694937609be70f5e1823065fb9ad47addc33fddd12da1fc8267468
7
- data.tar.gz: 6bd2923fcf74cdcae8ff5828ec38eeca41e29b52d759ca4b306da5bc377d1b2c07fab9180fb5acd3d2e8d88277905e4ed4852dadee9d0c24fc0564dedc92a7d9
6
+ metadata.gz: 8592a29f188ccc45ee9db74cf72579b5c63957ed4a9a64e015c7f3627bd2ee0fdf23e80efad608b690313fe5a4db28f2db0d5660a0a0a894736e500d1aa5bc78
7
+ data.tar.gz: eedefbd87696d56163aef9da0b6af8b4061bea74626054d4bf1c78b7d70425a61939db451a6081b79efdb42b17e248f1a8eaf037b5c882026bff7f5a79d87e62
@@ -41,7 +41,8 @@ module Proxy
41
41
  container_instance.singleton_dependency :container_gateway_main_impl, (lambda do
42
42
  Proxy::ContainerGateway::ContainerGatewayMain.new(
43
43
  database: container_instance.get_dependency(:database_impl),
44
- **settings.slice(:pulp_endpoint, :pulp_client_ssl_ca, :pulp_client_ssl_cert, :pulp_client_ssl_key)
44
+ **settings.slice(:pulp_endpoint, :pulp_client_ssl_ca, :pulp_client_ssl_cert,
45
+ :pulp_client_ssl_key, :client_endpoint)
45
46
  )
46
47
  end)
47
48
  end
@@ -1,6 +1,7 @@
1
1
  require 'active_support'
2
2
  require 'active_support/core_ext/integer'
3
3
  require 'active_support/core_ext/string'
4
+ require 'active_support/core_ext/object/blank'
4
5
  require 'active_support/time_with_zone'
5
6
  require 'sinatra'
6
7
  require 'smart_proxy_container_gateway/container_gateway'
@@ -45,8 +46,9 @@ module Proxy
45
46
  status pulp_response.code.to_i
46
47
  body pulp_response.body
47
48
  else
48
- redirection_location = pulp_response['location']
49
- redirect to(redirection_location)
49
+ redirection_uri = URI(pulp_response['location'])
50
+ redirection_uri.host = URI(container_gateway_main.client_endpoint).host
51
+ redirect(redirection_uri.to_s)
50
52
  end
51
53
  end
52
54
 
@@ -137,6 +139,17 @@ module Proxy
137
139
  get '/v2/token' do
138
140
  response.headers['Docker-Distribution-API-Version'] = 'registry/2.0'
139
141
 
142
+ # Flatpak client requests do not contain the account param that podman relies on.
143
+ # It contains Base64 encoded username in the Authorization header.
144
+ # We need to extract the username from the Authorization header and
145
+ # set it as the account param to be used when inserting new token record.
146
+ if flatpak_client? && auth_header.raw_header.present?
147
+ encoded_string = auth_header.raw_header&.split(' ')&.[](1)
148
+ decoded_string = Base64.decode64(encoded_string) if encoded_string.present?
149
+ username = decoded_string.split(':')[0] if decoded_string.present?
150
+ request.params['account'] ||= username if username.present?
151
+ end
152
+
140
153
  unless auth_header.present? && auth_header.basic_auth?
141
154
  return { token: AuthorizationHeader::UNAUTHORIZED_TOKEN, issued_at: Time.now.rfc3339,
142
155
  expires_in: 1.year.seconds.to_i }.to_json
@@ -164,12 +177,15 @@ module Proxy
164
177
  # 'expires_in' is an optional field. If not provided, assume 60 seconds per OAuth2 spec
165
178
  expires_in = token_response_body.fetch("expires_in", 60)
166
179
  expires_at = token_issue_time + expires_in.seconds
167
-
168
- container_gateway_main.insert_token(
169
- request.params['account'],
170
- token_response_body['token'],
171
- expires_at.rfc3339
172
- )
180
+ if request.params['account'].present?
181
+ container_gateway_main.insert_token(
182
+ request.params['account'],
183
+ token_response_body['token'],
184
+ expires_at.rfc3339
185
+ )
186
+ else
187
+ halt 401, "unauthorized"
188
+ end
173
189
 
174
190
  repo_response = ForemanApi.new.fetch_user_repositories(auth_header.raw_header, request.params)
175
191
  if repo_response.code.to_i != 200
@@ -208,6 +224,10 @@ module Proxy
208
224
 
209
225
  private
210
226
 
227
+ def flatpak_client?
228
+ request.user_agent&.downcase&.include?('flatpak')
229
+ end
230
+
211
231
  def head_or_get_blobs
212
232
  repository = params[:splat][0]
213
233
  digest = params[:splat][1]
@@ -217,8 +237,9 @@ module Proxy
217
237
  status pulp_response.code.to_i
218
238
  body pulp_response.body
219
239
  else
220
- redirection_location = pulp_response['location']
221
- redirect to(redirection_location)
240
+ redirection_uri = URI(pulp_response['location'])
241
+ redirection_uri.host = URI(container_gateway_main.client_endpoint).host
242
+ redirect(redirection_uri.to_s)
222
243
  end
223
244
  end
224
245
 
@@ -264,12 +285,21 @@ module Proxy
264
285
  if auth_header.present? && auth_header.valid_user_token?
265
286
  user_token_is_valid = true
266
287
  username = auth_header.user[:name]
288
+ # For flatpak client, header doesn't contain user name. Extract it from token.
289
+ username ||= container_gateway_main.token_user(@value.split(' ')[1]) if flatpak_client?
267
290
  end
268
291
  username = request.params['account'] if username.nil?
269
292
 
270
293
  return if container_gateway_main.authorized_for_repo?(repository, user_token_is_valid, username)
271
294
 
272
295
  redirect_authorization_headers
296
+
297
+ # If username couldn't be determined from the token or auth_headers
298
+ # which is case for first flatpak request, halt with 401 instead of 404
299
+ if flatpak_client? && username.nil?
300
+ halt 401, "unauthorized"
301
+ end
302
+
273
303
  throw_repo_not_found_error
274
304
  end
275
305
 
@@ -9,17 +9,20 @@ module Proxy
9
9
  extend ::Proxy::Log
10
10
 
11
11
  class ContainerGatewayMain
12
- attr_reader :database
12
+ attr_reader :database, :client_endpoint
13
13
 
14
- def initialize(database:, pulp_endpoint:, pulp_client_ssl_ca:, pulp_client_ssl_cert:, pulp_client_ssl_key:)
14
+ # rubocop:disable Metrics/ParameterLists, Layout/LineLength
15
+ def initialize(database:, pulp_endpoint:, pulp_client_ssl_ca:, pulp_client_ssl_cert:, pulp_client_ssl_key:, client_endpoint: nil)
15
16
  @database = database
16
17
  @pulp_endpoint = pulp_endpoint
18
+ @client_endpoint = client_endpoint || pulp_endpoint
17
19
  @pulp_client_ssl_ca = pulp_client_ssl_ca
18
20
  @pulp_client_ssl_cert = OpenSSL::X509::Certificate.new(File.read(pulp_client_ssl_cert))
19
21
  @pulp_client_ssl_key = OpenSSL::PKey::RSA.new(
20
22
  File.read(pulp_client_ssl_key)
21
23
  )
22
24
  end
25
+ # rubocop:enable Metrics/ParameterLists, Layout/LineLength
23
26
 
24
27
  def pulp_registry_request(uri, headers)
25
28
  http_client = Net::HTTP.new(uri.host, uri.port)
@@ -1,5 +1,5 @@
1
1
  module Proxy
2
2
  module ContainerGateway
3
- VERSION = '3.1.1'.freeze
3
+ VERSION = '3.3.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_container_gateway
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Ballou
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-05 00:00:00.000000000 Z
11
+ date: 2025-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport