From c43eea0587d6e656c85dc1ef1519797caa878e0a Mon Sep 17 00:00:00 2001 From: malletvapid23 Date: Mon, 15 Nov 2021 17:30:54 +0200 Subject: [PATCH] [sonic-package-manager] fix registry requests failing when no service field in Bearer fields (#1921) Signed-off-by: Stepan Blyschak stepanb@nvidia.com What I did If Auth service did not reply with "service" field, don't fail and request the token without it. How I did it Modified registry.py and added UT. How to verify it Tested on DUT. --- setup.py | 1 + sonic_package_manager/registry.py | 17 ++++++++-------- tests/sonic_package_manager/test_registry.py | 21 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 1dba5e6..c269bb1 100644 --- a/setup.py +++ b/setup.py @@ -209,6 +209,7 @@ ], tests_require = [ 'pyfakefs', + 'responses', 'pytest', 'mockredispy>=2.9.3', 'deepdiff==5.2.3' diff --git a/sonic_package_manager/registry.py b/sonic_package_manager/registry.py index 8c03b07..5cac546 100644 --- a/sonic_package_manager/registry.py +++ b/sonic_package_manager/registry.py @@ -23,20 +23,21 @@ class AuthenticationService: """ AuthenticationService provides an authentication tokens. """ @staticmethod - def get_token(realm, service, scope) -> str: + def get_token(bearer: Dict) -> str: """ Retrieve an authentication token. Args: - realm: Realm: url to request token. - service: service to request token for. - scope: scope to requests token for. + bearer: Bearer token. Returns: token value as a string. """ - log.debug(f'getting authentication token: realm={realm} service={service} scope={scope}') + log.debug(f'getting authentication token {bearer}') + if 'realm' not in bearer: + raise AuthenticationServiceError(f'Realm is required in bearer') - response = requests.get(f'{realm}?scope={scope}&service={service}') + url = bearer.pop('realm') + response = requests.get(url, params=bearer) if response.status_code != requests.codes.ok: raise AuthenticationServiceError('Failed to retrieve token') @@ -44,7 +45,7 @@ def get_token(realm, service, scope) -> str: token = content['token'] expires_in = content['expires_in'] - log.debug(f'authentication token for realm={realm} service={service} scope={scope}: ' + log.debug(f'authentication token for bearer={bearer}: ' f'token={token} expires_in={expires_in}') return token @@ -85,7 +86,7 @@ def _execute_get_request(url, headers): log.debug(f'unauthorized: retrieving authentication details ' f'from response headers {www_authenticate_details}') bearer = www_authenticate.parse(www_authenticate_details)['bearer'] - token = AuthenticationService.get_token(**bearer) + token = AuthenticationService.get_token(bearer) headers['Authorization'] = f'Bearer {token}' # Repeat request response = requests.get(url, headers=headers) diff --git a/tests/sonic_package_manager/test_registry.py b/tests/sonic_package_manager/test_registry.py index 0d82499..0b6072a 100644 --- a/tests/sonic_package_manager/test_registry.py +++ b/tests/sonic_package_manager/test_registry.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +import requests +import responses from sonic_package_manager.registry import RegistryResolver @@ -13,3 +15,22 @@ def test_get_registry_for(): assert registry.url == 'https://registry-server:5000' registry = resolver.get_registry_for('registry-server.com/docker') assert registry.url == 'https://registry-server.com' + + +@responses.activate +def test_registry_auth(): + resolver = RegistryResolver() + registry = resolver.get_registry_for('registry-server:5000/docker') + responses.add(responses.GET, registry.url + '/v2/docker/tags/list', + headers={ + 'www-authenticate': 'Bearer realm="https://auth.docker.io/token",scope="repository:library/docker:pull,push"' + }, + status=requests.codes.unauthorized) + responses.add(responses.GET, + 'https://auth.docker.io/token?scope=repository:library/docker:pull,push', + json={'token': 'a', 'expires_in': '100'}, + status=requests.codes.ok) + responses.add(responses.GET, registry.url + '/v2/docker/tags/list', + json={'tags': ['a', 'b']}, + status=requests.codes.ok) + assert registry.tags('registry-server:5000/docker') == ['a', 'b']