Commit c8101384 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Improve dependency proxy for containers

Add support for namespaced image names like `linuxserver/nextcloud`
Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parent 565c2fc4
......@@ -2,19 +2,29 @@
class DependencyProxy::Registry
AUTH_URL = 'https://auth.docker.io'.freeze
LIBRARY_URL = 'https://registry-1.docker.io/v2/library'.freeze
LIBRARY_URL = 'https://registry-1.docker.io/v2'.freeze
class << self
def auth_url(image)
"#{AUTH_URL}/token?service=registry.docker.io&scope=repository:library/#{image}:pull"
"#{AUTH_URL}/token?service=registry.docker.io&scope=repository:#{image_path(image)}:pull"
end
def manifest_url(image, tag)
"#{LIBRARY_URL}/#{image}/manifests/#{tag}"
"#{LIBRARY_URL}/#{image_path(image)}/manifests/#{tag}"
end
def blob_url(image, blob_sha)
"#{LIBRARY_URL}/#{image}/blobs/#{blob_sha}"
"#{LIBRARY_URL}/#{image_path(image)}/blobs/#{blob_sha}"
end
private
def image_path(image)
if image.include?('/')
image
else
"library/#{image}"
end
end
end
end
......@@ -121,6 +121,9 @@ end
# Because docker adds v2 prefix to URI this need to be outside of usual group routes
scope constraints: { format: nil } do
get 'v2', to: proc { [200, {}, ['']] }
get 'v2/*group_id/dependency_proxy/containers/:image/manifests/*tag' => 'groups/dependency_proxy_for_containers#manifest'
get 'v2/*group_id/dependency_proxy/containers/:image/blobs/:sha' => 'groups/dependency_proxy_for_containers#blob'
constraints image: Gitlab::PathRegex.container_image_regex do
get 'v2/*group_id/dependency_proxy/containers/*image/manifests/*tag' => 'groups/dependency_proxy_for_containers#manifest'
get 'v2/*group_id/dependency_proxy/containers/*image/blobs/:sha' => 'groups/dependency_proxy_for_containers#blob'
end
end
......@@ -9,6 +9,10 @@ module EE
def saml_callback_regex
@saml_callback_regex ||= %r(\A\/groups\/(?<group>#{full_namespace_route_regex})\/\-\/saml\/callback\z).freeze
end
def container_image_regex
@container_image_regex ||= %r{\A([\w\.-]+\/){0,1}([\w\.-]+)\z}.freeze
end
end
end
end
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::PathRegex do
describe '.container_image_regex' do
subject { described_class.container_image_regex }
it { is_expected.to match('gitlab-ce') }
it { is_expected.to match('gitlab_ce') }
it { is_expected.to match('gitlab-org/gitlab-ce') }
it { is_expected.to match('100px.com/100px.ruby') }
it { is_expected.not_to match('foo/bar/baz') }
it { is_expected.not_to match('ruby:2.3.6') }
end
end
......@@ -2,10 +2,12 @@
require 'rails_helper'
RSpec.describe DependencyProxy::Registry, type: :model do
let(:image) { 'ruby' }
let(:tag) { '2.3.5-alpine' }
let(:blob_sha) { '40bd001563085fc35165329ea1ff5c5ecbdbbeef' }
context 'image name without namespace' do
let(:image) { 'ruby' }
describe '#auth_url' do
it 'returns a correct auth url' do
expect(described_class.auth_url(image))
......@@ -26,4 +28,30 @@ RSpec.describe DependencyProxy::Registry, type: :model do
.to eq('https://registry-1.docker.io/v2/library/ruby/blobs/40bd001563085fc35165329ea1ff5c5ecbdbbeef')
end
end
end
context 'image name with namespace' do
let(:image) { 'foo/ruby' }
describe '#auth_url' do
it 'returns a correct auth url' do
expect(described_class.auth_url(image))
.to eq('https://auth.docker.io/token?service=registry.docker.io&scope=repository:foo/ruby:pull')
end
end
describe '#manifest_url' do
it 'returns a correct manifest url' do
expect(described_class.manifest_url(image, tag))
.to eq('https://registry-1.docker.io/v2/foo/ruby/manifests/2.3.5-alpine')
end
end
describe '#blob_url' do
it 'returns a correct blob url' do
expect(described_class.blob_url(image, blob_sha))
.to eq('https://registry-1.docker.io/v2/foo/ruby/blobs/40bd001563085fc35165329ea1ff5c5ecbdbbeef')
end
end
end
end
......@@ -93,6 +93,7 @@ describe 'Group routing', "routing" do
allow(Group).to receive(:find_by_full_path).with('gitlabhq', any_args).and_return(true)
end
context 'image name without namespace' do
it 'routes to #manifest' do
expect(get('/v2/gitlabhq/dependency_proxy/containers/ruby/manifests/2.3.6'))
.to route_to('groups/dependency_proxy_for_containers#manifest', group_id: 'gitlabhq', image: 'ruby', tag: '2.3.6')
......@@ -103,4 +104,17 @@ describe 'Group routing', "routing" do
.to route_to('groups/dependency_proxy_for_containers#blob', group_id: 'gitlabhq', image: 'ruby', sha: 'abc12345')
end
end
context 'image name with namespace' do
it 'routes to #manifest' do
expect(get('/v2/gitlabhq/dependency_proxy/containers/foo/bar/manifests/2.3.6'))
.to route_to('groups/dependency_proxy_for_containers#manifest', group_id: 'gitlabhq', image: 'foo/bar', tag: '2.3.6')
end
it 'routes to #blob' do
expect(get('/v2/gitlabhq/dependency_proxy/containers/foo/bar/blobs/abc12345'))
.to route_to('groups/dependency_proxy_for_containers#blob', group_id: 'gitlabhq', image: 'foo/bar', sha: 'abc12345')
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment