summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/services/auth/container_registry_authentication_service.rb7
-rw-r--r--changelogs/unreleased/add-star-for-action-scope.yml4
-rw-r--r--lib/gitlab/auth.rb3
-rw-r--r--spec/lib/gitlab/auth_spec.rb3
-rw-r--r--spec/services/auth/container_registry_authentication_service_spec.rb138
5 files changed, 139 insertions, 16 deletions
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 5e151b0f044..7dae5880931 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -103,6 +103,8 @@ module Auth
build_can_pull?(requested_project) || user_can_pull?(requested_project)
when 'push'
build_can_push?(requested_project) || user_can_push?(requested_project)
+ when '*'
+ user_can_admin?(requested_project)
else
false
end
@@ -120,6 +122,11 @@ module Auth
(requested_project == project || can?(current_user, :build_read_container_image, requested_project))
end
+ def user_can_admin?(requested_project)
+ has_authentication_ability?(:admin_container_image) &&
+ can?(current_user, :admin_container_image, requested_project)
+ end
+
def user_can_pull?(requested_project)
has_authentication_ability?(:read_container_image) &&
can?(current_user, :read_container_image, requested_project)
diff --git a/changelogs/unreleased/add-star-for-action-scope.yml b/changelogs/unreleased/add-star-for-action-scope.yml
new file mode 100644
index 00000000000..a8119a01ec4
--- /dev/null
+++ b/changelogs/unreleased/add-star-for-action-scope.yml
@@ -0,0 +1,4 @@
+---
+title: Add star for action scope, in order to delete image from registry
+merge_request: 13248
+author: jean
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 9bed81e7327..7d3aa532750 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -218,7 +218,8 @@ module Gitlab
def full_authentication_abilities
read_authentication_abilities + [
:push_code,
- :create_container_image
+ :create_container_image,
+ :admin_container_image
]
end
alias_method :api_scope_authentication_abilities, :full_authentication_abilities
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 8f57e73e40d..4a498e79c87 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -313,7 +313,8 @@ describe Gitlab::Auth do
def full_authentication_abilities
read_authentication_abilities + [
:push_code,
- :create_container_image
+ :create_container_image,
+ :admin_container_image
]
end
end
diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb
index d23c09d6d1d..1c2d0b3e0dc 100644
--- a/spec/services/auth/container_registry_authentication_service_spec.rb
+++ b/spec/services/auth/container_registry_authentication_service_spec.rb
@@ -8,7 +8,7 @@ describe Auth::ContainerRegistryAuthenticationService do
let(:payload) { JWT.decode(subject[:token], rsa_key).first }
let(:authentication_abilities) do
- [:read_container_image, :create_container_image]
+ [:read_container_image, :create_container_image, :admin_container_image]
end
subject do
@@ -59,6 +59,12 @@ describe Auth::ContainerRegistryAuthenticationService do
it { expect(payload).to include('access' => []) }
end
+ shared_examples 'a deletable' do
+ it_behaves_like 'an accessible' do
+ let(:actions) { ['*'] }
+ end
+ end
+
shared_examples 'a pullable' do
it_behaves_like 'an accessible' do
let(:actions) { ['pull'] }
@@ -120,7 +126,7 @@ describe Auth::ContainerRegistryAuthenticationService do
context 'allow developer to push images' do
before do
- project.team << [current_user, :developer]
+ project.add_developer(current_user)
end
let(:current_params) do
@@ -131,9 +137,22 @@ describe Auth::ContainerRegistryAuthenticationService do
it_behaves_like 'container repository factory'
end
+ context 'disallow developer to delete images' do
+ before do
+ project.add_developer(current_user)
+ end
+
+ let(:current_params) do
+ { scope: "repository:#{project.path_with_namespace}:*" }
+ end
+
+ it_behaves_like 'an inaccessible'
+ it_behaves_like 'not a container repository factory'
+ end
+
context 'allow reporter to pull images' do
before do
- project.team << [current_user, :reporter]
+ project.add_reporter(current_user)
end
context 'when pulling from root level repository' do
@@ -146,9 +165,22 @@ describe Auth::ContainerRegistryAuthenticationService do
end
end
+ context 'disallow reporter to delete images' do
+ before do
+ project.add_reporter(current_user)
+ end
+
+ let(:current_params) do
+ { scope: "repository:#{project.path_with_namespace}:*" }
+ end
+
+ it_behaves_like 'an inaccessible'
+ it_behaves_like 'not a container repository factory'
+ end
+
context 'return a least of privileges' do
before do
- project.team << [current_user, :reporter]
+ project.add_reporter(current_user)
end
let(:current_params) do
@@ -161,7 +193,7 @@ describe Auth::ContainerRegistryAuthenticationService do
context 'disallow guest to pull or push images' do
before do
- project.team << [current_user, :guest]
+ project.add_guest(current_user)
end
let(:current_params) do
@@ -171,6 +203,19 @@ describe Auth::ContainerRegistryAuthenticationService do
it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end
+
+ context 'disallow guest to delete images' do
+ before do
+ project.add_guest(current_user)
+ end
+
+ let(:current_params) do
+ { scope: "repository:#{project.path_with_namespace}:*" }
+ end
+
+ it_behaves_like 'an inaccessible'
+ it_behaves_like 'not a container repository factory'
+ end
end
context 'for public project' do
@@ -194,6 +239,15 @@ describe Auth::ContainerRegistryAuthenticationService do
it_behaves_like 'not a container repository factory'
end
+ context 'disallow anyone to delete images' do
+ let(:current_params) do
+ { scope: "repository:#{project.path_with_namespace}:*" }
+ end
+
+ it_behaves_like 'an inaccessible'
+ it_behaves_like 'not a container repository factory'
+ end
+
context 'when repository name is invalid' do
let(:current_params) do
{ scope: 'repository:invalid:push' }
@@ -225,16 +279,62 @@ describe Auth::ContainerRegistryAuthenticationService do
it_behaves_like 'an inaccessible'
it_behaves_like 'not a container repository factory'
end
+
+ context 'disallow anyone to delete images' do
+ let(:current_params) do
+ { scope: "repository:#{project.path_with_namespace}:*" }
+ end
+
+ it_behaves_like 'an inaccessible'
+ it_behaves_like 'not a container repository factory'
+ end
end
context 'for external user' do
- let(:current_user) { create(:user, external: true) }
- let(:current_params) do
- { scope: "repository:#{project.full_path}:pull,push" }
+ context 'disallow anyone to pull or push images' do
+ let(:current_user) { create(:user, external: true) }
+ let(:current_params) do
+ { scope: "repository:#{project.path_with_namespace}:pull,push" }
+ end
+
+ it_behaves_like 'an inaccessible'
+ it_behaves_like 'not a container repository factory'
end
- it_behaves_like 'an inaccessible'
- it_behaves_like 'not a container repository factory'
+ context 'disallow anyone to delete images' do
+ let(:current_user) { create(:user, external: true) }
+ let(:current_params) do
+ { scope: "repository:#{project.path_with_namespace}:*" }
+ end
+
+ it_behaves_like 'an inaccessible'
+ it_behaves_like 'not a container repository factory'
+ end
+ end
+ end
+ end
+
+ context 'delete authorized as master' do
+ let(:current_project) { create(:project) }
+ let(:current_user) { create(:user) }
+
+ let(:authentication_abilities) do
+ [:admin_container_image]
+ end
+
+ before do
+ current_project.add_master(current_user)
+ end
+
+ it_behaves_like 'a valid token'
+
+ context 'allow to delete images' do
+ let(:current_params) do
+ { scope: "repository:#{current_project.path_with_namespace}:*" }
+ end
+
+ it_behaves_like 'a deletable' do
+ let(:project) { current_project }
end
end
end
@@ -248,7 +348,7 @@ describe Auth::ContainerRegistryAuthenticationService do
end
before do
- current_project.team << [current_user, :developer]
+ current_project.add_developer(current_user)
end
it_behaves_like 'a valid token'
@@ -267,6 +367,16 @@ describe Auth::ContainerRegistryAuthenticationService do
end
end
+ context 'disallow to delete images' do
+ let(:current_params) do
+ { scope: "repository:#{current_project.path_with_namespace}:*" }
+ end
+
+ it_behaves_like 'an inaccessible' do
+ let(:project) { current_project }
+ end
+ end
+
context 'for other projects' do
context 'when pulling' do
let(:current_params) do
@@ -288,7 +398,7 @@ describe Auth::ContainerRegistryAuthenticationService do
context 'when you are member' do
before do
- project.team << [current_user, :developer]
+ project.add_developer(current_user)
end
it_behaves_like 'a pullable'
@@ -318,7 +428,7 @@ describe Auth::ContainerRegistryAuthenticationService do
context 'when you are member' do
before do
- project.team << [current_user, :developer]
+ project.add_developer(current_user)
end
it_behaves_like 'a pullable'
@@ -345,7 +455,7 @@ describe Auth::ContainerRegistryAuthenticationService do
let(:project) { create(:project, :public) }
before do
- project.team << [current_user, :developer]
+ project.add_developer(current_user)
end
it_behaves_like 'an inaccessible'