Commit bc4d0a8c authored by Etienne Baqué's avatar Etienne Baqué

Merge branch 'vij-cr-storage-quota' into 'master'

Handle auth error for container registry

See merge request gitlab-org/gitlab!83278
parents 5247f187 4142c344
...@@ -5,6 +5,19 @@ module EE ...@@ -5,6 +5,19 @@ module EE
module ContainerRegistryAuthenticationService module ContainerRegistryAuthenticationService
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
StorageError = Class.new(StandardError)
override :execute
def execute(authentication_abilities:)
super
rescue StorageError
error(
'DENIED',
status: 403,
message: 'You are above your storage quota! Visit https://docs.gitlab.com/ee/user/usage_quotas.html to learn more.'
)
end
private private
override :can_access? override :can_access?
...@@ -14,6 +27,8 @@ module EE ...@@ -14,6 +27,8 @@ module EE
return false return false
end end
raise StorageError if storage_error?(requested_project, requested_action)
super super
end end
...@@ -30,6 +45,13 @@ module EE ...@@ -30,6 +45,13 @@ module EE
def access_denied_in_maintenance_mode? def access_denied_in_maintenance_mode?
@access_denied_in_maintenance_mode @access_denied_in_maintenance_mode
end end
def storage_error?(project, action)
return false unless project
return false unless action == 'push'
project.root_ancestor.over_storage_limit?
end
end end
end end
end end
...@@ -53,4 +53,82 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do ...@@ -53,4 +53,82 @@ RSpec.describe Auth::ContainerRegistryAuthenticationService do
context 'when not in maintenance mode' do context 'when not in maintenance mode' do
it_behaves_like 'a container registry auth service' it_behaves_like 'a container registry auth service'
end end
context 'when over storage limit' do
include_context 'container registry auth service context'
let_it_be(:current_user) { create(:user) }
let_it_be(:namespace) { create(:group) }
before do
allow_next_found_instance_of(Project) do |instance|
allow(instance).to receive(:root_ancestor).and_return namespace
end
allow(namespace).to receive(:over_storage_limit?).and_return true
end
context 'when there is a project' do
let_it_be(:project) { create(:project, namespace: namespace) }
before do
project.add_developer(current_user)
end
shared_examples 'storage error' do
it 'returns an appropriate response' do
expect(subject[:errors].first).to include(
code: 'DENIED',
message: 'You are above your storage quota! Visit https://docs.gitlab.com/ee/user/usage_quotas.html to learn more.'
)
end
end
context 'does not allow developer to push images' do
context 'when only pushing an image' do
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:push"] }
end
it_behaves_like 'not a container repository factory' do
it_behaves_like 'storage error'
end
end
context 'when performing multiple actions including push' do
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:push,pull"] }
end
it_behaves_like 'not a container repository factory' do
it_behaves_like 'storage error'
end
end
end
context 'allows developers to pull images' do
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:pull"] }
end
it_behaves_like 'a pullable'
end
context 'allows maintainers to delete images' do
before do
project.add_maintainer(current_user)
end
it_behaves_like 'allowed to delete container repository images'
end
end
context 'when there is no project' do
let(:project) { nil }
it 'does not return a storage error' do
expect(subject[:errors]).to be_nil
end
end
end
end end
...@@ -154,6 +154,30 @@ RSpec.shared_examples 'logs an auth warning' do |requested_actions| ...@@ -154,6 +154,30 @@ RSpec.shared_examples 'logs an auth warning' do |requested_actions|
end end
end end
RSpec.shared_examples 'allowed to delete container repository images' do
let(:authentication_abilities) do
[:admin_container_image]
end
it_behaves_like 'a valid token'
context 'allow to delete images' do
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:*"] }
end
it_behaves_like 'a deletable'
end
context 'allow to delete images since registry 2.7' do
let(:current_params) do
{ scopes: ["repository:#{project.full_path}:delete"] }
end
it_behaves_like 'a deletable since registry 2.7'
end
end
RSpec.shared_examples 'a container registry auth service' do RSpec.shared_examples 'a container registry auth service' do
include_context 'container registry auth service context' include_context 'container registry auth service context'
...@@ -544,38 +568,14 @@ RSpec.shared_examples 'a container registry auth service' do ...@@ -544,38 +568,14 @@ RSpec.shared_examples 'a container registry auth service' do
end end
context 'delete authorized as maintainer' do context 'delete authorized as maintainer' do
let_it_be(:current_project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let(:authentication_abilities) do
[:admin_container_image]
end
before_all do before_all do
current_project.add_maintainer(current_user) project.add_maintainer(current_user)
end
it_behaves_like 'a valid token'
context 'allow to delete images' do
let(:current_params) do
{ scopes: ["repository:#{current_project.full_path}:*"] }
end
it_behaves_like 'a deletable' do
let(:project) { current_project }
end
end end
context 'allow to delete images since registry 2.7' do it_behaves_like 'allowed to delete container repository images'
let(:current_params) do
{ scopes: ["repository:#{current_project.full_path}:delete"] }
end
it_behaves_like 'a deletable since registry 2.7' do
let(:project) { current_project }
end
end
end end
context 'build authorized as user' do context 'build authorized as user' do
......
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