Managing and Rotating API Tokens with PowerShell

As the usage of RESTful API endpoints continues to increase in the data center and for multi-cloud operations, the need for a secure method for accessing API endpoints increases. One of the less involved steps you can take to authenticate against an API is to use a token. In this post, I’ll go over the architecture of token based requests, how to create and use a token, and provide some thoughts on token rotation. I will be using the Rubrik Cloud Data Management platform’s set of RESTful APIs and token management as part of this post.

API Tokens for Secure Authentication

Most RESTful API endpoints will accept two different types of authorization: basic authentication and token authentication. This information is stored in the header of an API request to prove the identity of the user. More specifically, a key name of authorization is paired with a value that contains the appropriate credentials.

For basic authentication, you can read my blog post entitled “Tackling Basic RESTful Authentication with PowerShell” to better understand how the base64 string is encoded in the value. There is a section dedicated to crafting a basic authentication key-value pair.

Token authentication is a much more popular method for handling authorization, especially across public cloud services. Instead of using the credentials of a user, the user is represented by a token. Their permissions, role, and scope is preserved by the token. These are helpful for services that need to programmatically call upon the API and can be invalidated if leaked or no longer needed without adversely affecting the user account.

Rubrik’s API Tokens have additional layers of security applied to them. The following requests are not available to API Tokens:

  • Updating or deleting any MFA (Multi-factor Authentication) servers
  • Creating new sessions or generating additional API tokens
  • Creating new user accounts or updating user account information
  • Updating user preferences
  • Creating, updating, or deleting LDAP services

Generating a New API Token

Every vendor will have a different procedure for generating a new API Token. I’ll use Rubrik as my example here to better explain the concepts and show how it works.

The process for manually creating a new API Token is to log into the UI under whatever account you wish to represent with a token.

  • Click on the account name in the upper right corner of the UI and select API Token Manager.
  • From there, a list of all API Tokens that have been generated will appear, but the token value itself is not shown and is only available at the time of generation for security purposes.
  • Click the green “+” button in the upper right corner to start a new token wizard, then fill in the duration (in days) and a tag value (to describe the token) to complete the workflow.
The UI simplifies choices down to duration and tag.

You can also request a token using an automated workflow and the PowerShell SDK for Rubrik thanks to a recent pull request. The command is New-RubrikAPIToken and will generate an API Token that adheres to your expiration and tagging needs.

In the example below, I have requested a new API Token to use with a serverless function running on AWS Lambda in US West 1 (N. California). The PowerShell function is sending a POST request to /api/internal/session using the current session information. I have truncated the resulting values for brevity:

New-RubrikAPIToken -Expiration 600 -Tag 'aws-us-west-1-lambda'
id             : 7cb4b25c
organizationId : Organization:::b6c0d1d1
userId         : 30047f2a
token          : joiN2NiNGIyN
expiration     : 2019-06-26 20:05:28
tag            : aws-us-west-1-lambda

Under the covers, an API request is being sent using my session information to generate a new API Token. The payload of the body is as follows:

Body = {
  "initParams": {
    "apiToken": {
      "tag": "aws-us-west-1-lambda",
      "expiration": 600

Note: At this time, the length of a tag cannot exceed 20 characters.

If you’d also like to get a list of different API Tokens that exist, send a GET request to /api/internal/session with a query parameter containing your user ID value. Alternatively, the PowerShell function Get-RubrikAPIToken will retrieve all known tokens based on your current session’s user ID value.

Making a Request with an API Token

You have a shiny new API Token. Great! Now what?

The use of a token for authorization changes the header construction slightly. The key remains authorization but the value changes to using the word bearer followed by the token itself. Using “bearer” seems to be the single most troublesome spot for those new to authenticating with a token, so don’t feel bad if you missed this.

'Authorization: bearer joiN2NiNGIyN'

If using the Rubrik REST API Explorer click on the green Authorize button on the top right of the page. Scroll down to the API Key Authorization section and enter the word bearer (red line), insert a space, and then paste the API Token (green line). Note that the token below is truncated for brevity. Click Authorize to use the API Token for subsequent requests during your session.

The “basic” value changes to “bearer” when a token is used.

The API Token will remain in place until it reaches the expiration date and time. The token will delete itself and become invalid beyond that point.

It’s also possible to use the token with the PowerShell SDK for Rubrik. Instead of passing along a credential object or manually entering your username and password, use the token parameter as shown below:

Connect-Rubrik -Server -Token joiN2NiNGIyN
Name                           Value
----                           -----
time                           2019-06-26 14:40:06
api                            1
header                         {Authorization, User-Agent}
version                        5.0.0

You are now able to execute API requests by way of the SDK using the API Token. For example, if I wanted to get information on an SLA Domain:

Get-RubrikSLA -Name 'Gold AWS DND' -PrimaryClusterID 'local'
id                            : e641d876-0955-4e7e-a7f1-a162281fdc74
primaryClusterId              : 8b4fe6f6-cc87-4354-a125-b65e23cf8c90
name                          : Gold AWS DND

Removing an API Token

In the event that you need to remove an API Token prior to its expiration, such as seeing that a colleague accidentally put it in their GitHub repository, it’s important to understand the process.

From a UI perspective, visit the API Token Manager page and select the token that should be removed, then choose “Delete” to remove it. Or, send a POST request to the /api/internal/session/bulk_delete endpoint with an array of token ID values.

Alternatively, use the PowerShell SDK for Rubrik to remove the token. The cmdlet Remove-RubrikAPIToken accepts the token id value as the only parameter, as shown below:

Remove-RubrikAPIToken -TokenId '7cb4b25c'
Are you sure you want to perform this action?
Performing the operation "Deletes session tokens" on target "7cb4b25c".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): y

Because this is a destructive operation, the cmdlet requires confirmation and be silenced with -Force if you do not want to entertain manual acceptance. You can also pass an array argument that contains multiple token id values if you want to remove more than one a time, which I have found to be handy in testing environments. Here is an example:

Remove-RubrikAPIToken -TokenId ("11111111-2222-3333-4444-555555555555","aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")

Rotating your API Token

While it’s possible to generate a token that lasts for 365 days, this isn’t the ideal use case for a production environment. I prefer to use shorter lived tokens that live in a secure vault and are rotated on a regular basis, such as weekly or monthly. Or issue them to others who need access for a limited period of time, such as power users, contractors, or a project team.

In these situations, my standard operation procedure is to:

  • Use short lived tokens and store them in AWS KMS, HashiCorp Vault, secured variables in AppVeyor and Azure Automation, or even something more consumer like KeePass for certain situations.
  • Make sure your code is referencing a token from these locations. Don’t use a hard coded value that is not easily rotated.
  • Generate a new token prior to the expiration of the old token using the PowerShell SDK for Rubrik, a direct call to the RESTful API (such as Invoke-RestMethod or curl), or any other trigger-based workflow that you prefer that can hit an API endpoint as the user or service account that is represented by the token.

Getting in the habit of using tokens for automation will increase your security awareness, reduce your reliance on user credentials, and aid your transition into a more service-oriented architecture approach.

That’s all I have right now on API Tokens. If you have any questions or comments, feel free to reach out or leave a comment below. And, if you’re keen on learning more about security and encryption in the cloud, check out the “Encrypting Your Data in the Cloud” series written by my sharp colleague Ken Hui.