SailPoint - Python Library¶

Pre-Requisites¶

  1. Install python on your workstation.
  2. Install the python module sailpoint - Ensure you have the most up to date version
    pip install sailpoint-1.X-py3-none-any.whl
  1. It is also recommended that you install the rich python module. This will allow you to print json and other python objects in a nice, tidy and readable format.
    pip install rich
  1. Within IDN navigate to Preferences->Personal Access Tokens and create an access token

Now you should be ready to continue.

Getting the library set up¶

You will need to use the information from the token you set up in IDN, and populate the values below:

In [ ]:
from sailpoint.util import IDN
from rich import print
my_idn_settings = {
    "secret": "0123abc0123abc0123abc0123abc0123abc0123abc0123abc0123abc0123abcd",
    "client_id": "abc123abaasd123abcd123abac123",
    "tenant": "mytest-sb"
}
idn = IDN(**my_idn_settings)

Alternatively if you prefer to not include the access token information in your script files, you can add this to a file in your home directory.

Create a file in your home directory: eg. C:\Users\dpeters\.idn_api with the contents as follows: (replacing the values with your access token information)

{
    "secret": "0123abc0123abc0123abc0123abc0123abc0123abc0123abc0123abc0123abcd",
    "client_id": "abc123abaasd123abcd123abac123",
    "tenant": "mytest-sb"
}

With this file in place, the sailpoint python module will pick up the connection details automatically and you can initialize the library without having to specify these details.

You should be able to run the following code without any errors.

In [1]:
from sailpoint.util import IDN
from rich import print
idn = IDN()

Help documentation in the python library¶

Help documentation is embedded in the python library.

To obtain the help information you can run the python help() function.

To print the documentation for the entire module you could run the following:

help(idn)

Or you can alternatively just run the help function for the specific method you are interested in:

In [2]:
help(idn.get_user_by_name)
Help on method get_user_by_name in module sailpoint.util:

get_user_by_name(name) method of sailpoint.util.IDN instance
    Gets the user by their name
    
    You can also include wildcards such as: Dave*
    Search is case insensitive
    
    Parameters
    --------------------
    name: string
        The name to search
    
    Results
    --------------------
    identities: list of identities

Try listing an identity¶

To get the users identity by name you can run this function according to the help message.

Sepcify a single string parameter to the function:

In [ ]:
print(idn.get_user_by_name('Jason Bourne'))

Listing source systems¶

If you run the list_sources function, you will get a lot of information back. Feel free to try it below by uncommenting the idn.list_sources() function call.

However, maybe you want to use a little script to retrieve only the information you want to see.

In [ ]:
# print(idn.list_sources())

# running the above will list a lot of information, perhaps we just want the name and descriptions of the sources
# We can use a little script to do this:

for source in idn.list_sources():
    print("Source: " + source['name'] + " Description: " + source['description'])

Listing unhealthy sources¶

You can build upon the above function and list only the unhealthy sources.

Say for example you would like to build a script that is run on a hourly basis that lists unhealthy sources and if one is found, you would like to automate some response. This could be sending an email, or creating a jira ticket. In this case we will just print out the name of the source that is not healthy. When considering scripts like this, be aware of the out-of-the-box functionality build into IDN. For example IDN has System Notifications which may be sufficient for what you need to accomplish.

In [ ]:
idn.list_sources()
for source in idn.list_sources():
    if not source['healthy']:
        print(f"Source is not healthy: {source['name']}")

A practical example - Account Aggregation¶

Now lets do something more useful that you can not do through the IDN UI.

Say we need to run a non-optimized account aggregation.

We can use the function run_acct_aggregation.

Use the help function to read about this:

In [3]:
help(idn.run_acct_aggregation)
Help on method run_acct_aggregation in module sailpoint.util:

run_acct_aggregation(source_name, optimized=True) method of sailpoint.util.IDN instance
    Runs an account aggregation for a source
    
    Parameters
    --------------------
    source_name: string
        The name of the source to run the aggregation for.
    
    optimized: boolean
        If True this will be an optimized aggregation, if False it will
        do a non-optimized aggregation.
    
    Results
    --------------------
    dict: The result of the API call

Performing a non-optimized account aggregation¶

Lets do an non-optimized account aggregation on the source: Active Directory

In [ ]:
idn.run_acct_aggregation('Active Directory', optimized=False)

IDN Search¶

The IDN search capability can be accessed through the search method. Using the python library and the IDN API you can search on anything as you do through the search UI.

In [4]:
# To see the help message run:
help(idn.search)
Help on method search in module sailpoint.util:

search(payload) method of sailpoint.util.IDN instance
    Runs a generic search
    
    You must provide the full payload.
    
    Can be used to search for anything that the search accepts
    
    Tip: Use developer tools in your browser on the search screen to
    figure out the payload.
    
    For example:
    
    payload = {
        "query": {"query": "email:"jason.bourne@sailpoint.com""},
        "indices": ["identities"],
    }
    
    Parameters
    --------------------
    payload: dict
        The full search payload
    
    Results
    --------------------
    dict: the result

For example you may want to list all users who have the Analyst Access Profile, but are not analysts.

The query string that can be used in the search UI is as follows:

@access(name:"Analyst Role") AND attributes.analyst:N

If you open developer tools in your browser when you submit that query, you will see in the post the following payload:

{"query":{"query":"@access(name:\"Analyst Role\") AND attributes.analyst:N"},"indices":["identities"],"includeNested":false,"sort":["displayName"]}

This same payload can be submitted using the search method in the python library:

In [ ]:
payload = {"query":{"query":"@access(name:\"Analyst Role\") AND attributes.analyst:N"},"indices":["identities"],"includeNested":False,"sort":["displayName"]}
# idn.search(payload)

# Again this may provide more information than what you need for your script, so you can write a small script to include only the information you would like to see

# first lets get the list of users
user_list = idn.search(payload)

print(f'There are: {len(user_list)} users who have the Analyst Role but are not Analysts')
print('The following users have the Analyst Role but are not Analysts:')
for user in user_list:
    user_type = ''
    if user['isManager']:
        user_type = 'manager'
    else:
        user_type = 'regular user'
    print(f"\t- {user['displayName']} - This is a {user_type}")

IDN API¶

The IDN API is documented at: IdentityNow v3 API

Here you will see each API documented with examples. You can click on the python icon to see the python code you would use to call the specified API.

For example if we wanted to call the API: Pending Access Request Approvals List

We can do this with the idn.api object included in the library.

In most cases the library will return the response object. If there is json included in the response, which should be the case most of the time on a successful call, you can access the json by using the json() method on the response.

In [ ]:
# As always you can see the help by running the following:
help(idn.api)

We can use the API to list all requests that are pending approval in the system:

In [ ]:
response = idn.api(endpoint='access-request-approvals/pending')
print('Status Code: ' + str(response.status_code))
print(response.json())
In [ ]:
response = idn.api(endpoint='access-request-approvals/completed')
print('Status Code: ' + str(response.status_code))

# print(response.json())

# again this may provide more information than you need so you can write a script to get the output you are looking for

for req in response.json():
    print(f"Request Date: {req['requestCreated']} For: {req['requestedFor']['name']} Access: {req['requestedObject']['name']}")