Skip to content

Getting Data Out of Tanium with the API Gateway and GraphQL

Use the API Gateway and GraphQL to power your own apps with rich Tanium data

Tech Insights

Tanium is an incredibly powerful platform, and many users may need to get data out of Tanium using their own tools. Tanium Connect can always export data and send it to a product, server, or file, respectively, but sometimes users may need to pull data manually rather than accept data. The new API Gateway from Tanium can make this process a breeze. In this blog, I’ll show you how to log in to Tanium via python and query machine data.

Requirements

  • A Tanium environment with the latest API Gateway solution imported. This blog was tested on version 1.3.64.0000.
  • Python 3 with “requests” and “JSON” libraries

Authentication

Before we can start pulling data from Tanium, we’ll need to ensure we can log in. There are two options for logging in – using a Tanium username/password and using an API token. Logging in via a username and password is not possible if you log in via SSO or use Tanium Cloud, so you’ll need to use an API token if this is the case with your Tanium environment.

Creating an API Token

To create an API Token, you’ll want to log in to your Tanium Server as you normally would and find the API Tokens option within the “Administration” menu.

[Note: Creating API Tokens requires specific permission, for more information please review the Tanium documentation regarding API Tokens here.]

Screenshot 1: Showing where to create API Tokens within the Tanium console

Screenshot 1: Showing where to create API Tokens

After accessing the API Tokens page, you can then click the “New API Token” button on the right side of the screen. This will allow you to create a token, and provide how long the token is valid for, and which API Addresses are allowed to use this API Token. After filling out the modal, a popup will show up that displays the token for a limited amount of time. Please take note of the token as this cannot be viewed after the popup closes.

Logging in to Tanium via username and password

If your Tanium environment is not using SSO to log in, then you can use your username and password to authenticate and work with Tanium’s API. The below function is an example of how we can log in to the Tanium Server via a username and password and extract the session token.

[Note: This session token will expire after a period of inactivity so you may need to reauthenticate, as necessary.]

Code block 1: Getting a session token via username/password

def loginUsernamePassword(ts: str, username: str, password: str) -> str:
"""
Example function of how to login to a Tanium Server via
a username and password combination. This will return the
session token.
parameter ts is the Tanium server to use.
parameter username is the username to use when logging in.
parameter password is the password to use when logging in.
"""
payload = {}
payload["username"] = username
payload["password"] = password
r = requests.post(f"{ts}/api/v2/session/login",
json=payload
)

session_token = r.json()['data']['session']
print(f"Status code received from logging in: {r.status_code}")
return session_token

Testing authentication

Once we have an API Token created, we can start testing authentication. The API Token needs to be added as a header in any https requests to the Tanium Server. After we receive the session token from either the API Tokens page in the Tanium console or from logging in via a username/password combination, we will validate that the token works correctly. This can be done by calling the /api/v2/session/validate route on the Tanium Server. The function block below has an example of how this can be achieved.

Code block 2: Validating an API/session token is valid


def validateToken(ts: str, token: str):
"""
Example function of how to validate that an API token is able
to hit the Tanium server and get a 200 response.

parameter ts is the Tanium server to use.
Example: 'https://MyTaniumServer.com'
parameter token is the api token string generated from the ts gui.
"""

r = requests.post(f"{ts}/api/v2/session/validate",
json={'session': token},
headers={'session': token}
)


# status_code should be 200 on successful validation of token.
print(f"Status code from validating token: {r.status_code}.")

Using the API Gateway and GraphQL

After we successfully logged into the Tanium Server and validated our token, we can start querying the API Gateway to extract information about the environment. If you haven’t used graphQL before, it may be a good idea to head over to their documentation for a quick read about what graphQL is and how the query language works. The website is found here: https://graphql.org/learn/.

Before automating things via the Tanium API, we can go into the API Gateway in the Tanium console and start exploring the data fields we can query. Photo 2 shows where you can access the API Gateway area of the Tanium Console.

Screenshot 2: Showing where the API Gateway is in the Tanium console

Screenshot 2: Showing where the API Gateway is in the Tanium console

Once we access this page, we can view an interactive graphQL IDE that allows us to explore and experiment with various queries and get real data out. See Photo 3 where we can run an initial query to view the current time reported by the server.

Screenshot 3: Doing a simple graphQL query in the Tanium Console

Screenshot 3: Doing a simple graphQL query in the Tanium Console

By using the interactive graphQL query in the Tanium console, we can explore and build our queries that we can then take into our python script to automate. For example, we can build a very simple python function that would execute the same “{now}” query, as shown below.

Code block 3: Executing the ‘now’ query via python

def graphQLQueryNow(ts: str, token: str):
"""

graphQLQueryNow will execute the 'now' graphQL query
against the Tanium server that is passed into this function.

parameter ts is the Tanium server to use.
parameter token is the api token string generated from the ts gui.
"""

jsonObj = {'query': "{now}"}

r = requests.post(ts + "/plugin/products/gateway/graphql",
json=jsonObj,
headers={'session': token},
)

print(f"Status code received from 'now' query: {r.status_code}")
print(f"'now' query json response: {r.json()}")

This is a great start on executing the first Tanium query via python but let us try getting endpoint data from the interactive graphQL explorer in the Tanium Console. The photo below shows how we can query for all endpoints and their operating system.

Screenshot 4: Querying all endpoints and their operating system

Screenshot 4: Querying all endpoints and their operating system

This is finally giving us endpoint data, but there is one last missing piece. Unless your environment has 20 or fewer machines, you will see that this data does not provide the information for the entire environment. GraphQL has pagination enabled by default, which means we will need to make multiple requests to receive a full dataset of the entire environment. Let us augment our query to show pagination information, so then we will know how we can parse this when automating through a python script.

Screenshot 5: Enabling “pageInfo” information on a graphQL Query

Screenshot 5: Enabling “pageInfo” information on a graphQL Query

When this “pageInfo” data is enabled, we can see if there is more data left to parse through on the server via the “hasNextPage” field. Additionally, we can track where we are inside the dataset by reviewing the “startCursor” and “endCursor” fields. If we wanted to get the next set of data, we can simply add a (after: “lastcursor”) into our endpoints query, as shown below.

Screenshot 6: Iterating to the next set of data via the cursor in graphQL

Screenshot 6: Iterating to the next set of data via the cursor in graphQL

We can see that when we add this “after” argument into the endpoints query, the resultant data is the next set of 20 machines. Now that we know how to paginate through the data, we can finally put everything together in a python script that will run an automated query for us.

Code Block 4: Putting it all together to query full datasets


def graphQL_pagination(ts: str, token: str):
"""

graphQL_pagination will every endpoint's name and os using
graphQL and pagination.

parameter ts is the Tanium server to use.
parameter token is the api token string generated from the ts gui.
"""

init_query = '''
{
endpoints {
pageInfo {
startCursor
endCursor
hasNextPage
}
edges {
node {
name
os {
name
}
}
}
}
}
'''

def do_request(ts: str, token: str, queryString: str) -> requests.Response:
r = requests.post(ts + "/plugin/products/gateway/graphql",
json={'query': queryString},
headers={'session': token},
)
return r

endpoint_data = []
next_query = init_query
while True:

# do the request, and format response into json
r = do_request(ts, token, next_query)
resp_obj = r.json()

# extract the page information from the json object
has_next_page = resp_obj["data"]["endpoints"]["pageInfo"]["hasNextPage"]
end_cursor = resp_obj["data"]["endpoints"]["pageInfo"]["endCursor"]
start_cursor = resp_obj["data"]["endpoints"]["pageInfo"]["startCursor"]

# let the user know what part of the cursor we are at.
print(
f"Recieved data for endpoints between start: {start_cursor} and end: {end_cursor}.")

# add the endpoint data into our list object
endpoint_data.extend(resp_obj["data"]["endpoints"]["edges"])

# if the next page is "False" then we reached the end of the dataset!
if not has_next_page:
break

# inject the "after" argument into the original query
next_query = init_query[:25] + \
f"(after: \"{end_cursor}\") " + init_query[25:]

Hopefully this gets you started on how to use the API Gateway outside of Tanium. Don’t forget that many use cases can be accomplished simply by using the native connectors that are supplied by Tanium Connect. When needing to build any customized integration, the API Gateway is an extremely helpful resource, and additional functionality is being added every week – including module support. Reach out to your Tanium representative for further information on any road map items or further support to assist with any API Gateway endeavors.

Alex Collins

Alex Collins is a Staff R&D Engineer at Tanium. He has had many titles within the TAM and R&D departments. Previously he worked as a software engineer at Red Hat and IBM.

Tanium Subscription Center

Get Tanium digests straight to your inbox, including the latest thought leadership, industry news and best practices for IT security and operations.

SUBSCRIBE NOW