smart_proxy_container_gateway 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -3
- data/lib/smart_proxy_container_gateway/container_gateway.rb +10 -6
- data/lib/smart_proxy_container_gateway/container_gateway_api.rb +36 -8
- data/lib/smart_proxy_container_gateway/container_gateway_main.rb +19 -14
- data/lib/smart_proxy_container_gateway/database.rb +7 -14
- data/lib/smart_proxy_container_gateway/version.rb +1 -1
- data/settings.d/container_gateway.yml.example +13 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb4e40d814ff330008ad5f1bf4bf667ba9e91415bc997ea4d66a2beb7fb0a00e
|
4
|
+
data.tar.gz: 84360d1228198e91460a2b841985b12c5c9f5d5d062d191862a2e9cc5bef10e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37997d8de598e480912ecc0785fc755138aa90163dcb20981210eff4a935ae85a49a157b8c51189a6a13a6a29a1ff391429e477257d466b0b9d0d19d04d33fcd
|
7
|
+
data.tar.gz: 5a81a246030ed8d9fcd7b847c30fb241c2974e203ae09b256a017432cffa549073430a203e5d6231f55527db005237477a4903482c88ddad47e4c2ca894f8def
|
data/README.md
CHANGED
@@ -38,9 +38,8 @@ The Container Gateway plugin requires a Pulp 3 instance to connect to. Related
|
|
38
38
|
SQLite and PostgreSQL are supported, with SQLite being the default for development and testing.
|
39
39
|
Use PostgreSQL in production for improved performance by adding the following settings:
|
40
40
|
```
|
41
|
-
# Example PostgreSQL connection settings
|
42
|
-
:
|
43
|
-
:postgresql_connection_string: postgres://foreman-proxy:changeme@localhost:5432/container_gateway
|
41
|
+
# Example PostgreSQL connection settings, using UNIX socket and ident auth
|
42
|
+
:db_connection_string: postgres:///container_gateway
|
44
43
|
```
|
45
44
|
|
46
45
|
When switching from SQLite to PostgreSQL, if the PostgreSQL database is empty, the SQLite database will be automatically migrated to PostgreSQL.
|
@@ -7,8 +7,6 @@ module Proxy
|
|
7
7
|
|
8
8
|
default_settings :pulp_endpoint => "https://#{`hostname`.strip}",
|
9
9
|
:katello_registry_path => '/v2/',
|
10
|
-
:database_backend => 'sqlite',
|
11
|
-
:sqlite_db_path => '/var/lib/foreman-proxy/smart_proxy_container_gateway.db',
|
12
10
|
:sqlite_timeout => 30_000
|
13
11
|
|
14
12
|
# Load defaults that copy values from SETTINGS. This is done as
|
@@ -29,10 +27,16 @@ module Proxy
|
|
29
27
|
|
30
28
|
load_dependency_injection_wirings do |container_instance, settings|
|
31
29
|
container_instance.singleton_dependency :database_impl, (lambda do
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
connection_string = settings.fetch(:db_connection_string) do
|
31
|
+
unless settings[:sqlite_db_path]
|
32
|
+
raise ValueError, 'Missing db_connection_string or sqlite_db_path option'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Legacy setup
|
36
|
+
"sqlite://#{settings[:sqlite_db_path]}?timeout=#{settings[:sqlite_timeout]}"
|
37
|
+
end
|
38
|
+
|
39
|
+
Proxy::ContainerGateway::Database.new(connection_string, settings[:sqlite_db_path])
|
36
40
|
end)
|
37
41
|
container_instance.singleton_dependency :container_gateway_main_impl, (lambda do
|
38
42
|
Proxy::ContainerGateway::ContainerGatewayMain.new(
|
@@ -19,13 +19,17 @@ module Proxy
|
|
19
19
|
inject_attr :container_gateway_main_impl, :container_gateway_main
|
20
20
|
|
21
21
|
get '/v1/_ping/?' do
|
22
|
-
container_gateway_main.ping
|
22
|
+
pulp_response = container_gateway_main.ping(translated_headers_for_proxy)
|
23
|
+
status pulp_response.code.to_i
|
24
|
+
body pulp_response.body
|
23
25
|
end
|
24
26
|
|
25
27
|
get '/v2/?' do
|
26
28
|
if auth_header.present? && (auth_header.unauthorized_token? || auth_header.valid_user_token?)
|
27
29
|
response.headers['Docker-Distribution-API-Version'] = 'registry/2.0'
|
28
|
-
container_gateway_main.ping
|
30
|
+
pulp_response = container_gateway_main.ping(translated_headers_for_proxy)
|
31
|
+
status pulp_response.code.to_i
|
32
|
+
body pulp_response.body
|
29
33
|
else
|
30
34
|
redirect_authorization_headers
|
31
35
|
halt 401, "unauthorized"
|
@@ -36,22 +40,34 @@ module Proxy
|
|
36
40
|
repository = params[:splat][0]
|
37
41
|
tag = params[:splat][1]
|
38
42
|
handle_repo_auth(repository, auth_header, request)
|
39
|
-
|
40
|
-
|
43
|
+
pulp_response = container_gateway_main.manifests(repository, tag, translated_headers_for_proxy)
|
44
|
+
if pulp_response.code.to_i >= 400
|
45
|
+
status pulp_response.code.to_i
|
46
|
+
body pulp_response.body
|
47
|
+
else
|
48
|
+
redirection_location = pulp_response['location']
|
49
|
+
redirect to(redirection_location)
|
50
|
+
end
|
41
51
|
end
|
42
52
|
|
43
53
|
get '/v2/*/blobs/*/?' do
|
44
54
|
repository = params[:splat][0]
|
45
55
|
digest = params[:splat][1]
|
46
56
|
handle_repo_auth(repository, auth_header, request)
|
47
|
-
|
48
|
-
|
57
|
+
pulp_response = container_gateway_main.blobs(repository, digest, translated_headers_for_proxy)
|
58
|
+
if pulp_response.code.to_i >= 400
|
59
|
+
status pulp_response.code.to_i
|
60
|
+
body pulp_response.body
|
61
|
+
else
|
62
|
+
redirection_location = pulp_response['location']
|
63
|
+
redirect to(redirection_location)
|
64
|
+
end
|
49
65
|
end
|
50
66
|
|
51
67
|
get '/v2/*/tags/list/?' do
|
52
68
|
repository = params[:splat][0]
|
53
69
|
handle_repo_auth(repository, auth_header, request)
|
54
|
-
pulp_response = container_gateway_main.tags(repository, params)
|
70
|
+
pulp_response = container_gateway_main.tags(repository, translated_headers_for_proxy, params)
|
55
71
|
# "link"=>["<http://pulpcore-api/v2/container-image-name/tags/list?n=100&last=last-tag-name>; rel=\"next\""],
|
56
72
|
# https://docs.docker.com/registry/spec/api/#pagination-1
|
57
73
|
if pulp_response['link'].nil?
|
@@ -59,7 +75,8 @@ module Proxy
|
|
59
75
|
else
|
60
76
|
headers['link'] = pulp_response['link']
|
61
77
|
end
|
62
|
-
pulp_response.
|
78
|
+
status pulp_response.code.to_i
|
79
|
+
body pulp_response.body
|
63
80
|
end
|
64
81
|
|
65
82
|
get '/v1/search/?' do
|
@@ -181,6 +198,17 @@ module Proxy
|
|
181
198
|
|
182
199
|
private
|
183
200
|
|
201
|
+
def translated_headers_for_proxy
|
202
|
+
current_headers = {}
|
203
|
+
env = request.env.select do |key, _value|
|
204
|
+
key.match("^HTTP_.*")
|
205
|
+
end
|
206
|
+
env.each do |header|
|
207
|
+
current_headers[header[0].split('_')[1..].join('-')] = header[1]
|
208
|
+
end
|
209
|
+
current_headers
|
210
|
+
end
|
211
|
+
|
184
212
|
def handle_repo_auth(repository, auth_header, request)
|
185
213
|
user_token_is_valid = false
|
186
214
|
if auth_header.present? && auth_header.valid_user_token?
|
@@ -21,7 +21,7 @@ module Proxy
|
|
21
21
|
)
|
22
22
|
end
|
23
23
|
|
24
|
-
def pulp_registry_request(uri)
|
24
|
+
def pulp_registry_request(uri, headers)
|
25
25
|
http_client = Net::HTTP.new(uri.host, uri.port)
|
26
26
|
http_client.ca_file = @pulp_client_ssl_ca
|
27
27
|
http_client.cert = @pulp_client_ssl_cert
|
@@ -30,30 +30,33 @@ module Proxy
|
|
30
30
|
|
31
31
|
http_client.start do |http|
|
32
32
|
request = Net::HTTP::Get.new uri
|
33
|
+
headers.each do |key, value|
|
34
|
+
request[key] = value
|
35
|
+
end
|
33
36
|
http.request request
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
37
|
-
def ping
|
40
|
+
def ping(headers)
|
38
41
|
uri = URI.parse("#{@pulp_endpoint}/pulpcore_registry/v2/")
|
39
|
-
pulp_registry_request(uri)
|
42
|
+
pulp_registry_request(uri, headers)
|
40
43
|
end
|
41
44
|
|
42
|
-
def manifests(repository, tag)
|
45
|
+
def manifests(repository, tag, headers)
|
43
46
|
uri = URI.parse(
|
44
47
|
"#{@pulp_endpoint}/pulpcore_registry/v2/#{repository}/manifests/#{tag}"
|
45
48
|
)
|
46
|
-
pulp_registry_request(uri)
|
49
|
+
pulp_registry_request(uri, headers)
|
47
50
|
end
|
48
51
|
|
49
|
-
def blobs(repository, digest)
|
52
|
+
def blobs(repository, digest, headers)
|
50
53
|
uri = URI.parse(
|
51
54
|
"#{@pulp_endpoint}/pulpcore_registry/v2/#{repository}/blobs/#{digest}"
|
52
55
|
)
|
53
|
-
pulp_registry_request(uri)
|
56
|
+
pulp_registry_request(uri, headers)
|
54
57
|
end
|
55
58
|
|
56
|
-
def tags(repository, params = {})
|
59
|
+
def tags(repository, headers, params = {})
|
57
60
|
query = "?"
|
58
61
|
unless params[:n].nil? || params[:n] == ""
|
59
62
|
query = "#{query}n=#{params[:n]}"
|
@@ -64,7 +67,7 @@ module Proxy
|
|
64
67
|
uri = URI.parse(
|
65
68
|
"#{@pulp_endpoint}/pulpcore_registry/v2/#{repository}/tags/list#{query}"
|
66
69
|
)
|
67
|
-
pulp_registry_request(uri)
|
70
|
+
pulp_registry_request(uri, headers)
|
68
71
|
end
|
69
72
|
|
70
73
|
def v1_search(params = {})
|
@@ -192,12 +195,14 @@ module Proxy
|
|
192
195
|
checksum = Digest::SHA256.hexdigest(token)
|
193
196
|
user = Sequel::Model(database.connection[:users]).find_or_create(name: username)
|
194
197
|
|
195
|
-
database.connection
|
196
|
-
|
197
|
-
|
198
|
-
|
198
|
+
database.connection.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do
|
199
|
+
database.connection[:authentication_tokens].where(:token_checksum => checksum).delete
|
200
|
+
Sequel::Model(database.connection[:authentication_tokens]).
|
201
|
+
create(token_checksum: checksum, expire_at: expire_at_string.to_s, user_id: user.id)
|
202
|
+
return unless clear_expired_tokens
|
199
203
|
|
200
|
-
|
204
|
+
database.connection[:authentication_tokens].where { expire_at < Sequel::CURRENT_TIMESTAMP }.delete
|
205
|
+
end
|
201
206
|
end
|
202
207
|
|
203
208
|
private
|
@@ -4,22 +4,15 @@ module Proxy
|
|
4
4
|
class Database
|
5
5
|
attr_reader :connection
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
|
9
|
-
|
7
|
+
def initialize(connection_string, prior_sqlite_db_path = nil)
|
8
|
+
@connection = Sequel.connect(connection_string)
|
9
|
+
if connection_string.start_with?('sqlite://')
|
10
10
|
@connection.run("PRAGMA foreign_keys = ON;")
|
11
11
|
@connection.run("PRAGMA journal_mode = wal;")
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@connection = Sequel.connect(options[:postgresql_connection_string])
|
18
|
-
if File.exist?(options[:sqlite_db_path]) &&
|
19
|
-
(!@connection.table_exists?(:repositories) || @connection[:repositories].count.zero?)
|
20
|
-
migrate_to_postgres(Sequel.sqlite(options[:sqlite_db_path]), @connection)
|
21
|
-
File.delete(options[:sqlite_db_path])
|
22
|
-
end
|
12
|
+
elsif prior_sqlite_db_path && File.exist?(prior_sqlite_db_path) &&
|
13
|
+
(!@connection.table_exists?(:repositories) || @connection[:repositories].count.zero?)
|
14
|
+
migrate_to_postgres(Sequel.sqlite(prior_sqlite_db_path), @connection)
|
15
|
+
File.delete(prior_sqlite_db_path)
|
23
16
|
end
|
24
17
|
migrate
|
25
18
|
end
|
@@ -1,10 +1,16 @@
|
|
1
1
|
---
|
2
2
|
:enabled: true
|
3
|
-
|
4
|
-
:
|
5
|
-
:
|
6
|
-
:
|
7
|
-
:
|
8
|
-
|
3
|
+
|
4
|
+
#:pulp_endpoint: 'https://pulp3.example.com'
|
5
|
+
#:pulp_client_ssl_ca: '/path/to/ca.pem'
|
6
|
+
#:pulp_client_ssl_cert: '/path/to/cert.pem'
|
7
|
+
#:pulp_client_ssl_key: '/path/to/key.pem'
|
8
|
+
|
9
|
+
#:katello_registry_path: '/v2/'
|
10
|
+
|
11
|
+
#:db_connection_string: postgresql:///container_gateway
|
12
|
+
|
13
|
+
# Legacy options
|
14
|
+
#:sqlite_db_path: '/var/lib/foreman-proxy/smart_proxy_container_gateway.db'
|
9
15
|
# Database busy timeout in milliseconds
|
10
|
-
|
16
|
+
#:sqlite_timeout: 30000
|
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:
|
4
|
+
version: 3.0.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-
|
11
|
+
date: 2024-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|