From 2e0edf8f6eb359aef0fdfafe5f0adcf571682147 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Tue, 5 Jun 2018 17:31:00 -0400 Subject: [PATCH 1/2] Have catalog endpoint return empty if the namespace is disabled --- endpoints/v2/catalog.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/endpoints/v2/catalog.py b/endpoints/v2/catalog.py index 5d29cfffc..c36a6ecee 100644 --- a/endpoints/v2/catalog.py +++ b/endpoints/v2/catalog.py @@ -1,6 +1,6 @@ import features -from flask import jsonify +from flask import jsonify, abort from auth.auth_context import get_authenticated_user from auth.registry_jwt_auth import process_registry_jwt_auth @@ -14,8 +14,14 @@ from endpoints.v2.models_pre_oci import data_model as model @anon_protect @paginate() def catalog_search(limit, offset, pagination_callback): - username = get_authenticated_user().username if get_authenticated_user() else None include_public = bool(features.PUBLIC_CATALOG) + if not include_public and not get_authenticated_user(): + return jsonify({'repositories': []}) + + username = get_authenticated_user().username if get_authenticated_user() else None + if username and not get_authenticated_user().enabled: + return jsonify({'repositories': []}) + visible_repositories = model.get_visible_repositories(username, limit + 1, offset, include_public=include_public) response = jsonify({ From ef167ab7e3143e915ae71de6edc4ed213c53695f Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Tue, 5 Jun 2018 17:31:11 -0400 Subject: [PATCH 2/2] Rate limit the catalog endpoint by auth token and IP address --- conf/nginx/rate-limiting.conf | 3 +-- conf/nginx/server-base.conf.jnj | 10 ++++++---- endpoints/v2/catalog.py | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/conf/nginx/rate-limiting.conf b/conf/nginx/rate-limiting.conf index 2ffbd320c..f5c3117f7 100644 --- a/conf/nginx/rate-limiting.conf +++ b/conf/nginx/rate-limiting.conf @@ -2,8 +2,6 @@ # Check the Authorization header and, if it is empty, use their proxy protocol # IP, else use the header as their unique identifier for rate limiting. -# Enterprise users will never be using proxy protocol, thus the value will be -# empty string. This means they will not get rate limited. map $http_authorization $registry_bucket { "" $proxy_protocol_addr; default $http_authorization; @@ -11,5 +9,6 @@ map $http_authorization $registry_bucket { limit_req_zone $proxy_protocol_addr zone=verbs:10m rate=1r/s; limit_req_zone $registry_bucket zone=repositories:10m rate=1r/s; +limit_req_zone $registry_bucket zone=catalog:10m rate=10r/m; limit_req_status 429; limit_req_log_level warn; diff --git a/conf/nginx/server-base.conf.jnj b/conf/nginx/server-base.conf.jnj index c5dc8ff72..84af02d6f 100644 --- a/conf/nginx/server-base.conf.jnj +++ b/conf/nginx/server-base.conf.jnj @@ -75,6 +75,12 @@ location ~ ^/(v1/repositories|v2/auth)/ { limit_req zone=repositories burst=10; } +location ~ ^/v2/_catalog(.*)$ { + proxy_pass http://registry_app_server; + proxy_read_timeout 10; + limit_req zone=catalog; +} + location /secscan/ { proxy_pass http://jwtproxy_secscan; } @@ -136,10 +142,6 @@ location ~ ^/v2 { client_max_body_size {{ maximum_layer_size }}; } -location /v2/_catalog { - return 400; -} - location ~ ^/v1 { # Setting ANY header clears all inherited proxy_set_header directives proxy_set_header X-Forwarded-For $proper_forwarded_for; diff --git a/endpoints/v2/catalog.py b/endpoints/v2/catalog.py index c36a6ecee..557910602 100644 --- a/endpoints/v2/catalog.py +++ b/endpoints/v2/catalog.py @@ -1,6 +1,6 @@ import features -from flask import jsonify, abort +from flask import jsonify from auth.auth_context import get_authenticated_user from auth.registry_jwt_auth import process_registry_jwt_auth