summaryrefslogtreecommitdiff
path: root/app/services/auth/container_registry_authentication_service.rb
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2016-05-14 11:15:19 -0500
committerKamil Trzcinski <ayufan@ayufan.eu>2016-05-14 11:15:33 -0500
commit654d5ad3f42732df77553bfbc2230f17d9185267 (patch)
treee732669d38adb58696ac7e9b78dbd1d3a835340c /app/services/auth/container_registry_authentication_service.rb
parent906c880400a36abd34426c634d2a9f6086909db0 (diff)
parent63cdf1aeb04b9694c0b6d44b1141868fcc5a0904 (diff)
downloadgitlab-ce-654d5ad3f42732df77553bfbc2230f17d9185267.tar.gz
Merge branch 'docker-registry' into docker-registry-view
Diffstat (limited to 'app/services/auth/container_registry_authentication_service.rb')
-rw-r--r--app/services/auth/container_registry_authentication_service.rb84
1 files changed, 84 insertions, 0 deletions
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
new file mode 100644
index 00000000000..e7aa7faeb96
--- /dev/null
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -0,0 +1,84 @@
+module Auth
+ class ContainerRegistryAuthenticationService < BaseService
+ AUDIENCE = 'container_registry'
+
+ def execute
+ return error('not found', 404) unless registry.enabled
+
+ if params[:offline_token]
+ return error('forbidden', 403) unless current_user
+ end
+
+ return error('forbidden', 401) if scopes.blank?
+
+ { token: authorized_token(scopes).encoded }
+ end
+
+ def self.full_access_token(*names)
+ registry = Gitlab.config.registry
+ token = ::JWT::RSAToken.new(registry.key)
+ token.issuer = registry.issuer
+ token.audience = AUDIENCE
+ token[:access] = names.map do |name|
+ { type: 'repository', name: name, actions: %w(pull push) }
+ end
+ token.encoded
+ end
+
+ private
+
+ def authorized_token(access)
+ token = ::JWT::RSAToken.new(registry.key)
+ token.issuer = registry.issuer
+ token.audience = params[:service]
+ token.subject = current_user.try(:username)
+ token[:access] = access
+ token
+ end
+
+ def scopes
+ return unless params[:scope]
+
+ @scopes ||= begin
+ scope = process_scope(params[:scope])
+ [scope].compact
+ end
+ end
+
+ def process_scope(scope)
+ type, name, actions = scope.split(':', 3)
+ actions = actions.split(',')
+
+ case type
+ when 'repository'
+ process_repository_access(type, name, actions)
+ end
+ end
+
+ def process_repository_access(type, name, actions)
+ requested_project = Project.find_with_namespace(name)
+ return unless requested_project
+
+ actions = actions.select do |action|
+ can_access?(requested_project, action)
+ end
+
+ { type: type, name: name, actions: actions } if actions.present?
+ end
+
+ def can_access?(requested_project, requested_action)
+ case requested_action
+ when 'pull'
+ requested_project.public? || requested_project == project || can?(current_user, :read_container_registry, requested_project)
+ when 'push'
+ requested_project == project || can?(current_user, :create_container_registry, requested_project)
+ else
+ false
+ end
+ end
+
+ def registry
+ Gitlab.config.registry
+ end
+ end
+end