smart_proxy_container_gateway 3.3.1 → 3.4.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 +4 -4
- data/lib/smart_proxy_container_gateway/container_gateway_api.rb +116 -9
- data/lib/smart_proxy_container_gateway/container_gateway_main.rb +94 -0
- data/lib/smart_proxy_container_gateway/foreman_api.rb +8 -2
- data/lib/smart_proxy_container_gateway/rhsm_client.rb +33 -0
- data/lib/smart_proxy_container_gateway/sequel_migrations/005_host_repositories.rb +24 -0
- data/lib/smart_proxy_container_gateway/version.rb +1 -1
- data/lib/smart_proxy_container_gateway.rb +1 -0
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 470113167c3182629d62ee7babddf775b3e99e4c21ce0df5a9716894867dad86
|
4
|
+
data.tar.gz: 7adbe20e3c0dda9a9a3704501144c5f4134c7d9c266f36b19f24e83df09ad997
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b017c8a19c575d9ddcae254500917089eef21739914b5dc73447ba39af9840679028a4401bf15fd1216ae7299b7da7f55c6200a87830d7553fd8b380bc6c821b
|
7
|
+
data.tar.gz: e37b37684d5eaace152ab018067f4fa9292a5f5663543e030ed07eba894e59d6486c6b43a0c465c11dd7de65af14599b2e54a22882ff541dd5cb45e1ae381776
|
@@ -7,9 +7,11 @@ require 'sinatra'
|
|
7
7
|
require 'smart_proxy_container_gateway/container_gateway'
|
8
8
|
require 'smart_proxy_container_gateway/container_gateway_main'
|
9
9
|
require 'smart_proxy_container_gateway/foreman_api'
|
10
|
+
require 'smart_proxy_container_gateway/rhsm_client'
|
10
11
|
|
11
12
|
module Proxy
|
12
13
|
module ContainerGateway
|
14
|
+
# rubocop:disable Metrics/ClassLength
|
13
15
|
class Api < ::Sinatra::Base
|
14
16
|
include ::Proxy::Log
|
15
17
|
helpers ::Proxy::Helpers
|
@@ -19,6 +21,35 @@ module Proxy
|
|
19
21
|
inject_attr :database_impl, :database
|
20
22
|
inject_attr :container_gateway_main_impl, :container_gateway_main
|
21
23
|
|
24
|
+
get '/index/static/?' do
|
25
|
+
client_cert = ::Cert::RhsmClient.new(cert_from_request) if valid_cert?
|
26
|
+
valid_uuid = client_cert&.uuid&.present?
|
27
|
+
|
28
|
+
pulp_response = container_gateway_main.flatpak_static_index(translated_headers_for_proxy, params)
|
29
|
+
|
30
|
+
if pulp_response.code.to_i >= 400
|
31
|
+
status pulp_response.code.to_i
|
32
|
+
body pulp_response.body
|
33
|
+
elsif valid_uuid
|
34
|
+
host = database.connection[:hosts][{ uuid: client_cert.uuid }]
|
35
|
+
if host.nil?
|
36
|
+
repo_response = ForemanApi.new.fetch_host_repositories(client_cert.uuid, request.params)
|
37
|
+
halt repo_response.code.to_i, repo_response.body unless repo_response.code.to_i == 200
|
38
|
+
container_gateway_main.update_host_repositories(client_cert.uuid,
|
39
|
+
JSON.parse(repo_response.body)['repositories'])
|
40
|
+
end
|
41
|
+
catalog = container_gateway_main.host_catalog(client_cert.uuid).select_map(::Sequel[:repositories][:name])
|
42
|
+
pulp_index = JSON.parse(pulp_response.body)
|
43
|
+
halt 400, "Error: 'Results' key is missing in pulp_index" unless pulp_index.key?("Results")
|
44
|
+
pulp_index["Results"].select! { |result| catalog.include?(result["Name"]) }
|
45
|
+
status 200
|
46
|
+
body pulp_index.to_json
|
47
|
+
else
|
48
|
+
status pulp_response.code.to_i
|
49
|
+
body pulp_response.body
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
22
53
|
get '/v1/_ping/?' do
|
23
54
|
pulp_response = container_gateway_main.ping(translated_headers_for_proxy)
|
24
55
|
status pulp_response.code.to_i
|
@@ -26,7 +57,9 @@ module Proxy
|
|
26
57
|
end
|
27
58
|
|
28
59
|
get '/v2/?' do
|
29
|
-
|
60
|
+
client_cert = ::Cert::RhsmClient.new(cert_from_request) if valid_cert?
|
61
|
+
valid_uuid = client_cert&.uuid&.present?
|
62
|
+
if valid_uuid || (auth_header.present? && (auth_header.unauthorized_token? || auth_header.valid_user_token?))
|
30
63
|
response.headers['Docker-Distribution-API-Version'] = 'registry/2.0'
|
31
64
|
pulp_response = container_gateway_main.ping(translated_headers_for_proxy)
|
32
65
|
status pulp_response.code.to_i
|
@@ -117,8 +150,17 @@ module Proxy
|
|
117
150
|
end
|
118
151
|
|
119
152
|
get '/v2/_catalog/?' do
|
153
|
+
client_cert = ::Cert::RhsmClient.new(cert_from_request) if valid_cert?
|
120
154
|
catalog = []
|
121
|
-
if
|
155
|
+
if client_cert&.uuid&.present?
|
156
|
+
host = database.connection[:hosts][{ uuid: client_cert.uuid }]
|
157
|
+
if host.nil?
|
158
|
+
repo_response = ForemanApi.new.fetch_host_repositories(client_cert.uuid, request.params)
|
159
|
+
container_gateway_main.update_host_repositories(client_cert.uuid,
|
160
|
+
JSON.parse(repo_response.body)['repositories'])
|
161
|
+
end
|
162
|
+
catalog = container_gateway_main.host_catalog(client_cert.uuid).select_map(::Sequel[:repositories][:name])
|
163
|
+
elsif auth_header.present?
|
122
164
|
if auth_header.unauthenticated_token? || auth_header.unauthorized_token?
|
123
165
|
catalog = container_gateway_main.catalog.select_map(::Sequel[:repositories][:name])
|
124
166
|
elsif auth_header.valid_user_token?
|
@@ -213,12 +255,51 @@ module Proxy
|
|
213
255
|
{}
|
214
256
|
end
|
215
257
|
|
258
|
+
put '/update_hosts/?' do
|
259
|
+
do_authorize_any
|
260
|
+
hosts = params['hosts'] || []
|
261
|
+
# Refresh hosts table
|
262
|
+
database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do
|
263
|
+
hosts_table = database.connection[:hosts]
|
264
|
+
hosts_table.delete
|
265
|
+
hosts_table.import(%i[uuid], hosts.map { |host| [host['uuid']] })
|
266
|
+
end
|
267
|
+
{}
|
268
|
+
end
|
269
|
+
|
270
|
+
put '/host_repository_mapping/?' do
|
271
|
+
do_authorize_any
|
272
|
+
container_gateway_main.update_host_repo_mapping(params)
|
273
|
+
{}
|
274
|
+
end
|
275
|
+
|
276
|
+
put '/update_host_repositories/?' do
|
277
|
+
do_authorize_any
|
278
|
+
params['hosts'].flat_map do |host_map|
|
279
|
+
host_map.filter_map do |host_uuid, repos|
|
280
|
+
if repos.nil? || repos.empty?
|
281
|
+
repo_names = []
|
282
|
+
else
|
283
|
+
repo_names = repos
|
284
|
+
.select { |repo| repo['auth_required'].to_s.downcase == "true" }
|
285
|
+
.map { |repo| repo['repository'] }
|
286
|
+
end
|
287
|
+
container_gateway_main.update_host_repositories(host_uuid, repo_names)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
{}
|
291
|
+
end
|
292
|
+
|
216
293
|
private
|
217
294
|
|
218
295
|
def flatpak_client?
|
219
296
|
request.user_agent&.downcase&.include?('flatpak')
|
220
297
|
end
|
221
298
|
|
299
|
+
def valid_cert?
|
300
|
+
cert_from_request.present? && !cert_from_request.empty? && !cert_from_request.include?('null')
|
301
|
+
end
|
302
|
+
|
222
303
|
def head_or_get_blobs
|
223
304
|
repository = params[:splat][0]
|
224
305
|
digest = params[:splat][1]
|
@@ -272,6 +353,8 @@ module Proxy
|
|
272
353
|
end
|
273
354
|
|
274
355
|
def handle_repo_auth(repository, auth_header, request)
|
356
|
+
return if handle_client_cert_auth(repository)
|
357
|
+
|
275
358
|
user_token_is_valid = false
|
276
359
|
if auth_header.present? && auth_header.valid_user_token?
|
277
360
|
user_token_is_valid = true
|
@@ -279,19 +362,33 @@ module Proxy
|
|
279
362
|
# For flatpak client, header doesn't contain user name. Extract it from token.
|
280
363
|
username ||= container_gateway_main.token_user(@value.split(' ')[1]) if flatpak_client?
|
281
364
|
end
|
282
|
-
username
|
365
|
+
username ||= request.params['account']
|
283
366
|
|
284
367
|
return if container_gateway_main.authorized_for_repo?(repository, user_token_is_valid, username)
|
285
368
|
|
369
|
+
handle_unauthorized_access(username)
|
370
|
+
end
|
371
|
+
|
372
|
+
def handle_unauthorized_access(username)
|
286
373
|
redirect_authorization_headers
|
374
|
+
halt 401, "unauthorized" if flatpak_client? && username.nil?
|
375
|
+
throw_repo_not_found_error
|
376
|
+
end
|
287
377
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
378
|
+
def handle_client_cert_auth(repository)
|
379
|
+
client_cert = ::Cert::RhsmClient.new(cert_from_request) if valid_cert?
|
380
|
+
valid_uuid = client_cert&.uuid&.present?
|
381
|
+
if valid_uuid
|
382
|
+
host = database.connection[:hosts][{ uuid: client_cert.uuid }]
|
383
|
+
if host.nil?
|
384
|
+
repo_response = ForemanApi.new.fetch_host_repositories(client_cert.uuid, request.params)
|
385
|
+
container_gateway_main.update_host_repositories(client_cert.uuid,
|
386
|
+
JSON.parse(repo_response.body)['repositories'])
|
387
|
+
end
|
388
|
+
halt 401, "unauthorized" unless container_gateway_main.cert_authorized_for_repo?(repository, client_cert.uuid)
|
389
|
+
return true
|
292
390
|
end
|
293
|
-
|
294
|
-
throw_repo_not_found_error
|
391
|
+
false
|
295
392
|
end
|
296
393
|
|
297
394
|
def redirect_authorization_headers
|
@@ -301,6 +398,15 @@ module Proxy
|
|
301
398
|
"scope=\"repository:registry:pull,push\""
|
302
399
|
end
|
303
400
|
|
401
|
+
def cert_from_request
|
402
|
+
request.env['HTTP_X_RHSM_SSL_CLIENT_CERT'] ||
|
403
|
+
request.env['SSL_CLIENT_CERT'] ||
|
404
|
+
request.env['HTTP_SSL_CLIENT_CERT'] ||
|
405
|
+
ENV['HTTP_X_RHSM_SSL_CLIENT_CERT'] ||
|
406
|
+
ENV['SSL_CLIENT_CERT'] ||
|
407
|
+
ENV['HTTP_SSL_CLIENT_CERT']
|
408
|
+
end
|
409
|
+
|
304
410
|
def auth_header
|
305
411
|
AuthorizationHeader.new(request.env['HTTP_AUTHORIZATION'])
|
306
412
|
end
|
@@ -363,5 +469,6 @@ module Proxy
|
|
363
469
|
end
|
364
470
|
end
|
365
471
|
end
|
472
|
+
# rubocop:enable Metrics/ClassLength
|
366
473
|
end
|
367
474
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'uri'
|
3
3
|
require 'digest'
|
4
|
+
require 'erb'
|
4
5
|
require 'smart_proxy_container_gateway/dependency_injection'
|
5
6
|
require 'sequel'
|
6
7
|
module Proxy
|
@@ -40,6 +41,14 @@ module Proxy
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
44
|
+
def flatpak_static_index(headers, params = {})
|
45
|
+
uri = URI.parse("#{@pulp_endpoint}/pulpcore_registry/index/static")
|
46
|
+
unless params.empty?
|
47
|
+
uri.query = params.map { |k, v| "#{ERB::Util.url_encode(k.to_s)}=#{ERB::Util.url_encode(v.to_s)}" }.join('&')
|
48
|
+
end
|
49
|
+
pulp_registry_request(uri, headers)
|
50
|
+
end
|
51
|
+
|
43
52
|
def ping(headers)
|
44
53
|
uri = URI.parse("#{@pulp_endpoint}/pulpcore_registry/v2/")
|
45
54
|
pulp_registry_request(uri, headers)
|
@@ -101,6 +110,17 @@ module Proxy
|
|
101
110
|
end
|
102
111
|
end
|
103
112
|
|
113
|
+
def host_catalog(host_uuid = nil)
|
114
|
+
if host_uuid.nil?
|
115
|
+
unauthenticated_repos
|
116
|
+
else
|
117
|
+
database.connection[:repositories].
|
118
|
+
left_join(:hosts_repositories, repository_id: :id).
|
119
|
+
left_join(:hosts, ::Sequel[:hosts][:id] => :host_id).where(uuid: host_uuid).
|
120
|
+
or(Sequel[:repositories][:auth_required] => false).order(::Sequel[:repositories][:name])
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
104
124
|
def unauthenticated_repos
|
105
125
|
database.connection[:repositories].where(auth_required: false).order(:name)
|
106
126
|
end
|
@@ -163,6 +183,66 @@ module Proxy
|
|
163
183
|
end
|
164
184
|
end
|
165
185
|
|
186
|
+
# Replaces the entire host-repo mapping for all hosts.
|
187
|
+
# Assumes host is present in the DB.
|
188
|
+
def update_host_repo_mapping(host_repo_maps)
|
189
|
+
# Get DB tables
|
190
|
+
hosts_repositories = database.connection[:hosts_repositories]
|
191
|
+
|
192
|
+
# Build list of [repository_id, host_id] pairs
|
193
|
+
entries = build_host_repository_mapping(host_repo_maps)
|
194
|
+
|
195
|
+
# Insert all in a single transaction
|
196
|
+
database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do
|
197
|
+
hosts_repositories.delete
|
198
|
+
hosts_repositories.import(%i[repository_id host_id], entries)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def build_host_repository_mapping(host_repo_maps)
|
203
|
+
hosts = database.connection[:hosts]
|
204
|
+
repositories = database.connection[:repositories]
|
205
|
+
entries = host_repo_maps['hosts'].flat_map do |host_map|
|
206
|
+
host_map.filter_map do |host_uuid, repos|
|
207
|
+
host = hosts[{ uuid: host_uuid }]
|
208
|
+
next unless host
|
209
|
+
|
210
|
+
repo_names = repos
|
211
|
+
.select { |repo| repo['auth_required'].to_s.downcase == "true" }
|
212
|
+
.map { |repo| repo['repository'] }
|
213
|
+
|
214
|
+
repositories
|
215
|
+
.where(name: repo_names, auth_required: true)
|
216
|
+
.select(:id)
|
217
|
+
.map { |repo| [repo[:id], host[:id]] }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
entries.flatten!(1)
|
221
|
+
end
|
222
|
+
|
223
|
+
def update_host_repositories(uuid, repositories)
|
224
|
+
host = find_or_create_host(uuid)
|
225
|
+
hosts_repositories = database.connection[:hosts_repositories]
|
226
|
+
database.connection.transaction(isolation: :serializable,
|
227
|
+
retry_on: [Sequel::SerializationFailure],
|
228
|
+
num_retries: 10) do
|
229
|
+
hosts_repositories.where(host_id: host[:id]).delete
|
230
|
+
return if repositories.nil? || repositories.empty?
|
231
|
+
|
232
|
+
hosts_repositories.import(
|
233
|
+
%i[repository_id host_id],
|
234
|
+
database.connection[:repositories].where(name: repositories, auth_required: true).select(:id).map do |repo|
|
235
|
+
[repo[:id], host[:id]]
|
236
|
+
end
|
237
|
+
)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def find_or_create_host(uuid)
|
242
|
+
database.connection[:hosts].insert_conflict(target: :uuid, action: :ignore).insert(uuid: uuid)
|
243
|
+
database.connection[:hosts][{ uuid: uuid }]
|
244
|
+
end
|
245
|
+
|
166
246
|
# Returns:
|
167
247
|
# true if the user is authorized to access the repo, or
|
168
248
|
# false if the user is not authorized to access the repo or if it does not exist
|
@@ -185,6 +265,20 @@ module Proxy
|
|
185
265
|
false
|
186
266
|
end
|
187
267
|
|
268
|
+
def cert_authorized_for_repo?(repo_name, uuid)
|
269
|
+
database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do
|
270
|
+
repository = database.connection[:repositories][{ name: repo_name }]
|
271
|
+
return false if repository.nil?
|
272
|
+
return true unless repository[:auth_required]
|
273
|
+
|
274
|
+
database.connection[:hosts_repositories]
|
275
|
+
.where(repository_id: repository[:id])
|
276
|
+
.join(:hosts, id: :host_id)
|
277
|
+
.where(Sequel[:hosts][:uuid] => uuid)
|
278
|
+
.any?
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
188
282
|
def token_user(token)
|
189
283
|
database.connection[:users][{
|
190
284
|
id: database.connection[:authentication_tokens].where(token_checksum: checksum(token)).select(:user_id)
|
@@ -1,15 +1,17 @@
|
|
1
1
|
require 'uri'
|
2
|
+
require 'openssl'
|
2
3
|
|
3
4
|
module Proxy
|
4
5
|
module ContainerGateway
|
5
6
|
class ForemanApi
|
6
|
-
def registry_request(auth_header, params, suffix)
|
7
|
+
def registry_request(auth_header, params, suffix, uuid: '', cert: false)
|
7
8
|
uri = URI.join(Proxy::SETTINGS.foreman_url, Proxy::ContainerGateway::Plugin.settings.katello_registry_path, suffix)
|
8
9
|
uri.query = process_params(params)
|
9
10
|
|
10
11
|
req = Net::HTTP::Get.new(uri)
|
11
|
-
req.add_field('Authorization', auth_header)
|
12
|
+
req.add_field('Authorization', auth_header) unless cert
|
12
13
|
req.add_field('Accept', 'application/json')
|
14
|
+
req.add_field('HostUUID', uuid) if cert
|
13
15
|
req.content_type = 'application/json'
|
14
16
|
http = Net::HTTP.new(uri.hostname, uri.port)
|
15
17
|
http.use_ssl = true
|
@@ -29,6 +31,10 @@ module Proxy
|
|
29
31
|
def fetch_user_repositories(auth_header, params)
|
30
32
|
registry_request(auth_header, params, '_catalog')
|
31
33
|
end
|
34
|
+
|
35
|
+
def fetch_host_repositories(uuid, params)
|
36
|
+
registry_request(nil, params, '_catalog', uuid: uuid, cert: true)
|
37
|
+
end
|
32
38
|
end
|
33
39
|
end
|
34
40
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Cert
|
5
|
+
class RhsmClient
|
6
|
+
attr_accessor :cert
|
7
|
+
|
8
|
+
def initialize(cert)
|
9
|
+
self.cert = extract(cert)
|
10
|
+
end
|
11
|
+
|
12
|
+
def uuid
|
13
|
+
@uuid ||= @cert.subject.to_a.find { |entry| entry[0] == 'CN' }&.[](1)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def extract(cert)
|
19
|
+
raise('Invalid cert provided. Ensure that the provided cert is not empty.') if cert.empty?
|
20
|
+
|
21
|
+
cert = strip_cert(cert)
|
22
|
+
cert = Base64.decode64(cert)
|
23
|
+
OpenSSL::X509::Certificate.new(cert)
|
24
|
+
end
|
25
|
+
|
26
|
+
def strip_cert(cert)
|
27
|
+
cert = cert.to_s.gsub("-----BEGIN CERTIFICATE-----", "").gsub("-----END CERTIFICATE-----", "")
|
28
|
+
cert.delete!(' ')
|
29
|
+
cert.delete!("\n")
|
30
|
+
cert
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Sequel.migration do
|
2
|
+
up do
|
3
|
+
# Create the hosts table
|
4
|
+
create_table(:hosts) do
|
5
|
+
primary_key :id
|
6
|
+
String :uuid, null: false, unique: true
|
7
|
+
end
|
8
|
+
|
9
|
+
# Create the hosts_repositories join table
|
10
|
+
create_table(:hosts_repositories) do
|
11
|
+
foreign_key :host_id, :hosts, on_delete: :cascade
|
12
|
+
foreign_key :repository_id, :repositories, on_delete: :cascade
|
13
|
+
primary_key %i[host_id repository_id]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
down do
|
18
|
+
# Drop the hosts_repositories join table
|
19
|
+
drop_table(:hosts_repositories)
|
20
|
+
|
21
|
+
# Drop the hosts table
|
22
|
+
drop_table(:hosts)
|
23
|
+
end
|
24
|
+
end
|
@@ -2,3 +2,4 @@ require 'smart_proxy_container_gateway/version'
|
|
2
2
|
require 'smart_proxy_container_gateway/database'
|
3
3
|
require 'smart_proxy_container_gateway/container_gateway'
|
4
4
|
require 'smart_proxy_container_gateway/container_gateway_main'
|
5
|
+
require 'smart_proxy_container_gateway/rhsm_client'
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_proxy_container_gateway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Ballou
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: activesupport
|
@@ -77,8 +76,8 @@ email: ianballou67@gmail.com
|
|
77
76
|
executables: []
|
78
77
|
extensions: []
|
79
78
|
extra_rdoc_files:
|
80
|
-
- README.md
|
81
79
|
- LICENSE
|
80
|
+
- README.md
|
82
81
|
files:
|
83
82
|
- LICENSE
|
84
83
|
- README.md
|
@@ -91,17 +90,18 @@ files:
|
|
91
90
|
- lib/smart_proxy_container_gateway/database.rb
|
92
91
|
- lib/smart_proxy_container_gateway/dependency_injection.rb
|
93
92
|
- lib/smart_proxy_container_gateway/foreman_api.rb
|
93
|
+
- lib/smart_proxy_container_gateway/rhsm_client.rb
|
94
94
|
- lib/smart_proxy_container_gateway/sequel_migrations/001_initial.rb
|
95
95
|
- lib/smart_proxy_container_gateway/sequel_migrations/002_auth_tokens.rb
|
96
96
|
- lib/smart_proxy_container_gateway/sequel_migrations/003_authorization_reorg.rb
|
97
97
|
- lib/smart_proxy_container_gateway/sequel_migrations/004_users_repositories_cascade_delete.rb
|
98
|
+
- lib/smart_proxy_container_gateway/sequel_migrations/005_host_repositories.rb
|
98
99
|
- lib/smart_proxy_container_gateway/version.rb
|
99
100
|
- settings.d/container_gateway.yml.example
|
100
101
|
homepage: https://github.com/Katello/smart_proxy_container_gateway
|
101
102
|
licenses:
|
102
103
|
- GPL-3.0-only
|
103
104
|
metadata: {}
|
104
|
-
post_install_message:
|
105
105
|
rdoc_options: []
|
106
106
|
require_paths:
|
107
107
|
- lib
|
@@ -116,8 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
requirements: []
|
119
|
-
rubygems_version: 3.
|
120
|
-
signing_key:
|
119
|
+
rubygems_version: 3.6.7
|
121
120
|
specification_version: 4
|
122
121
|
summary: Pulp 3 container registry support for Foreman/Katello Smart-Proxy
|
123
122
|
test_files: []
|