-
Notifications
You must be signed in to change notification settings - Fork 106
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
On each execute_get call, check age of auth token, reinitialize HubRestApi object if >= 1.5 hours. #118
base: master
Are you sure you want to change the base?
On each execute_get call, check age of auth token, reinitialize HubRestApi object if >= 1.5 hours. #118
Changes from all commits
92a57ca
ea0a704
03ead3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,8 @@ | |
|
||
''' | ||
import logging | ||
import os | ||
import time | ||
import requests | ||
import json | ||
from operator import itemgetter | ||
|
@@ -86,26 +88,32 @@ class HubInstance(object): | |
|
||
# TODO: What to do about the config file for thread-safety, concurrency | ||
configfile = ".restconfig.json" | ||
|
||
global root_dir | ||
# For refresh to find the .restconfig.json file upon reinitialization, | ||
# client script must be executed in the same directory | ||
root_dir = os.getcwd() | ||
refresh_token = False | ||
def __init__(self, *args, **kwargs): | ||
# Config needs to be an instance variable for thread-safety, concurrent use of HubInstance() | ||
self.config = {} | ||
|
||
try: | ||
self.config['baseurl'] = args[0] | ||
api_token = kwargs.get('api_token', False) | ||
if api_token: | ||
self.config['api_token'] = api_token | ||
else: | ||
self.config['username'] = args[1] | ||
self.config['password'] = args[2] | ||
self.config['insecure'] = kwargs.get('insecure', False) | ||
self.config['debug'] = kwargs.get('debug', False) | ||
|
||
if kwargs.get('write_config_flag', True): | ||
self.write_config() | ||
except Exception: | ||
self.read_config() | ||
self.read_config() | ||
self.refresh_token = kwargs.get('refresh_token') | ||
if not kwargs.get('refresh_token', False): | ||
try: | ||
self.config['baseurl'] = args[0] | ||
api_token = kwargs.get('api_token', False) | ||
if api_token: | ||
self.config['api_token'] = api_token | ||
else: | ||
self.config['username'] = args[1] | ||
self.config['password'] = args[2] | ||
self.config['insecure'] = kwargs.get('insecure', False) | ||
self.config['debug'] = kwargs.get('debug', False) | ||
|
||
if kwargs.get('write_config_flag', True): | ||
self.write_config() | ||
except Exception: | ||
self.read_config() | ||
|
||
if self.config['insecure']: | ||
requests.packages.urllib3.disable_warnings() | ||
|
@@ -123,6 +131,9 @@ def __init__(self, *args, **kwargs): | |
|
||
def read_config(self): | ||
try: | ||
#always return to the examples directory to read the config | ||
if not os.getcwd().endswith("examples"): | ||
os.chdir(root_dir) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could this potentially create a problem if you were calling this from another application that uses the blackduck library, rather than from the examples directory? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi, yes, this is a potential problem that I've been hoping to make progress on before merging. The root of the problem is that .restconfig is located in examples on the first HubRestApi object init. When a refresh actually does occur, .restconfig no longer exists in context at the time HubRestApi reinitializes itself, so I reset back to examples to ensure that .restconfig is available. There has to be a better approach, it's just not clear to me. Any ideas? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the .restonfig.json is written to (or read from) the current working directory. It is not hard-coded to anything. So, if I invoke a program in /Users/gsnyder/Projects/sage for instance, the .restonfig.json needs to be in the /Users/gsnyder/Projects/sage directory for it to be read. Or, if I was initializing the HubInstance using parameters, then the .restconfig.json would be written to that directory. Also, the config is saved in memory to self.config, so do we really need to read anything again? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the hardcoded part. Now, it works under the assumption that .restconfig.json is in the current working directory. |
||
with open('.restconfig.json','r') as f: | ||
self.config = json.load(f) | ||
except: | ||
|
@@ -151,6 +162,8 @@ def get_auth_token(self): | |
except json.decoder.JSONDecodeError as e: | ||
logger.exception("Authentication failure, could not obtain bearer token") | ||
raise Exception("Failed to obtain bearer token, check for valid authentication token") | ||
# set token expiration to 1.5h | ||
self.access_token_expiration = time.time() + 5200 | ||
return (bearer_token, csrf_token, None) | ||
else: | ||
authendpoint="/j_spring_security_check" | ||
|
@@ -162,6 +175,8 @@ def get_auth_token(self): | |
response = session.post(url, credentials, verify= not self.config['insecure']) | ||
cookie = response.headers['Set-Cookie'] | ||
token = cookie[cookie.index('=')+1:cookie.index(';')] | ||
# set token expiration to 1.5h | ||
self.access_token_expiration = time.time() + 5200 | ||
return (token, None, cookie) | ||
|
||
def _get_hub_rest_api_version_info(self): | ||
|
@@ -231,7 +246,27 @@ def get_limit_paramstring(self, limit): | |
|
||
def get_apibase(self): | ||
return self.config['baseurl'] + "/api" | ||
|
||
|
||
def reauthenticate(self, *args, **kwargs): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, this really isn't a good idea. It would be far better to rerun auth rather than explicitly reinitialising the class. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried rerunning the call to authenticate in my first attempt. I couldn't get it to work, I'll revisit. Thanks for taking a look! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may have unexpected side effects down the line. Generally speaking in python the only time you should need to manually call |
||
try: | ||
kwargs.update({"refresh_token":self.refresh_token}) | ||
self.__init__(self, *args, **kwargs) | ||
except Exception as e: | ||
print("There was an error when refreshing the token: {}".format(e)) | ||
return None | ||
else: | ||
return self | ||
|
||
class Decorators(): | ||
@staticmethod | ||
def refresh_token(decorated): | ||
def wrapper(hub_api_object, *args, **kwargs): | ||
if time.time() > hub_api_object.access_token_expiration and hub_api_object.refresh_token: | ||
hub_api_object.reauthenticate(hub_api_object, *args, **kwargs) | ||
return decorated(hub_api_object, *args, **kwargs) | ||
|
||
return wrapper | ||
|
||
### | ||
# | ||
# Role stuff | ||
|
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 skip the try/except block?
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 think that try/except block is checking if the .restconfig exists, if it doesn't check the args and write it.
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 keyword argument named refresh_token that the client script can pass on instantiation. Refreshing the token is now off by default.