async def _basic_auth_registry_request(app: web.Application, path: str, method: str, **session_kwargs) -> Tuple[Dict, Dict]: if not config.REGISTRY_URL: raise exceptions.DirectorException("URL to registry is not defined") url = URL( f"{'https' if config.REGISTRY_SSL else 'http'}://{config.REGISTRY_URL}{path}" ) logger.debug("Requesting registry using %s", url) # try the registry with basic authentication first, spare 1 call resp_data: Dict = {} resp_headers: Dict = {} auth = (BasicAuth(login=config.REGISTRY_USER, password=config.REGISTRY_PW) if config.REGISTRY_AUTH and config.REGISTRY_USER and config.REGISTRY_PW else None) session = app[APP_CLIENT_SESSION_KEY] try: async with session.request(method.lower(), url, auth=auth, **session_kwargs) as response: if response.status == HTTPStatus.UNAUTHORIZED: logger.debug("Registry unauthorized request: %s", await response.text()) # basic mode failed, test with other auth mode resp_data, resp_headers = await _auth_registry_request( url, method, response.headers, session, **session_kwargs) elif response.status == HTTPStatus.NOT_FOUND: logger.exception("Path to registry not found: %s", url) raise exceptions.ServiceNotAvailableError(str(path)) elif response.status > 399: logger.exception("Unknown error while accessing registry: %s", str(response)) raise exceptions.RegistryConnectionError(str(response)) else: # registry that does not need an auth resp_data = await response.json(content_type=None) resp_headers = response.headers return (resp_data, resp_headers) except client_exceptions.ClientError as exc: logger.exception("Unknown error while accessing registry: %s", str(exc)) raise exceptions.DirectorException( f"Unknown error while accessing registry: {str(exc)}")
async def _auth_registry_request( url: URL, method: str, auth_headers: Dict, session: ClientSession ) -> Tuple[Dict, Dict]: if not config.REGISTRY_AUTH or not config.REGISTRY_USER or not config.REGISTRY_PW: raise exceptions.RegistryConnectionError( "Wrong configuration: Authentication to registry is needed!" ) # auth issue let's try some authentication get the auth type auth_type = None auth_details: Dict[str, str] = {} for key in auth_headers: if str(key).lower() == "www-authenticate": auth_type, auth_value = str(auth_headers[key]).split(" ", 1) auth_details = { x.split("=")[0]: x.split("=")[1].strip('"') for x in auth_value.split(",") } break if not auth_type: raise exceptions.RegistryConnectionError( "Unknown registry type: cannot deduce authentication method!" ) auth = BasicAuth(login=config.REGISTRY_USER, password=config.REGISTRY_PW) # bearer type, it needs a token with all communications if auth_type == "Bearer": # get the token token_url = URL(auth_details["realm"]).with_query( service=auth_details["service"], scope=auth_details["scope"] ) async with session.get(token_url, auth=auth) as token_resp: if not token_resp.status == 200: raise exceptions.RegistryConnectionError( "Unknown error while authentifying with registry: {}".format( str(token_resp) ) ) bearer_code = (await token_resp.json())["token"] headers = {"Authorization": "Bearer {}".format(bearer_code)} async with getattr(session, method.lower())( url, headers=headers ) as resp_wtoken: if resp_wtoken.status == 404: _logger.exception("path to registry not found: %s", url) raise exceptions.ServiceNotAvailableError(str(url)) if resp_wtoken.status > 399: _logger.exception( "Unknown error while accessing with token authorized registry: %s", str(resp_wtoken), ) raise exceptions.RegistryConnectionError(str(resp_wtoken)) resp_data = await resp_wtoken.json(content_type=None) resp_headers = resp_wtoken.headers return (resp_data, resp_headers) elif auth_type == "Basic": # basic authentication should not be since we tried already... async with getattr(session, method.lower())(url, auth=auth) as resp_wbasic: if resp_wbasic.status == 404: _logger.exception("path to registry not found: %s", url) raise exceptions.ServiceNotAvailableError(str(url)) if resp_wbasic.status > 399: _logger.exception( "Unknown error while accessing with token authorized registry: %s", str(resp_wbasic), ) raise exceptions.RegistryConnectionError(str(resp_wbasic)) resp_data = await resp_wbasic.json(content_type=None) resp_headers = resp_wbasic.headers return (resp_data, resp_headers) raise exceptions.RegistryConnectionError( f"Unknown registry authentification type: {url}" )