-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: integration authz headers in Dirac client #87
Conversation
I think the general approach looks good and like the right way to go 👍 I'll do a specific review once you figure out the CI. |
533540a
to
adb2ddd
Compare
Here are the changes I performed to make
It is just for info in case there are better solutions. The issue related to DIRAC Integration tests is expected, I am going to make a PR once we are okay with the structure of this one. Update: |
1550268
to
5669464
Compare
src/diracx/client/aio/_patch.py
Outdated
] # Add all objects you want publicly available to users at this package level | ||
|
||
|
||
CREDENTIALS_PATH = Path.home() / ".cache" / "diracx" / "credentials.json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These settings probably should be in one of:
diracx.cli.__init__.py
because the CLI is the primary user for that locationdiracx.client.__init__.py
because so anybody using the client (cli, legacy dirac, tasks) may potentially use itdiracx.core.__init__.py
because it it really is such a crucial value that it could be here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I vote for the last one (and maybe naming it DEFAULT_CREDENTIALS_PATH
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually had a chat with @aldbr and actually what could make even more sense is to put it in the Preferences
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I put it in the Preferences
credentials.get("access_token"), credentials.get("expires_on") | ||
) | ||
|
||
async def close(self) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need to redefine all the methods below ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a docstring to explain, but basically because AsyncTokenCredential
is a Python protocol and we need to provide an implementation of the methods.
src/diracx/client/aio/_patch.py
Outdated
""" | ||
|
||
def __init__(self, **kwargs: Any) -> None: | ||
endpoint = get_diracx_preferences().url |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should still be possible to overwrite this and the client id
dff1cc7
to
cee3c34
Compare
The issue with the integration tests is related to the normal (non-aio) |
To get the CI green again I've pushed a workaround to |
ed8214a
to
85ecd9b
Compare
adf2704
to
f731204
Compare
f731204
to
2740864
Compare
I'm adding a comment to explain the latest changes because it is becoming hard to review and I am sorry for that:
|
This PR aims to enhance the
autorest
Dirac
client by encapsulating the configuration options such as the authorization headers. The primary purpose is to simplify code for thecli
developers.Note: the
Dirac
client is able to auto refresh the access token.Chosen solution
The solution is based on the
azure.core
architecture.We redefine 3 classes:
Dirac
: to encapsulate the endpoint and an authentication policyAsyncTokenCredential
: provide OAuth tokensAsyncBearerTokenCredentialPolicy
: an authentication policy which aims at adding the authorization headers to the requestsThis solution was chosen after thorough research and analysis, as it was deemed (by myself) the simplest way to incorporate authorization headers into requests.
Considered alternatives
azure-identity
The python autorest documentation recommends using a credential type from the
azure identity
package to initialize the client.The DeviceCodeCredentials seems adapted to our use case. It is able to obtain a token using the
device_code
flow and cache it. Then it is automatically refreshed when needed.Problem: it is tightly coupled with Azure applications.
DeviceCodeCredential
inherits fromInteractiveCredential
, which inherits fromMsalCredential
. There are mandatory non-standard parameters such astenant_id
. Setting it to""
orNone
does not help. The only option would have been to create new classes inheriting from the mentioned classes, which would have been inefficient.AzureAD
authentication librarymicrosoft-authentication-library-for-python seems to provide a generic OAuth2 library but does not automatically refresh access tokens. Furthermore, it would probably be tricky to integrate to the
Dirac
autorest client.authlib
in combination withazure.core
authlib
would help managing tokens. It is even able to automatically refresh access tokens.But the library would be limited in our context as the
Dirac
client is initialized each time a new command starts.