smart_proxy_container_gateway 1.0.0 → 1.0.5
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 +5 -5
- data/lib/smart_proxy_container_gateway/container_gateway.rb +15 -4
- data/lib/smart_proxy_container_gateway/container_gateway_api.rb +89 -32
- data/lib/smart_proxy_container_gateway/container_gateway_main.rb +102 -25
- data/lib/smart_proxy_container_gateway/foreman_api.rb +13 -5
- data/lib/smart_proxy_container_gateway/sequel_migrations/003_authorization_reorg.rb +65 -0
- data/lib/smart_proxy_container_gateway/version.rb +1 -1
- data/settings.d/container_gateway.yml.example +2 -0
- metadata +17 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f7f64eda929055e1dbf8e33f6f25797f5f01eaec99fc44c68b48cdbb54e3ac24
|
4
|
+
data.tar.gz: 3b82489df2523cc112474f8f88925959123db0ea34848462dcaa3a15aa2f01f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7275b37d4d4e2de7be47377f45790277df201752f429a3d1bea719a7f644b9a59e7b39a312f75d4b6c75d66c2ada8a21970cab2b6ee665ee11c45dfd739d2905
|
7
|
+
data.tar.gz: 0f12062658a3840ddccb627e1e2ef2602e3e53b03b218684ff2f6a733504107a49329237d56f6a0b5ed6669509b422622459f84dc2c66484ddb99f5ec10bfa71
|
@@ -9,10 +9,21 @@ module Proxy
|
|
9
9
|
:katello_registry_path => '/v2/',
|
10
10
|
:sqlite_db_path => '/var/lib/foreman-proxy/smart_proxy_container_gateway.db'
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# Load defaults that copy values from SETTINGS. This is done as
|
13
|
+
# programmable settings since SETTINGS isn't initialized during plugin
|
14
|
+
# loading.
|
15
|
+
load_programmable_settings do |settings|
|
16
|
+
settings[:pulp_client_ssl_ca] ||= SETTINGS.foreman_ssl_ca
|
17
|
+
settings[:pulp_client_ssl_cert] ||= SETTINGS.foreman_ssl_cert
|
18
|
+
settings[:pulp_client_ssl_key] ||= SETTINGS.foreman_ssl_key
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO: sqlite_db_path should able be readable or creatable. There's no
|
22
|
+
# test for creatable
|
23
|
+
validate_readable :pulp_client_ssl_ca, :pulp_client_ssl_cert, :pulp_client_ssl_key
|
24
|
+
validate :pulp_endpoint, url: true
|
25
|
+
|
26
|
+
rackup_path File.join(__dir__, 'container_gateway_http_config.ru')
|
16
27
|
end
|
17
28
|
end
|
18
29
|
end
|
@@ -2,7 +2,6 @@ require 'sinatra'
|
|
2
2
|
require 'smart_proxy_container_gateway/container_gateway'
|
3
3
|
require 'smart_proxy_container_gateway/container_gateway_main'
|
4
4
|
require 'smart_proxy_container_gateway/foreman_api'
|
5
|
-
require 'sequel'
|
6
5
|
require 'sqlite3'
|
7
6
|
|
8
7
|
module Proxy
|
@@ -10,7 +9,7 @@ module Proxy
|
|
10
9
|
class Api < ::Sinatra::Base
|
11
10
|
include ::Proxy::Log
|
12
11
|
helpers ::Proxy::Helpers
|
13
|
-
|
12
|
+
helpers ::Sinatra::Authorization::Helpers
|
14
13
|
|
15
14
|
get '/v1/_ping/?' do
|
16
15
|
Proxy::ContainerGateway.ping
|
@@ -18,6 +17,7 @@ module Proxy
|
|
18
17
|
|
19
18
|
get '/v2/?' do
|
20
19
|
if auth_header.present? && (auth_header.unauthorized_token? || auth_header.valid_user_token?)
|
20
|
+
response.headers['Docker-Distribution-API-Version'] = 'registry/2.0'
|
21
21
|
Proxy::ContainerGateway.ping
|
22
22
|
else
|
23
23
|
redirect_authorization_headers
|
@@ -26,31 +26,32 @@ module Proxy
|
|
26
26
|
end
|
27
27
|
|
28
28
|
get '/v2/:repository/manifests/:tag/?' do
|
29
|
-
|
30
|
-
redirect_authorization_headers
|
31
|
-
halt 401, "unauthorized"
|
32
|
-
end
|
29
|
+
handle_repo_auth(params, auth_header, request)
|
33
30
|
redirection_location = Proxy::ContainerGateway.manifests(params[:repository], params[:tag])
|
34
31
|
redirect to(redirection_location)
|
35
32
|
end
|
36
33
|
|
37
34
|
get '/v2/:repository/blobs/:digest/?' do
|
38
|
-
|
39
|
-
redirect_authorization_headers
|
40
|
-
halt 401, "unauthorized"
|
41
|
-
end
|
35
|
+
handle_repo_auth(params, auth_header, request)
|
42
36
|
redirection_location = Proxy::ContainerGateway.blobs(params[:repository], params[:digest])
|
43
37
|
redirect to(redirection_location)
|
44
38
|
end
|
45
39
|
|
46
40
|
get '/v1/search/?' do
|
47
41
|
# Checks for podman client and issues a 404 in that case. Podman
|
48
|
-
# examines the response from a /
|
42
|
+
# examines the response from a /v1/search request. If the result
|
49
43
|
# is a 4XX, it will then proceed with a request to /_catalog
|
50
44
|
if !request.env['HTTP_USER_AGENT'].nil? && request.env['HTTP_USER_AGENT'].downcase.include?('libpod')
|
51
45
|
halt 404, "not found"
|
52
46
|
end
|
53
47
|
|
48
|
+
if auth_header.present? && !auth_header.blank?
|
49
|
+
username = auth_header.v1_foreman_authorized_username
|
50
|
+
if username.nil?
|
51
|
+
halt 401, "unauthorized"
|
52
|
+
end
|
53
|
+
params[:user] = username
|
54
|
+
end
|
54
55
|
repositories = Proxy::ContainerGateway.v1_search(params)
|
55
56
|
|
56
57
|
content_type :json
|
@@ -58,13 +59,23 @@ module Proxy
|
|
58
59
|
end
|
59
60
|
|
60
61
|
get '/v2/_catalog/?' do
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
catalog = []
|
63
|
+
if auth_header.present?
|
64
|
+
if auth_header.unauthorized_token?
|
65
|
+
catalog = Proxy::ContainerGateway.catalog
|
66
|
+
elsif auth_header.valid_user_token?
|
67
|
+
catalog = Proxy::ContainerGateway.catalog(auth_header.user)
|
68
|
+
else
|
69
|
+
redirect_authorization_headers
|
70
|
+
halt 401, "unauthorized"
|
71
|
+
end
|
72
|
+
else
|
73
|
+
redirect_authorization_headers
|
74
|
+
halt 401, "unauthorized"
|
75
|
+
end
|
64
76
|
|
65
|
-
get '/v2/unauthenticated_repository_list/?' do
|
66
77
|
content_type :json
|
67
|
-
{ repositories:
|
78
|
+
{ repositories: catalog }.to_json
|
68
79
|
end
|
69
80
|
|
70
81
|
get '/v2/token' do
|
@@ -72,8 +83,8 @@ module Proxy
|
|
72
83
|
|
73
84
|
unless auth_header.present? && auth_header.basic_auth?
|
74
85
|
one_year = (60 * 60 * 24 * 365)
|
75
|
-
return { token: AuthorizationHeader::UNAUTHORIZED_TOKEN, issued_at: Time.now,
|
76
|
-
expires_at: Time.now + one_year }.to_json
|
86
|
+
return { token: AuthorizationHeader::UNAUTHORIZED_TOKEN, issued_at: Time.now.iso8601,
|
87
|
+
expires_at: (Time.now + one_year).iso8601 }.to_json
|
77
88
|
end
|
78
89
|
|
79
90
|
token_response = ForemanApi.new.fetch_token(auth_header.raw_header, request.params)
|
@@ -83,28 +94,57 @@ expires_at: Time.now + one_year }.to_json
|
|
83
94
|
token_response_body = JSON.parse(token_response.body)
|
84
95
|
ContainerGateway.insert_token(request.params['account'], token_response_body['token'],
|
85
96
|
token_response_body['expires_at'])
|
97
|
+
|
98
|
+
repo_response = ForemanApi.new.fetch_user_repositories(auth_header.raw_header, request.params)
|
99
|
+
if repo_response.code.to_i != 200
|
100
|
+
halt repo_response.code.to_i, repo_response.body
|
101
|
+
else
|
102
|
+
ContainerGateway.update_user_repositories(request.params['account'],
|
103
|
+
JSON.parse(repo_response.body)['repositories'])
|
104
|
+
end
|
86
105
|
return token_response_body.to_json
|
87
106
|
end
|
88
107
|
end
|
89
108
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
109
|
+
get '/users/?' do
|
110
|
+
do_authorize_any
|
111
|
+
|
112
|
+
content_type :json
|
113
|
+
{ users: User.map(:name) }.to_json
|
114
|
+
end
|
115
|
+
|
116
|
+
put '/user_repository_mapping/?' do
|
117
|
+
do_authorize_any
|
118
|
+
|
119
|
+
ContainerGateway.update_user_repo_mapping(params)
|
120
|
+
{}
|
121
|
+
end
|
122
|
+
|
123
|
+
put '/repository_list/?' do
|
124
|
+
do_authorize_any
|
125
|
+
|
126
|
+
repositories = params['repositories'].nil? ? [] : params['repositories']
|
127
|
+
ContainerGateway.update_repository_list(repositories)
|
128
|
+
{}
|
104
129
|
end
|
105
130
|
|
106
131
|
private
|
107
132
|
|
133
|
+
def handle_repo_auth(params, auth_header, request)
|
134
|
+
user_token_is_valid = false
|
135
|
+
# FIXME: Getting unauthenticated token here...
|
136
|
+
if auth_header.present? && auth_header.valid_user_token?
|
137
|
+
user_token_is_valid = true
|
138
|
+
username = auth_header.user.name
|
139
|
+
end
|
140
|
+
username = request.params['account'] if username.nil?
|
141
|
+
|
142
|
+
return if Proxy::ContainerGateway.authorized_for_repo?(params[:repository], user_token_is_valid, username)
|
143
|
+
|
144
|
+
redirect_authorization_headers
|
145
|
+
halt 401, "unauthorized"
|
146
|
+
end
|
147
|
+
|
108
148
|
def redirect_authorization_headers
|
109
149
|
response.headers['Docker-Distribution-API-Version'] = 'registry/2.0'
|
110
150
|
response.headers['Www-Authenticate'] = "Bearer realm=\"https://#{request.host}/v2/token\"," \
|
@@ -123,6 +163,10 @@ expires_at: Time.now + one_year }.to_json
|
|
123
163
|
@value = value || ''
|
124
164
|
end
|
125
165
|
|
166
|
+
def user
|
167
|
+
ContainerGateway.token_user(@value.split(' ')[1])
|
168
|
+
end
|
169
|
+
|
126
170
|
def valid_user_token?
|
127
171
|
token_auth? && ContainerGateway.valid_token?(@value.split(' ')[1])
|
128
172
|
end
|
@@ -146,6 +190,19 @@ expires_at: Time.now + one_year }.to_json
|
|
146
190
|
def basic_auth?
|
147
191
|
@value.split(' ')[0] == 'Basic'
|
148
192
|
end
|
193
|
+
|
194
|
+
def blank?
|
195
|
+
Base64.decode64(@value.split(' ')[1]) == ':'
|
196
|
+
end
|
197
|
+
|
198
|
+
# A special case for the V1 API. Defer authentication to Foreman and return the username. `nil` if not authorized.
|
199
|
+
def v1_foreman_authorized_username
|
200
|
+
username = Base64.decode64(@value.split(' ')[1]).split(':')[0]
|
201
|
+
auth_response = ForemanApi.new.fetch_token(raw_header, { 'account' => username })
|
202
|
+
return username if auth_response.code.to_i == 200 && (JSON.parse(auth_response.body)['token'] != 'unauthenticated')
|
203
|
+
|
204
|
+
nil
|
205
|
+
end
|
149
206
|
end
|
150
207
|
end
|
151
208
|
end
|
@@ -1,15 +1,17 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'uri'
|
3
3
|
require 'digest'
|
4
|
-
|
4
|
+
require 'sequel'
|
5
5
|
module Proxy
|
6
6
|
module ContainerGateway
|
7
7
|
extend ::Proxy::Util
|
8
8
|
extend ::Proxy::Log
|
9
9
|
|
10
10
|
class << self
|
11
|
+
Sequel.extension :migration, :core_extensions
|
11
12
|
def pulp_registry_request(uri)
|
12
13
|
http_client = Net::HTTP.new(uri.host, uri.port)
|
14
|
+
http_client.ca_file = pulp_ca
|
13
15
|
http_client.cert = pulp_cert
|
14
16
|
http_client.key = pulp_key
|
15
17
|
http_client.use_ssl = true
|
@@ -48,7 +50,8 @@ module Proxy
|
|
48
50
|
|
49
51
|
repo_count = 0
|
50
52
|
repositories = []
|
51
|
-
|
53
|
+
user = params[:user].nil? ? nil : User.find(name: params[:user])
|
54
|
+
Proxy::ContainerGateway.catalog(user).each do |repo_name|
|
52
55
|
break if repo_count >= params[:n]
|
53
56
|
|
54
57
|
if params[:q].nil? || params[:q] == "" || repo_name.include?(params[:q])
|
@@ -59,48 +62,103 @@ module Proxy
|
|
59
62
|
repositories
|
60
63
|
end
|
61
64
|
|
62
|
-
def catalog
|
63
|
-
|
65
|
+
def catalog(user = nil)
|
66
|
+
if user.nil?
|
67
|
+
unauthenticated_repos
|
68
|
+
else
|
69
|
+
(unauthenticated_repos + user.repositories_dataset.map(:name)).sort
|
70
|
+
end
|
64
71
|
end
|
65
72
|
|
66
73
|
def unauthenticated_repos
|
67
|
-
|
68
|
-
conn[:unauthenticated_repositories].order(:name).map(:name)
|
74
|
+
Repository.where(auth_required: false).order(:name).map(:name)
|
69
75
|
end
|
70
76
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
+
# Replaces the entire list of repositories
|
78
|
+
def update_repository_list(repo_list)
|
79
|
+
RepositoryUser.dataset.delete
|
80
|
+
Repository.dataset.delete
|
81
|
+
repo_list.each do |repo|
|
82
|
+
Repository.find_or_create(name: repo['repository'],
|
83
|
+
auth_required: repo['auth_required'].to_s.downcase == "true")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Replaces the entire user-repo mapping for all logged-in users
|
88
|
+
def update_user_repo_mapping(user_repo_maps)
|
89
|
+
# Get hash map of all users and their repositories
|
90
|
+
# Ex: {"users"=> [{"admin"=>[{"repository"=>"repo", "auth_required"=>"true"}]}]}
|
91
|
+
# Go through list of repositories and add them to the DB
|
92
|
+
RepositoryUser.dataset.delete
|
93
|
+
user_repo_maps['users'].each do |user_repo_map|
|
94
|
+
user_repo_map.each do |user, repos|
|
95
|
+
repos.each do |repo|
|
96
|
+
found_repo = Repository.find(name: repo['repository'],
|
97
|
+
auth_required: repo['auth_required'].to_s.downcase == "true")
|
98
|
+
if found_repo.nil?
|
99
|
+
logger.warn("#{repo['repository']} does not exist in this smart proxy's environments")
|
100
|
+
elsif found_repo.auth_required
|
101
|
+
found_repo.add_user(User.find(name: user))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
77
105
|
end
|
78
106
|
end
|
79
107
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
108
|
+
# Replaces the user-repo mapping for a single user
|
109
|
+
def update_user_repositories(username, repositories)
|
110
|
+
user = User.where(name: username).first
|
111
|
+
user.remove_all_repositories
|
112
|
+
repositories.each do |repo_name|
|
113
|
+
found_repo = Repository.find(name: repo_name)
|
114
|
+
if found_repo.nil?
|
115
|
+
logger.warn("#{repo_name} does not exist in this smart proxy's environments")
|
116
|
+
elsif user.repositories_dataset.where(name: repo_name).first.nil? && found_repo.auth_required
|
117
|
+
user.add_repository(found_repo)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def authorized_for_repo?(repo_name, user_token_is_valid, username = nil)
|
123
|
+
repository = Repository.where(name: repo_name).first
|
124
|
+
|
125
|
+
# Repository doesn't exist
|
126
|
+
return false if repository.nil?
|
127
|
+
|
128
|
+
# Repository doesn't require auth
|
129
|
+
return true unless repository.auth_required
|
130
|
+
|
131
|
+
if username && user_token_is_valid && repository.auth_required
|
132
|
+
# User is logged in and has access to the repository
|
133
|
+
user = User.find(name: username)
|
134
|
+
return !user.repositories_dataset.where(name: repo_name).first.nil?
|
135
|
+
end
|
136
|
+
|
137
|
+
false
|
138
|
+
end
|
139
|
+
|
140
|
+
def token_user(token)
|
141
|
+
User[AuthenticationToken.find(token_checksum: Digest::SHA256.hexdigest(token)).user_id]
|
84
142
|
end
|
85
143
|
|
86
144
|
def valid_token?(token)
|
87
|
-
|
88
|
-
tokens.where(token_checksum: Digest::SHA256.hexdigest(token)).where do
|
145
|
+
AuthenticationToken.where(token_checksum: Digest::SHA256.hexdigest(token)).where do
|
89
146
|
expire_at > Sequel::CURRENT_TIMESTAMP
|
90
147
|
end.count.positive?
|
91
148
|
end
|
92
149
|
|
93
150
|
def insert_token(username, token, expire_at_string, clear_expired_tokens: true)
|
94
|
-
tokens = initialize_db[:authentication_tokens]
|
95
151
|
checksum = Digest::SHA256.hexdigest(token)
|
152
|
+
user = User.find_or_create(name: username)
|
96
153
|
|
97
|
-
|
98
|
-
|
99
|
-
|
154
|
+
AuthenticationToken.where(:token_checksum => checksum).delete
|
155
|
+
AuthenticationToken.create(token_checksum: checksum, expire_at: expire_at_string.to_s, user_id: user.id)
|
156
|
+
AuthenticationToken.where { expire_at < Sequel::CURRENT_TIMESTAMP }.delete if clear_expired_tokens
|
100
157
|
end
|
101
158
|
|
102
159
|
def initialize_db
|
103
|
-
|
160
|
+
file_path = Proxy::ContainerGateway::Plugin.settings.sqlite_db_path
|
161
|
+
conn = Sequel.connect("sqlite://#{file_path}")
|
104
162
|
container_gateway_path = $LOAD_PATH.detect { |path| path.include? 'smart_proxy_container_gateway' }
|
105
163
|
begin
|
106
164
|
Sequel::Migrator.check_current(conn, "#{container_gateway_path}/smart_proxy_container_gateway/sequel_migrations")
|
@@ -116,15 +174,34 @@ module Proxy
|
|
116
174
|
Sequel::Migrator.run(db_connection, "#{container_gateway_path}/smart_proxy_container_gateway/sequel_migrations")
|
117
175
|
end
|
118
176
|
|
177
|
+
def pulp_ca
|
178
|
+
Proxy::ContainerGateway::Plugin.settings.pulp_client_ssl_ca
|
179
|
+
end
|
180
|
+
|
119
181
|
def pulp_cert
|
120
|
-
OpenSSL::X509::Certificate.new(File.
|
182
|
+
OpenSSL::X509::Certificate.new(File.read(Proxy::ContainerGateway::Plugin.settings.pulp_client_ssl_cert))
|
121
183
|
end
|
122
184
|
|
123
185
|
def pulp_key
|
124
186
|
OpenSSL::PKey::RSA.new(
|
125
|
-
File.
|
187
|
+
File.read(Proxy::ContainerGateway::Plugin.settings.pulp_client_ssl_key)
|
126
188
|
)
|
127
189
|
end
|
128
190
|
end
|
191
|
+
|
192
|
+
class Repository < ::Sequel::Model(Proxy::ContainerGateway.initialize_db[:repositories])
|
193
|
+
many_to_many :users
|
194
|
+
end
|
195
|
+
|
196
|
+
class User < ::Sequel::Model(Proxy::ContainerGateway.initialize_db[:users])
|
197
|
+
many_to_many :repositories
|
198
|
+
one_to_many :authentication_tokens
|
199
|
+
end
|
200
|
+
|
201
|
+
class RepositoryUser < ::Sequel::Model(Proxy::ContainerGateway.initialize_db[:repositories_users]); end
|
202
|
+
|
203
|
+
class AuthenticationToken < ::Sequel::Model(Proxy::ContainerGateway.initialize_db[:authentication_tokens])
|
204
|
+
many_to_one :users
|
205
|
+
end
|
129
206
|
end
|
130
207
|
end
|
@@ -3,15 +3,15 @@ require 'uri'
|
|
3
3
|
module Proxy
|
4
4
|
module ContainerGateway
|
5
5
|
class ForemanApi
|
6
|
-
def
|
7
|
-
|
8
|
-
|
6
|
+
def registry_request(auth_header, params, suffix)
|
7
|
+
uri = URI.join(Proxy::SETTINGS.foreman_url, Proxy::ContainerGateway::Plugin.settings.katello_registry_path, suffix)
|
8
|
+
uri.query = process_params(params)
|
9
9
|
|
10
|
-
req = Net::HTTP::Get.new(
|
10
|
+
req = Net::HTTP::Get.new(uri)
|
11
11
|
req.add_field('Authorization', auth_header)
|
12
12
|
req.add_field('Accept', 'application/json')
|
13
13
|
req.content_type = 'application/json'
|
14
|
-
http = Net::HTTP.new(
|
14
|
+
http = Net::HTTP.new(uri.hostname, uri.port)
|
15
15
|
http.use_ssl = true
|
16
16
|
|
17
17
|
http.request(req)
|
@@ -21,6 +21,14 @@ module Proxy
|
|
21
21
|
params = params_in.slice('scope', 'account').compact
|
22
22
|
URI.encode_www_form(params)
|
23
23
|
end
|
24
|
+
|
25
|
+
def fetch_token(auth_header, params)
|
26
|
+
registry_request(auth_header, params, 'token')
|
27
|
+
end
|
28
|
+
|
29
|
+
def fetch_user_repositories(auth_header, params)
|
30
|
+
registry_request(auth_header, params, '_catalog')
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
26
34
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
Sequel.migration do
|
2
|
+
up do
|
3
|
+
# TODO: Should I be migrating the existing data?
|
4
|
+
|
5
|
+
create_table(:repositories) do
|
6
|
+
primary_key :id
|
7
|
+
String :name, null: false
|
8
|
+
Boolean :auth_required, null: false
|
9
|
+
end
|
10
|
+
|
11
|
+
create_table(:users) do
|
12
|
+
primary_key :id
|
13
|
+
String :name, null: false
|
14
|
+
end
|
15
|
+
|
16
|
+
# Migrate unauthenticated_repositories to the new repositories table (TODO: can I select `false` like that?)
|
17
|
+
from(:repositories).insert(%i[name auth_required],
|
18
|
+
from(:unauthenticated_repositories).select(:name, false))
|
19
|
+
|
20
|
+
# Migrate names from authentication_tokens to the new users table
|
21
|
+
from(:users).insert([:name], from(:authentication_tokens).select(:username))
|
22
|
+
|
23
|
+
alter_table(:authentication_tokens) do
|
24
|
+
add_foreign_key :user_id, :users
|
25
|
+
end
|
26
|
+
|
27
|
+
# Populate the new user_id foreign key for all authentication_tokens
|
28
|
+
from(:authentication_tokens).insert([:user_id],
|
29
|
+
from(:users).select(:id).where(name: self[:authentication_tokens][:username]))
|
30
|
+
|
31
|
+
alter_table(:authentication_tokens) do
|
32
|
+
drop_column :username
|
33
|
+
end
|
34
|
+
|
35
|
+
create_join_table(repository_id: :repositories, user_id: :users)
|
36
|
+
drop_table :unauthenticated_repositories
|
37
|
+
end
|
38
|
+
|
39
|
+
down do
|
40
|
+
alter_table(:authentication_tokens) do
|
41
|
+
add_column :username, String
|
42
|
+
end
|
43
|
+
|
44
|
+
# Repopulate the name column with usernames
|
45
|
+
from(:authentication_tokens).update(username:
|
46
|
+
from(:users).select(:name).where(id: self[:authentication_tokens][:user_id]))
|
47
|
+
|
48
|
+
alter_table(:authentication_tokens) do
|
49
|
+
drop_foreign_key :user_id
|
50
|
+
end
|
51
|
+
|
52
|
+
create_table(:unauthenticated_repositories) do
|
53
|
+
primary_key :id
|
54
|
+
String :name, null: false
|
55
|
+
end
|
56
|
+
|
57
|
+
# Repopulate the unauthenticated_repositories table
|
58
|
+
from(:unauthenticated_repositories).insert([:username],
|
59
|
+
from(:repositories).select(:name).where(auth_required: true))
|
60
|
+
|
61
|
+
drop_table :users
|
62
|
+
drop_table :repositories
|
63
|
+
drop_join_table(repository_id: :repositories, user_id: :users)
|
64
|
+
end
|
65
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
---
|
2
2
|
:enabled: true
|
3
3
|
:pulp_endpoint: 'https://your_pulp_3_server_here.com'
|
4
|
+
:pulp_client_ssl_ca: 'CA Cert for authenticating with Pulp'
|
4
5
|
:pulp_client_ssl_cert: 'X509 certificate for authenticating with Pulp'
|
5
6
|
:pulp_client_ssl_key: 'RSA private key for the Pulp certificate'
|
7
|
+
:katello_registry_path: 'Katello container registry suffix, e.g., /v2/'
|
6
8
|
:sqlite_db_path: '/var/lib/foreman-proxy/smart_proxy_container_gateway.db'
|
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_proxy_container_gateway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Ballou
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: sqlite3
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
description: Pulp 3 container registry support for Foreman/Katello Smart-Proxy
|
@@ -46,19 +46,20 @@ extra_rdoc_files:
|
|
46
46
|
- README.md
|
47
47
|
- LICENSE
|
48
48
|
files:
|
49
|
+
- LICENSE
|
50
|
+
- README.md
|
51
|
+
- bundler.d/container_gateway.rb
|
49
52
|
- lib/smart_proxy_container_gateway.rb
|
53
|
+
- lib/smart_proxy_container_gateway/container_gateway.rb
|
54
|
+
- lib/smart_proxy_container_gateway/container_gateway_api.rb
|
55
|
+
- lib/smart_proxy_container_gateway/container_gateway_http_config.ru
|
56
|
+
- lib/smart_proxy_container_gateway/container_gateway_main.rb
|
50
57
|
- lib/smart_proxy_container_gateway/foreman_api.rb
|
51
58
|
- lib/smart_proxy_container_gateway/sequel_migrations/001_initial.rb
|
52
59
|
- lib/smart_proxy_container_gateway/sequel_migrations/002_auth_tokens.rb
|
53
|
-
- lib/smart_proxy_container_gateway/
|
60
|
+
- lib/smart_proxy_container_gateway/sequel_migrations/003_authorization_reorg.rb
|
54
61
|
- lib/smart_proxy_container_gateway/version.rb
|
55
|
-
- lib/smart_proxy_container_gateway/container_gateway.rb
|
56
|
-
- lib/smart_proxy_container_gateway/container_gateway_api.rb
|
57
|
-
- lib/smart_proxy_container_gateway/container_gateway_main.rb
|
58
62
|
- settings.d/container_gateway.yml.example
|
59
|
-
- bundler.d/container_gateway.rb
|
60
|
-
- README.md
|
61
|
-
- LICENSE
|
62
63
|
homepage: http://github.com/ianballou/smart_proxy_container_gateway
|
63
64
|
licenses:
|
64
65
|
- GPLv3
|
@@ -69,17 +70,16 @@ require_paths:
|
|
69
70
|
- lib
|
70
71
|
required_ruby_version: !ruby/object:Gem::Requirement
|
71
72
|
requirements:
|
72
|
-
- - ~>
|
73
|
+
- - "~>"
|
73
74
|
- !ruby/object:Gem::Version
|
74
75
|
version: '2.5'
|
75
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
77
|
requirements:
|
77
|
-
- -
|
78
|
+
- - ">="
|
78
79
|
- !ruby/object:Gem::Version
|
79
80
|
version: '0'
|
80
81
|
requirements: []
|
81
|
-
|
82
|
-
rubygems_version: 2.0.14.1
|
82
|
+
rubygems_version: 3.0.3
|
83
83
|
signing_key:
|
84
84
|
specification_version: 4
|
85
85
|
summary: Pulp 3 container registry support for Foreman/Katello Smart-Proxy
|