Skip to content
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: add Client.logout and context manager #381

Merged
merged 7 commits into from
Aug 17, 2023
Merged

Conversation

oleobal
Copy link
Contributor

@oleobal oleobal commented Aug 9, 2023

Summary

Add a Client.logout function, which deletes a token obtained by Client.login (if any).

Add a context manager, making the following snippet legal:

with Client(
    client_name="org-1",
    backend_type="remote",
    url="http://substra-backend.org-1.com:8000",
    username="org-1",
    password="p@sswr0d44",
) as client:
    pass

Requires Substra/substra-backend#698

Closes FL-1008

Notes

Please check if the PR fulfills these requirements

  • If necessary, the changelog has been updated
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • The commit message follows the conventional commit specification
  • For any breaking changes, companion PRs have been opened on the following repositories:

@linear
Copy link

linear bot commented Aug 9, 2023

FL-1008 Add logout function to Substra SDK

Context

Security assessment V7 (the Audit page on Notion has links to the detailed report)

Risk score: 3/12 (low)

After logging in using username and password with the Substra Python library, an API token is issued. However, the library does not offer a logout function, which means that users cannot end their authenticated sessions actively. Authenticated API tokens thus always remain active on the server until the timeout expires.

The Substra Python library should have a logout function allowing users to end sessions actively. The function needs to invalidate the API token on the server side and securely delete related session data on the client.

Specification

Add a new endpoint to the backend that revokes the current ImplicitBearerToken

Add a Client.logout function to Substra SDK that calls that endpoint

It would be nice to also add a context manager because it would look professional:

with Client(username, password) as client:
   pass

Acceptance criteria

Substra SDK has a Client.logout or similar function that revokes the token created by Client.login

@oleobal oleobal marked this pull request as ready for review August 9, 2023 15:30
@oleobal oleobal requested a review from a team as a code owner August 9, 2023 15:30
@oleobal
Copy link
Contributor Author

oleobal commented Aug 9, 2023

I'm unsure what to document or test exactly. This change is mostly transparent for users, and I would be mocking a lot of stuff.

Comment on lines +314 to +321
def __enter__(self):
return self

def __exit__(self, exc_type, exc_value, traceback):
self.logout()

def __del__(self):
self.logout()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure whether context manager is still needed with __del__ defined, but people online say not to rely on it and using with is preferable. However that does mean updating our documentation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What part of the documentation are you reffering to ?

Copy link
Contributor Author

@oleobal oleobal Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean that in the documentation all examples of the form:

client = Client(...)
do_stuff(client)

should be replaced with:

with Client(...) as client:
    do_stuff(client)

Copy link
Member

@ThibaultFy ThibaultFy Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some scripts (such as the examples) need the client for more than a thousand lines, so I would not replace the old version, maybe just indicate that the context manager is also a valid option ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it in the sdk.Client reference, under the username argument.

Signed-off-by: Olivier Léobal <[email protected]>
Copy link
Member

@ThibaultFy ThibaultFy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR :)

Concerning the fact that we define a logout function only for the remote backend, I am not 100% convince... There is a login method defined in locals backend too, I think for the hybrid mode. You should take a look at it to ensure what we should do for this mode I think. (cf sdk/backends/local/dal.py.

For the tests, you could check that the token is deleted the using the context manager with or when deleting the object (del client).
This test can be useful to mock minimally

def test_client_with_password(mocker):

substra/sdk/client.py Outdated Show resolved Hide resolved
Comment on lines +314 to +321
def __enter__(self):
return self

def __exit__(self, exc_type, exc_value, traceback):
self.logout()

def __del__(self):
self.logout()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What part of the documentation are you reffering to ?

Copy link
Member

@ThibaultFy ThibaultFy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few small comments and will be good to me ! do you think we need a run of CI on it before merging ? No strong opinion on it on my side.

CHANGELOG.md Outdated Show resolved Hide resolved
substra/sdk/backends/remote/rest_client.py Outdated Show resolved Hide resolved
substra/sdk/client.py Outdated Show resolved Hide resolved
Co-authored-by: Thibault Fouqueray <[email protected]>
Signed-off-by: Olivier Léobal <[email protected]>
@oleobal
Copy link
Contributor Author

oleobal commented Aug 17, 2023

@ThibaultFy

do you think we need a run of CI on it before merging ? No strong opinion on it on my side.

I ran one yesterday but let's run a new one just to be sure ^^

@ThibaultFy
Copy link
Member

@ThibaultFy

do you think we need a run of CI on it before merging ? No strong opinion on it on my side.

I ran one yesterday but let's run a new one just to be sure ^^

Ah ok ok :) you're not using the /e2e command ?

@oleobal
Copy link
Contributor Author

oleobal commented Aug 17, 2023

you're not using the /e2e command ?

I am, just from the backend PR instead of this one

Copy link
Member

@ThibaultFy ThibaultFy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks a lot :)

oleobal added a commit to Substra/substra-backend that referenced this pull request Aug 17, 2023
- Solve the issue of sometimes issuing tokens that are about to expire,
by just issuing an new token every time and relying on the SDK to clean them up

- Add a new `server.allowImplicitLogin` option, allowing node admins to
disable the option altogether in order to improve security practices.

- Extend `/active-api-tokens -X DELETE` to also be able to delete
`ImplicitBearerToken`, adding an `id` field to `ImplicitBearerToken` for
this purpose. This is to enable users to terminate their sessions, as
per security recommendations

Closes FL-1067, FL-1140

Companion to Substra/substra-documentation#336
Leveraged by Substra/substra#381

Signed-off-by: Olivier Léobal <[email protected]>
@oleobal oleobal merged commit e2916b9 into main Aug 17, 2023
5 checks passed
@oleobal oleobal deleted the feat/client-logout branch August 17, 2023 10:18
Comment on lines +125 to +126
except requests.exceptions.Timeout as e:
raise exceptions.Timeout.from_request_exception(e)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to retry on Timeout? Or is it already handled at a higher level?
In all cases, I'm not sure if we want to raise uncaught exceptions to the user, or just have a warning logged 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants