From 6a5e40d4c23292a4c7ada704d1ecb3a1ca741479 Mon Sep 17 00:00:00 2001 From: Gerry Nelson <45608078+gerrynelson63@users.noreply.github.com> Date: Wed, 23 Nov 2022 13:15:32 -0500 Subject: [PATCH] Dev/refreshtoken (#123) * add token refresh * json.dumps * data * savetoken * fix folder id bug * fix index Co-authored-by: cloud-user --- getfolderid.py | 4 +-- savetoken.py | 65 ++++++++++++++++++++++++++++++++++++++++ sharedfunctions.py | 75 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 135 insertions(+), 9 deletions(-) create mode 100755 savetoken.py diff --git a/getfolderid.py b/getfolderid.py index eebc3df..62489fa 100755 --- a/getfolderid.py +++ b/getfolderid.py @@ -58,5 +58,5 @@ if output_style=='simple': print("Id = "+targets[0]) print("URI = "+targets[1]) print("Path = "+targets[2]) - print("CreatedBy = "+targets[3]) -else: printresult(targets[4],output_style) + print("CreatedBy = "+targets[4]) +else: printresult(targets[3],output_style) diff --git a/savetoken.py b/savetoken.py new file mode 100755 index 0000000..90dbd16 --- /dev/null +++ b/savetoken.py @@ -0,0 +1,65 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Saves the access token from the CLI credentials file to a file in the format expected by the SAS Vscode extension +# The token is saved to a file ~/.sas/_token.txt +# + +import sys +import json +import os + +from sharedfunctions import file_accessible, getprofileinfo + + #get authentication information for the header +credential_file=os.path.join(os.path.expanduser('~'),'.sas','credentials.json') + +# check that credential file is available and can be read +access_file=file_accessible(credential_file,'r') + +if access_file==False: + oaval=None + print("ERROR: Cannot read authentication credentials at: ", credential_file) + print("ERROR: Try refreshing your token with sas-admin auth login") + sys.exit() + +with open(credential_file) as json_file: + data = json.load(json_file) + +# profile + +cur_profile=os.environ.get("SAS_CLI_PROFILE","NOTSET") + +if cur_profile=="NOTSET": + print("SAS_CLI_PROFILE environment variable not set, using Default profile") + cur_profile='Default' +else: + print("SAS_CLI_PROFILE environment variable set to profile "+ cur_profile) + + +ssl_file=os.environ.get("SSL_CERT_FILE","NOTSET") + +if ssl_file=="NOTSET": + print("SSL_CERT_FILE environment variable not set.") +else: + print("SSL_CERT_FILE environment variable set to profile "+ ssl_file) + + +r_ssl_file=os.environ.get("REQUESTS_CA_BUNDLE","NOTSET") + +if r_ssl_file=="NOTSET": + print("REQUESTS_CA_BUNDLE environment variable not set.") +else: + print("REQUESTS_CA_BUNDLE environment variable set to profile "+ r_ssl_file) + +if cur_profile in data: + + oauthToken=data[cur_profile]['access-token'] + token_file=os.path.join(os.path.expanduser('~'),'.sas',cur_profile+"_token.txt") + + with open(token_file, "w") as tokenfile: + tokenfile.write(oauthToken) + + print("NOTE: token saved to "+token_file) + + diff --git a/sharedfunctions.py b/sharedfunctions.py index 1e55431..9209250 100755 --- a/sharedfunctions.py +++ b/sharedfunctions.py @@ -108,6 +108,8 @@ def callrestapi(reqval, reqtype, acceptType='application/json', contentType='app # get the auth token oaval=getauthtoken(baseurl) + #print(oaval) + # build the authorization header head= {'Content-type':contentType,'Accept':acceptType} head.update({"Authorization" : oaval}) @@ -204,7 +206,7 @@ def getfolderid(path): targeturi="/folders/folders/"+targetid targetcreatedBy=result['createdBy'] - return [targetid,targeturi,targetname,targetcreatedBy,result] + return [targetid,targeturi,targetname,result,targetcreatedBy] @@ -281,8 +283,7 @@ def getauthtoken(baseurl): with open(credential_file) as json_file: data = json.load(json_file) - type(data) - + # the sas-admin profile init creates an empty credential file # check that credential is in file, if it is add it to the header, if not exit @@ -296,7 +297,8 @@ def getauthtoken(baseurl): if cur_profile in data: oauthToken=data[cur_profile]['access-token'] - + refreshToken=data[cur_profile]['refresh-token'] + oauthTokenType="bearer" oaval=oauthTokenType + ' ' + oauthToken @@ -304,21 +306,80 @@ def getauthtoken(baseurl): head= {'Content-type':'application/json','Accept':'application/json' } head.update({"Authorization" : oaval}) - # test a connection to rest api if it fails exit + # test a connection to rest api if it fails try using the refresh token to re-authenticate r = requests.get(baseurl,headers=head) + if (400 <= r.status_code <=599): + + + #do refresh token request + #curl -k "${INGRESS_URL}/SASLogon/oauth/token" -H "Accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -u "sas.cli:" \-d "grant_type=refresh_token&refresh_token=${REFRESH_TOKEN}" + + #did it work + + # set oauthToken again from the output of the request + + # update oauthToken in credentials file from the output of the request + + refresh_headers = {"Accept": "application/json","Content-Type": "application/x-www-form-urlencoded",} + + client_id="sas.cli" + client_secret="" + + refresh_data = {} + refresh_data["grant_type"] = "refresh_token" + refresh_data["refresh_token"] = refreshToken + + response = requests.request("POST", url=baseurl+"/SASLogon/oauth/token", data=refresh_data, headers=refresh_headers,auth=(client_id, client_secret)) + + if (400 <= response.status_code <=599): + + oaval=None + print(r.text) + print("ERROR: cannot connect to "+baseurl+" with refresh token is your refresh token expired?") + print("ERROR: Try refreshing your token with the CLI auth login") + sys.exit() + + else: + + # set new token and update credentials.json + result=response.json() + newtoken=result["access_token"] + expires_in=result["expires_in"] + + # calculate new expiration + newexpiry=(dt.utcnow()+td(seconds=expires_in)).strftime('%Y-%m-%dT%H:%M:%SZ') + oaval=oauthTokenType + ' ' + newtoken + + # write the new token to the credentials file + data[cur_profile]['access-token']=newtoken + data[cur_profile]['expiry']=newexpiry + + filecontent=json.dumps(data,indent=2) + with open(credential_file, "w") as outfile: + outfile.write(filecontent) + + + + head= {'Content-type':'application/json','Accept':'application/json' } + head.update({"Authorization" : oaval}) + + # test a connection to rest api again if it fails exit + # tell user to re-authenticate with the sas-viya CLI + + r = requests.get(baseurl,headers=head) if (400 <= r.status_code <=599): oaval=None print(r.text) print("ERROR: cannot connect to "+baseurl+" is your token expired?") - print("ERROR: Try refreshing your token with sas-admin auth login") + print("ERROR: Try refreshing your token with the Viya CLI auth login") sys.exit() else: oaval=None print("ERROR: access token not in file: ", credential_file) - print("ERROR: Try refreshing your token with sas-admin auth login") + print("ERROR: Try refreshing your token with Viya CLI auth login") sys.exit() return oaval