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-libOAuth2ClientCredentialsSession 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'sOAuth2ClientCredentialsSession`.
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:
OAuth2ClientCredentialsSession.update_token is called
OAuth2ClientCredentialsSession.authenticate is called
OAuth2ClientCredentialsSession.get_token is called
requests.Session.post is called (through inheritance) - this method calls self.request which OAuth2ClientCredentialsSession has overwritten
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
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.
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 theresilient-lib
OAuth2ClientCredentialsSession
class to handle authentication / make HTTP requests):... (the same request -> update_token -> authenticate -> get_token -> post lines were repeated many times)
After some digging into / debugging the integration code, as well as the resilient-lib
OAuth2ClientCredentialsSession
code (and therequests.Session
code, sinceOAuth2ClientCredentialsSession
inherits fromrequests.Session
) it appears to me that there's an issue withresilient_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 inOAuth2ClientCredentialsSession
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:
OAuth2ClientCredentialsSession.update_token
is calledOAuth2ClientCredentialsSession.authenticate
is calledOAuth2ClientCredentialsSession.get_token
is calledrequests.Session.post
is called (through inheritance) - this method callsself.request
whichOAuth2ClientCredentialsSession
has overwrittenOAuth2ClientCredentialsSession.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 againOAuth2ClientCredentialsSession.update_token
is called and the process is repeated until the maximum recursion depth is reachedSo 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.