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

resilient-lib OAuth2ClientCredentialsSession.update_token method causes infinite loop #17

Open
lmahoney1 opened this issue Apr 22, 2021 · 0 comments

Comments

@lmahoney1
Copy link
Contributor

Description

I was getting the following stack trace after the fn_microsoft_security_graph integration ran for ~ 1 hour (this integration uses an instance of the resilient-lib OAuth2ClientCredentialsSession class to handle authentication / make HTTP requests):

Traceback (most recent call last):
File "/usr/lib64/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/usr/lib64/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "/opt/app-root/lib/python3.6/site-packages/fn_microsoft_security_graph/components/microsoft_security_graph_alerts_integrations.py", line 198, in msg_polling_thread
alert_list = get_alerts(self.options, self.Microsoft_security_graph_helper)
File "/opt/app-root/lib/python3.6/site-packages/fn_microsoft_security_graph/components/microsoft_security_graph_alerts_integrations.py", line 290, in get_alerts
r = ms_graph_helper.ms_graph_session.get(url)
File "/opt/app-root/lib/python3.6/site-packages/requests/sessions.py", line 555, in get
return self.request('GET', url, **kwargs)
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 140, in request
self.update_token()
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 126, in update_token
self.client_secret, self.scope, self.proxies)
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 86, in authenticate
r = self.get_token(token_url, client_id, client_secret, scope, proxies)
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 118, in get_token
return self.post(token_url, data=post_data, proxies=proxies)
File "/opt/app-root/lib/python3.6/site-packages/requests/sessions.py", line 590, in post
return self.request('POST', url, data=data, json=json, **kwargs)
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 140, in request
self.update_token()

... (the same request -> update_token -> authenticate -> get_token -> post lines were repeated many times)

File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 140, in request
self.update_token()
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 126, in update_token
self.client_secret, self.scope, self.proxies)
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 86, in authenticate
r = self.get_token(token_url, client_id, client_secret, scope, proxies)
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 118, in get_token
return self.post(token_url, data=post_data, proxies=proxies)
File "/opt/app-root/lib/python3.6/site-packages/requests/sessions.py", line 590, in post
return self.request('POST', url, data=data, json=json, **kwargs)
File "/opt/app-root/lib/python3.6/site-packages/resilient_lib/components/oauth2_client_credentials_session.py", line 139, in request
if self.expiration_time < time.time():
RecursionError: maximum recursion depth exceeded in comparison

After some digging into / debugging the integration code, as well as the resilient-lib OAuth2ClientCredentialsSession code (and the requests.Session code, since OAuth2ClientCredentialsSession inherits from requests.Session) it appears to me that there's an issue with resilient_lib's OAuth2ClientCredentialsSession`.

The error happens an hour after running as that's when the initial bearer token we get expires. The next time we try to get graph alerts after the bearer token has expired, the request method in OAuth2ClientCredentialsSession identifies that the bearer token is expired and that a new one needs to be retrieved, however this functionality appears to be broken.

Below is the process for retrieving a new bearer token:

  1. OAuth2ClientCredentialsSession.update_token is called
  2. OAuth2ClientCredentialsSession.authenticate is called
  3. OAuth2ClientCredentialsSession.get_token is called
  4. requests.Session.post is called (through inheritance) - this method calls self.request which OAuth2ClientCredentialsSession has overwritten
  5. OAuth2ClientCredentialsSession.request is called - Here's the issue, this method identifies that the bearer token is expired, and starts the process to retrieve a new bearer token again
  6. OAuth2ClientCredentialsSession.update_token is called and the process is repeated until the maximum recursion depth is reached

So the request to renew the bearer token is never sent, and there ends up being an infinite recursion loop.

Describe How to Reproduce

Try to make a request with an instance of resilient-lib.OAuth2ClientCredentialsSession after the initial bearer token retrieved expires.

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

No branches or pull requests

1 participant