diff --git a/pulp-glue/pulp_glue/common/authentication.py b/pulp-glue/pulp_glue/common/authentication.py index e2c201290..c6c9b9d55 100644 --- a/pulp-glue/pulp_glue/common/authentication.py +++ b/pulp-glue/pulp_glue/common/authentication.py @@ -7,14 +7,20 @@ import requests -class OAuth2Auth(requests.auth.AuthBase): - - def __init__(self, *args: t.List[t.Any], **kwargs: t.Dict[t.Any, t.Any]): - self.client_id = kwargs.get("username") - self.client_secret = kwargs.get("password") - self.flow: t.Dict[t.Any, t.Any] = kwargs["flow"] - self.token_url = self.flow["flows"]["clientCredentials"]["tokenUrl"] - self.scope = [*self.flow["flows"]["clientCredentials"]["scopes"]][0] +class OAuth2ClientCredentialsAuth(requests.auth.AuthBase): + def __init__( + self, + client_id: str = "", + client_secret: str = "", + token_url: str = "", + scopes: t.List[str] = [], + *args: t.List[t.Any], + **kwargs: t.Dict[t.Any, t.Any], + ): + self.client_id = client_id + self.client_secret = client_secret + self.token_url = token_url + self.scopes = scopes self.token: t.Dict[t.Any, t.Any] = {} def __call__(self, request: requests.PreparedRequest) -> requests.PreparedRequest: @@ -77,7 +83,7 @@ def retrieve_token(self) -> None: data = { "client_id": self.client_id, "client_secret": self.client_secret, - "scope": self.scope, + "scope": " ".join(self.scopes), "grant_type": "client_credentials", } diff --git a/pulp-glue/pulp_glue/common/openapi.py b/pulp-glue/pulp_glue/common/openapi.py index 6f00e214a..b7c538d37 100644 --- a/pulp-glue/pulp_glue/common/openapi.py +++ b/pulp-glue/pulp_glue/common/openapi.py @@ -45,6 +45,30 @@ class UnsafeCallError(OpenAPIError): pass +class OpenAPISecurityScheme: + def __init__(self, security_scheme: t.Dict[str, str]): + self.security_scheme = security_scheme + self.type: str = "" + self.description: str = "" + self.flows: t.Optional[t.Dict[str, str]] + + self.parse() + + def parse(self): + self.type = self.security_scheme["type"] + self.description = self.security_scheme.get("description", "") + + if self.type == "oauth2": + self.flows = self.security_scheme.get("flows") + if clientCredentials := self.flows.get("clientCredentials"): + self.flow_type: str = "clientCredentials" + self.token_url: str = clientCredentials.get("tokenUrl") + self.scopes: t.List[str] = list(clientCredentials.get("scopes").keys()) + + if self.type == "http": + self.scheme = self.security_scheme["scheme"] + + class AuthProviderBase: """ Base class for auth providers. @@ -79,8 +103,11 @@ def __call__( authorized_schemes_types.add(security_schemes[name]["type"]) if "oauth2" in authorized_schemes_types: - oauth_flow = [flow for flow in authorized_schemes if flow["type"] == "oauth2"][0] - result = self.auth(oauth_flow) + oauth_flow = OpenAPISecurityScheme( + [flow for flow in authorized_schemes if flow["type"] == "oauth2"][0] + ) + if oauth_flow.flow_type == "clientCredentials": + result = self.auth(oauth_flow) if result: return result elif "http" in authorized_schemes_types: diff --git a/pulpcore/cli/common/generic.py b/pulpcore/cli/common/generic.py index 401e7f761..96a7208d3 100644 --- a/pulpcore/cli/common/generic.py +++ b/pulpcore/cli/common/generic.py @@ -10,7 +10,7 @@ import requests import schema as s import yaml -from pulp_glue.common.authentication import OAuth2Auth +from pulp_glue.common.authentication import OAuth2ClientCredentialsAuth from pulp_glue.common.context import ( DATETIME_FORMATS, DEFAULT_LIMIT, @@ -238,8 +238,11 @@ def auth(self, flow: t.Dict[t.Any, t.Any]) -> t.Optional[requests.auth.AuthBase] if self.pulp_ctx.password is None: self.pulp_ctx.password = click.prompt("Password/ClientSecret") - return OAuth2Auth( - username=self.pulp_ctx.username, password=self.pulp_ctx.password, flow=flow + return OAuth2ClientCredentialsAuth( + client_id=self.pulp_ctx.username, + client_secret=self.pulp_ctx.password, + token_url=flow.token_url, + scopes=flow.scopes, )