Commit 7d3d1ec5 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Create container repository on successful push auth

Because we do not have yet two way communication between container
registry and GitLab, we need to eagerly create a new container
repository objects in database. We now do that after user/build
successfully authenticates a push action using auth service.
parent 236c9c17
...@@ -60,6 +60,7 @@ class ContainerRepository < ActiveRecord::Base ...@@ -60,6 +60,7 @@ class ContainerRepository < ActiveRecord::Base
end end
def self.create_from_path(path) def self.create_from_path(path)
self.create(project: path.repository_project, name: path.repository_name) self.create(project: path.repository_project,
name: path.repository_name)
end end
end end
...@@ -74,9 +74,25 @@ module Auth ...@@ -74,9 +74,25 @@ module Auth
return unless actions.present? return unless actions.present?
# At this point user/build is already authenticated.
#
ensure_container_repository!(path, actions)
{ type: type, name: path.to_s, actions: actions } { type: type, name: path.to_s, actions: actions }
end end
##
# Because we do not have two way communication with registry yet,
# we create a container repository image resource when push to the
# registry is successfuly authorized.
#
def ensure_container_repository!(path, actions)
return if path.has_repository?
return unless actions.include?('push')
ContainerRepository.create_from_path(path)
end
def can_access?(requested_project, requested_action) def can_access?(requested_project, requested_action)
return false unless requested_project.container_registry_enabled? return false unless requested_project.container_registry_enabled?
......
...@@ -44,6 +44,10 @@ module ContainerRegistry ...@@ -44,6 +44,10 @@ module ContainerRegistry
.where(name: repository_name).any? .where(name: repository_name).any?
end end
def root_repository?
@path == repository_project.full_path
end
def repository_project def repository_project
@project ||= Project.where_full_path_in(components.first(3))&.first @project ||= Project.where_full_path_in(components.first(3))&.first
end end
......
...@@ -80,6 +80,19 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -80,6 +80,19 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
it { is_expected.not_to include(:token) } it { is_expected.not_to include(:token) }
end end
shared_examples 'container repository factory' do
it 'creates a new containe repository resource' do
expect { subject }
.to change { project.container_repositories.count }.by(1)
end
end
shared_examples 'container repository factory' do
it 'does not create a new container repository resource' do
expect { subject }.not_to change { ContainerRepository.count }
end
end
describe '#full_access_token' do describe '#full_access_token' do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:token) { described_class.full_access_token(project.path_with_namespace) } let(:token) { described_class.full_access_token(project.path_with_namespace) }
...@@ -89,6 +102,8 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -89,6 +102,8 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
it_behaves_like 'an accessible' do it_behaves_like 'an accessible' do
let(:actions) { ['*'] } let(:actions) { ['*'] }
end end
it_behaves_like 'not a container repository factory'
end end
context 'user authorization' do context 'user authorization' do
...@@ -109,16 +124,20 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -109,16 +124,20 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a pushable' it_behaves_like 'a pushable'
it_behaves_like 'container repository factory'
end end
context 'allow reporter to pull images' do context 'allow reporter to pull images' do
before { project.team << [current_user, :reporter] } before { project.team << [current_user, :reporter] }
let(:current_params) do context 'when pulling from root level repository' do
{ scope: "repository:#{project.path_with_namespace}:pull" } let(:current_params) do
end { scope: "repository:#{project.path_with_namespace}:pull" }
end
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end
end end
context 'return a least of privileges' do context 'return a least of privileges' do
...@@ -129,6 +148,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -129,6 +148,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
context 'disallow guest to pull or push images' do context 'disallow guest to pull or push images' do
...@@ -139,6 +159,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -139,6 +159,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
end end
...@@ -151,6 +172,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -151,6 +172,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
context 'disallow anyone to push images' do context 'disallow anyone to push images' do
...@@ -159,6 +181,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -159,6 +181,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
end end
...@@ -172,6 +195,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -172,6 +195,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
context 'disallow anyone to push images' do context 'disallow anyone to push images' do
...@@ -180,6 +204,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -180,6 +204,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
end end
...@@ -190,6 +215,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -190,6 +215,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
end end
end end
...@@ -216,6 +242,10 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -216,6 +242,10 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
it_behaves_like 'a pullable and pushable' do it_behaves_like 'a pullable and pushable' do
let(:project) { current_project } let(:project) { current_project }
end end
it_behaves_like 'container repository factory' do
let(:project) { current_project }
end
end end
context 'for other projects' do context 'for other projects' do
...@@ -228,11 +258,13 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -228,11 +258,13 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
let(:project) { create(:empty_project, :public) } let(:project) { create(:empty_project, :public) }
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
shared_examples 'pullable for being team member' do shared_examples 'pullable for being team member' do
context 'when you are not member' do context 'when you are not member' do
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
context 'when you are member' do context 'when you are member' do
...@@ -241,12 +273,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -241,12 +273,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
context 'when you are owner' do context 'when you are owner' do
let(:project) { create(:empty_project, namespace: current_user.namespace) } let(:project) { create(:empty_project, namespace: current_user.namespace) }
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
end end
...@@ -260,6 +294,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -260,6 +294,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
context 'when you are not member' do context 'when you are not member' do
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
context 'when you are member' do context 'when you are member' do
...@@ -268,12 +303,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -268,12 +303,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
context 'when you are owner' do context 'when you are owner' do
let(:project) { create(:empty_project, namespace: current_user.namespace) } let(:project) { create(:empty_project, namespace: current_user.namespace) }
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
end end
end end
...@@ -293,12 +330,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -293,12 +330,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
context 'when you are owner' do context 'when you are owner' do
let(:project) { create(:empty_project, :public, namespace: current_user.namespace) } let(:project) { create(:empty_project, :public, namespace: current_user.namespace) }
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
end end
end end
...@@ -315,6 +354,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -315,6 +354,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'an inaccessible' it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end end
end end
end end
...@@ -322,6 +362,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -322,6 +362,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
context 'unauthorized' do context 'unauthorized' do
context 'disallow to use scope-less authentication' do context 'disallow to use scope-less authentication' do
it_behaves_like 'a forbidden' it_behaves_like 'a forbidden'
it_behaves_like 'not a container repository factory'
end end
context 'for invalid scope' do context 'for invalid scope' do
...@@ -330,6 +371,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -330,6 +371,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a forbidden' it_behaves_like 'a forbidden'
it_behaves_like 'not a container repository factory'
end end
context 'for private project' do context 'for private project' do
...@@ -351,6 +393,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -351,6 +393,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a pullable' it_behaves_like 'a pullable'
it_behaves_like 'not a container repository factory'
end end
context 'when pushing' do context 'when pushing' do
...@@ -359,6 +402,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -359,6 +402,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end end
it_behaves_like 'a forbidden' it_behaves_like 'a forbidden'
it_behaves_like 'not a container repository factory'
end end
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