pulp / pulp-cli

https://docs.pulpproject.org/pulp_cli/
GNU General Public License v2.0
36 stars 42 forks source link

Add OAuth2 ClientCredentials flow support #1013

Closed decko closed 3 months ago

decko commented 4 months ago

This work adds OAuth2 ClientCredentials grant flow support to the Pulp-CLI. Closes #926


We're going with the short-term pragmatic approach, and reserving the right to completely refactor this whole area soon


As test strategy, we have two options here:

1- Use the responses lib (link here), a library that mocks the requests lib. With that we can intercept calls to a IdP mock to obtain a token, and then intercept the call to a Pulp instance and assert that there's the access_token being used with the Authorization header.

2- Mock an IdP using nginx rewrite module to return a 200 Ok message with an appropriate response to the token request. Together we need to configure the pulp server to provide the proper URL to allow pulp-cli to request a token and test an authorized operation on it.

dkliban commented 3 months ago

@decko @mdellweg I used this PR to interact with our deployment that uses oauth2 for authentication. I set the username to client_id and the password to client_secret. I was able to create a domain, a repository, a remote, and sync the repository. Thanks for this awesome feature!

dkliban commented 3 months ago

I accidentally used wrong credentials and got the following traceback:

Traceback (most recent call last):
  File "/home/dkliban/insights-venv/bin/pulp", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulpcore/cli/common/generic.py", line 326, in invoke
    return super().invoke(ctx)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulpcore/cli/common/generic.py", line 326, in invoke
    return super().invoke(ctx)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulpcore/cli/common/generic.py", line 326, in invoke
    return super().invoke(ctx)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulpcore/cli/common/generic.py", line 326, in invoke
    return super().invoke(ctx)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)   
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/decorators.py", line 92, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/decorators.py", line 92, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulpcore/cli/common/generic.py", line 1289, in callback
    result = entity_ctx.list(limit=limit, offset=offset, parameters=kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulp-glue/pulp_glue/common/context.py", line 807, in list
    result: t.Mapping[str, t.Any] = self.call("list", parameters=payload)
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulp-glue/pulp_glue/common/context.py", line 609, in call
    return self.pulp_ctx.call(
           ^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulp-glue/pulp_glue/common/context.py", line 375, in call
    result = self.api.call(
             ^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulp-glue/pulp_glue/common/openapi.py", line 778, in call
    response: requests.Response = self._session.send(request)
                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/requests/sessions.py", line 710, in send
    r = dispatch_hook("response", hooks, r, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/insights-venv/lib64/python3.12/site-packages/requests/hooks.py", line 30, in dispatch_hook
    _hook_data = hook(hook_data, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dkliban/devel/pulp-cli/pulp-glue/pulp_glue/common/authentication.py", line 44, in handle401
    self.retrieve_token()
  File "/home/dkliban/devel/pulp-cli/pulp-glue/pulp_glue/common/authentication.py", line 93, in retrieve_token
    self.token["issued_at"] = datetime.now().isoformat()
    ~~~~~~~~~~^^^^^^^^^^^^^
TypeError: 'NoneType' object does not support item assignment
decko commented 3 months ago

Thanks @dkliban. We worked on that case and CLI is handling it fine now. Thanks.