Prevent registry operations against disabled namespaces
Allows admins to completely wall off a namespace by disabling it Fixes https://jira.coreos.com/browse/QUAY-869
This commit is contained in:
parent
6ffafe44d3
commit
f86c087b3b
14 changed files with 102 additions and 1 deletions
|
@ -99,6 +99,12 @@ def registry_server_executor(app):
|
|||
model.repository.create_repository(namespace, name, user, repo_kind='application')
|
||||
return 'OK'
|
||||
|
||||
def disable_namespace(namespace):
|
||||
namespace_obj = model.user.get_namespace_user(namespace)
|
||||
namespace_obj.enabled = False
|
||||
namespace_obj.save()
|
||||
return 'OK'
|
||||
|
||||
executor = LiveServerExecutor()
|
||||
executor.register('generate_csrf', generate_csrf)
|
||||
executor.register('set_supports_direct_download', set_supports_direct_download)
|
||||
|
@ -111,6 +117,7 @@ def registry_server_executor(app):
|
|||
executor.register('break_database', break_database)
|
||||
executor.register('reload_app', reload_app)
|
||||
executor.register('create_app_repository', create_app_repository)
|
||||
executor.register('disable_namespace', disable_namespace)
|
||||
return executor
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ class V1Protocol(RegistryProtocol):
|
|||
Failures.APP_REPOSITORY: 405,
|
||||
Failures.INVALID_REPOSITORY: 404,
|
||||
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
|
||||
Failures.NAMESPACE_DISABLED: 400,
|
||||
},
|
||||
V1ProtocolSteps.GET_IMAGES: {
|
||||
Failures.UNAUTHENTICATED: 403,
|
||||
|
@ -30,11 +31,13 @@ class V1Protocol(RegistryProtocol):
|
|||
Failures.APP_REPOSITORY: 405,
|
||||
Failures.ANONYMOUS_NOT_ALLOWED: 401,
|
||||
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
|
||||
Failures.NAMESPACE_DISABLED: 400,
|
||||
},
|
||||
V1ProtocolSteps.PUT_TAG: {
|
||||
Failures.MISSING_TAG: 404,
|
||||
Failures.INVALID_TAG: 400,
|
||||
Failures.INVALID_IMAGES: 400,
|
||||
Failures.NAMESPACE_DISABLED: 400,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ class V2Protocol(RegistryProtocol):
|
|||
Failures.APP_REPOSITORY: 405,
|
||||
Failures.ANONYMOUS_NOT_ALLOWED: 401,
|
||||
Failures.INVALID_REPOSITORY: 400,
|
||||
Failures.NAMESPACE_DISABLED: 400,
|
||||
},
|
||||
V2ProtocolSteps.GET_MANIFEST: {
|
||||
Failures.UNKNOWN_TAG: 404,
|
||||
|
|
|
@ -50,6 +50,7 @@ class Failures(Enum):
|
|||
INVALID_IMAGES = 'invalid-images'
|
||||
UNSUPPORTED_CONTENT_TYPE = 'unsupported-content-type'
|
||||
INVALID_BLOB = 'invalid-blob'
|
||||
NAMESPACE_DISABLED = 'namespace-disabled'
|
||||
|
||||
|
||||
class ProtocolOptions(object):
|
||||
|
|
|
@ -644,6 +644,36 @@ def test_chunked_uploading_mismatched_chunks(manifest_protocol, random_layer_dat
|
|||
images, credentials=credentials, options=options)
|
||||
|
||||
|
||||
def test_pull_disabled_namespace(pusher, puller, basic_images, liveserver_session,
|
||||
app_reloader, liveserver, registry_server_executor):
|
||||
""" Test: Attempt to pull a repository from a disabled namespace results in an error. """
|
||||
credentials = ('devtable', 'password')
|
||||
|
||||
# Push a new repository.
|
||||
pusher.push(liveserver_session, 'buynlarge', 'someneworgrepo', 'latest', basic_images,
|
||||
credentials=credentials)
|
||||
|
||||
# Disable the namespace.
|
||||
registry_server_executor.on(liveserver).disable_namespace('buynlarge')
|
||||
|
||||
# Attempt to pull, which should fail.
|
||||
puller.pull(liveserver_session, 'buynlarge', 'someneworgrepo', 'latest', basic_images,
|
||||
credentials=credentials, expected_failure=Failures.NAMESPACE_DISABLED)
|
||||
|
||||
|
||||
def test_push_disabled_namespace(pusher, basic_images, liveserver_session,
|
||||
app_reloader, liveserver, registry_server_executor):
|
||||
""" Test: Attempt to push a repository from a disabled namespace results in an error. """
|
||||
credentials = ('devtable', 'password')
|
||||
|
||||
# Disable the namespace.
|
||||
registry_server_executor.on(liveserver).disable_namespace('buynlarge')
|
||||
|
||||
# Attempt to push, which should fail.
|
||||
pusher.push(liveserver_session, 'buynlarge', 'someneworgrepo', 'latest', basic_images,
|
||||
credentials=credentials, expected_failure=Failures.NAMESPACE_DISABLED)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('public_catalog, credentials, expected_repos', [
|
||||
# No public access and no credentials => No results.
|
||||
(False, None, None),
|
||||
|
|
Reference in a new issue