BookmarkSubscribeRSS Feed

Discover Your Data with SAS Information Catalog APIs from Python – Access

Started ‎02-11-2024 by
Modified ‎07-17-2024 by
Views 1,380

Navigating through a sea of data assets can be a daunting task. SAS Information Catalog is your navigator in this journey, allowing you to discover, search, and manage your SAS Viya assets efficiently. When a data asset is discovered, hundreds of metrics are calculated. Imagine accessing these metrics with a simple command, downloading them, or even using them in a report or a flow. This blog series will guide you through the process of leveraging the SAS Information Catalog REST APIs from Python to learn more about your SAS Viya data assets. This post, in particular, will focus on acquiring an access token using a method revised in 2023.

 

 

SAS Information Catalog in Two Minutes

 

If you're new to SAS Information Catalog, here's a quick rundown. If you prefer to watch a video, check out SAS Demo | Top Data Questions You Can Answer with SAS Information Catalog or How to Use SAS Information Catalog. If you prefer to read, the catalog:

  • Allows you to discover, search, and manage your SAS Viya assets, such as data, tables, files, SAS Visual Analytics reports, SAS models, SAS decisions, SAS Studio flows, or code files.
  • You can search the catalog for your assets using keywords (free text search) or calculated metrics and their values (faceted search).
  • You can also view the information privacy status of your assets, which is calculated by the catalog.
  • The catalog produces numerous metrics about your data assets at both the table and column levels.
  • Agents, a set of jobs, drive the discovery process. They list the contents of a library, apply any filters, and then start calculating the metrics.
  • These metrics are then sent to an index that you can use for searching.

 

Why Use Catalog APIs?

 

Despite having comprehensive interfaces in SAS Information Catalog, there might be a need for custom reporting or workflows based on specific asset characteristics. SAS Information Catalog APIs, now made public, are the solution to this challenge.

 

Get an Access Token

 

Despite the availability of resources, getting a SAS Viya access token can sometimes be confusing and many users get stuck at this stage. The SAS Software GitHub page explains a simple method to get an access token to work with SAS Viya REST APIs.

 

However, there's a more secure and efficient method, described by Joe Furbee in Register Client and Create Access Token. I prefer this method as it excludes the password from the Python program, making the program more "Git-ready". The method also registers a client, uses an authorization code, and a TLS certificate to secure data in transit.

 

Recorded Demonstration

 

For a more visual understanding of the process, you can watch the following recorded demonstration:

 

 


Python Program


Here’s the complete code to get an access token and a refresh token.

# Run instructions
"""
Using Joe Furbee's approach: https://github.com/sassoftware/rest-api-use-cases/blob/main/python/authentication/registerClient_generateToken_Python_2023.ipynb
https://blogs.sas.com/content/sgf/2023/02/07/authentication-to-sas-viya/
"""
print('\nGetting parameters from the command line\n')

# 1 Packages
import requests, json, os, base64, sys

# 2. Arguments
print ("Number of arguments:", len(sys.argv), "arguments\n")
#print ("Argument List:", str(sys.argv))
baseURL=str(sys.argv[1])
client_id=str(sys.argv[2])
client_secret=str(sys.argv[3])
admin_user=str(sys.argv[4])
admin_password=str(sys.argv[5])
pem_path=str(sys.argv[6])

print()
print ("\nWe are going to use a certificate: ", pem_path)


# 3. Construct Variables
authUri="/SASLogon/oauth/token"

print('\nYour SAS VIYA host is ', baseURL)
print ('\nAuth URL', authUri)

# Get a BEARER_TOKEN to delete and register a client

print('\nGet a BEARER_TOKEN to register a client\n')

# generate API call for register access token
url = f"{baseURL}/SASLogon/oauth/token"

payload = f"grant_type=password&username={admin_user}&password={admin_password}"
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Authorization': 'Basic c2FzLmNsaTo='
}

# process the results
response = requests.request("POST", url, headers=headers, data=payload, verify=pem_path)

register_access_token = json.loads(response.text)['access_token']
print(json.dumps(response.json(), indent=4, sort_keys=True))

headers = {
'Content-Type': 'application/json',
'Authorization': "Bearer " + register_access_token
}

"""
# Delete the client if it already exists
print()
print(f"Delete the client {client_id} if it exists, using the BEARER_TOKEN")
print()

print(baseURL, "client", client_id)

response = requests.request("DELETE", f"{baseURL}/SASLogon/oauth/clients/{client_id}", headers=headers, verify=pem_path)
print(json.dumps(response.json(), indent=4, sort_keys=True))
"""

# Register the client using the BEARER_TOKEN
print(f"\nRegister the client {client_id} using the BEARER_TOKEN\n")

# create API call payload data
payload='{"client_id": "' + client_id +'","client_secret": "'+ client_secret +'","scope": ["openid", "uaa.user"],"authorized_grant_types": ["authorization_code","refresh_token"],"redirect_uri": "urn:ietf:wg:oauth:2.0:oob","access_token_validity": "43199"}'

# generate API call for register access token
url = f"{baseURL}/SASLogon/oauth/clients"


# REGISTER THE CLIENT process the results
response = requests.request("POST", url, headers=headers, data=payload, verify=pem_path)
print(json.dumps(response.json(), indent=4, sort_keys=True))

# Create an access token using the client and an authorization code
print('\nCreate an access token using the client and an authorization code\n')

# create the authorization url
codeURL = baseURL + "/SASLogon/oauth/authorize?client_id=" + client_id + "&response_type=code"

# encode the client string
client_string = client_id + ":" + client_secret
message_bytes = client_string.encode('ascii')
base64_bytes = base64.b64encode(message_bytes)
base64_message = base64_bytes.decode('ascii')

# prompt with instructions and entry for auth code
print(f"* Please visit the following site {codeURL}")
print("* If provided a login prompt, add your SAS login credentials")
print("* Once authenticated, you'll be redirected to an authorization screen, check all of the boxes that appear")
print("* This will result in a short string of numbers and letters such as `VAxVFVEnKr`; this is your authorization code; copy the code")
code = input("Please enter the authorization code you generated through the previous instructions, and then press Enter: ")

# generate API call for access token
url = f"{baseURL}/SASLogon/oauth/token#authorization_code"
payload = "grant_type=authorization_code&code=" + code
headers = {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': "Basic " + base64_message
}

# process the results
response = requests.request("POST", url, headers=headers, data=payload, verify=pem_path)
access_token = json.loads(response.text)['access_token']
refresh_token = json.loads(response.text)['refresh_token']
print(json.dumps(response.json(), indent=4, sort_keys=True))


# Create directory

#directory = os.getcwd()
directory = 'api'
if not os.path.exists("api/"):
    os.mkdir("api/")

# Create access_token.txt file

with open(directory + '/access_token.txt', 'w') as f:
    f.write(access_token)
print('\nThe access token was stored for you as ' + directory + '/access_token.txt\n')

# Create refresh_token.txt file

with open(directory + '/refresh_token.txt', 'w') as f:
    f.write(refresh_token)
print('\nThe refresh token was stored for you as ' + directory + '/refresh_token.txt\n')


Steps in the "2023" method:

 

  1. Get a BEARER_TOKEN to register (or delete) a client.
  2. Delete the client if it exists - commented out, as not relevant when running a first time.
  3. Register the client gel_app.
  4. Create an access token using the registered client and an authorization code.
  5. Visit a web-page, select the scopes and generate the authorization code.
  6. Paste the authorization code and get an access token and a refresh token.

 

Please note, you must remove statements that print the token from your production code. Those are there just for debugging.

 

Run the Program

 

In a Bash terminal on a Windows machine, you can run the program with the parameters you've set.

 

SASUSER=fill_in_here # SAS user
SASPASS=fill_in_here # SAS user password
CLIENTSECRET=fill_in_here # client secret
# Certificate on a Windows machine and executable is python
python get_token_2023.py https://my_sas_viya_url.sas.com gel_app $CLIENTSECRET $SASUSER $SASPASS 'C:\Users\myuser\Downloads\gelenv_trustedcerts.pem'

 

A SAS Viya certificate is used here, in the form of a .pem file. The .pem file was copied in the 'C:\Users\...\' folder.

 

In a Bash terminal on a Linux machine, the above statement would be:

 

SASUSER=fill_in_here # SAS user
SASPASS=fill_in_here # SAS user password
CLIENTSECRET=fill_in_here # client secret
# Certificate on a Linux machine and executable is python3
python3 get_token_2023.py https://my_sas_viya_url.sas.com gel_app $CLIENTSECRET $SASUSER $SASPASS /home/my_user/.certs/gelenv_trustedcerts.pem

 

A SAS Viya certificate is used here, in the form of a .pem file. The .pem file is assumed to be present in the '/home/myuser/' folder.

 

Refresh Token

 

Access tokens have a 1-hour time-to-live (ttl) by default, so it's common to use a refresh token to generate a new access token. The refresh token itself has a 90-day ttl, while the authorization code is good for 30 minutes and single use. The access token generated can be transferred to other notebooks, programs and used for external API calls.

 

Get an Access Token with a Refresh Token

 

You can use a refresh token to get an access token when the latter expires.

 

# 1 Packages
import requests, json, os, base64, sys

# 2. Arguments
print ("Number of arguments:", len(sys.argv), "arguments")
#print ("Argument List:", str(sys.argv))
baseURL=str(sys.argv[1])
client_id=str(sys.argv[2])
client_secret=str(sys.argv[3])
pem_path=str(sys.argv[4])
print ("\nWe are going to use a certificate: ", pem_path)

# encode client string
client_string = client_id + ":" + client_secret
message_bytes = client_string.encode('ascii')
base64_bytes = base64.b64encode(message_bytes)
base64_message = base64_bytes.decode('ascii')

# 3. Construct Variables
authUri="/SASLogon/oauth/token#refresh_token"
print('Your SAS VIYA host is ', baseURL, '\n')
print ('\nRefresh the access token by using the refresh token\n')
url = baseURL + authUri
# read the refresh token
directory = 'api'

print('\nRetrieving the saved refresh token\n')
with open("api/refresh_token.txt", "r", encoding="UTF-8") as f:
    refresh_token = f.read()
#print(refresh_token)

payload = "grant_type=refresh_token&refresh_token=" + refresh_token
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': 'application/json',
  'Authorization': "Basic " + base64_message
}

response = requests.request("POST", url, headers=headers, data=payload, verify=pem_path)
#print(response.text)

# process the results
response = requests.request("POST", url, headers=headers, data=payload, verify=pem_path)
access_token = json.loads(response.text)['access_token']
print(json.dumps(response.json(), indent=4, sort_keys=True))

# Create access_token.txt file

with open(directory + '/access_token.txt', 'w') as f:
    f.write(access_token)
print('\nThe access token was stored for you as ' + directory + '/access_token.txt\n')

 

Please note, you must remove statements that print the token. Those are there just for debugging.

 

Run the Program

 

In a Bash terminal on a Windows machine, you can run the program with the parameters you've set.

 

Note that you no longer need the user and the password with the refresh token method. The client, the secret and the refresh token itself are enough to get you an access token. In all the subsequent posts, we will use the refresh token to get a new access token.

 

CLIENTSECRET=fill_in_here # client secret
# Certificate on a Windows machine and executable is python
python refresh_token_2023.py https://my_sas_viya_url.sas.com gel_app $CLIENTSECRET 'C:\Users\myuser\Downloads\gelenv_trustedcerts.pem'

 

In a Bash terminal on a Linux machine, you can run the program with the parameters you've set.

 

CLIENTSECRET=fill_in_here # client secret
# Certificate on a Linux machine and executable is python3
python get_token_2023.py https://my_sas_viya_url.sas.com gel_app $CLIENTSECRET $SASUSER $SASPASS /home/my_user/.certs/gelenv_trustedcerts.pem

 

Conclusions

 

Learning how to harness the power of the SAS Information Catalog APIs can unlock a new level of efficiency and customization in managing your SAS Viya assets. By calling them from Python you can open the door to new integrations. This tutorial on acquiring an access token is the first step in that journey. Stay tuned for more in-depth discussions and tutorials in this series.

 

What to Read Next

 

Read the following post  in the series: Download Metadata and Metrics with SAS Information Catalog APIs from Python.

 

Acknowledgements

 

  • Thanks to my colleaque @joeFurbee  for all his work in this space.

 

Thank you for your time reading this post. If you liked the post, give it a thumbs up! Please comment and tell us what you think about having conversations with your data. If you wish to get more information, please write me an email.

Version history
Last update:
‎07-17-2024 08:25 PM
Updated by:
Contributors

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

Free course: Data Literacy Essentials

Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning  and boost your career prospects.

Get Started

Article Tags