Photo by Silas Köhler on Unsplash
Since day 1 of joining Pure Storage, I have been fond of all things APIs, SDKs, Automation and Scripting. Everyone is contributing from developer to sales to customers. This will be a blog series, breaking down my learning journey and tips I’ve gained for people who might be just starting out with Pure Storage APIs.
Introduction
Pure Storage is a leading provider of enterprise-grade storage solutions that are designed to meet the requirements of modern businesses. Its Python SDK enables developers to interact with its FlashArray and FlashBlade products programmatically. However, before you can start using the SDK, you need to authenticate with the storage system. In this blog, we’ll explore the various authentication methods that the Pure Storage Python SDK supports with examples of course.
The reason why I have decided to write this blog is to clear the confusion and redirect people to use the unified Pure Python client library py-pure-client
that is based on FlashArray, FlashBlade REST 2.x API. Rather than relying on the old REST 1.x API .
Installation
Pure Storage Unified Python SDK library requires Python 3.5 or higher.
What I really like about this library compared to the old one that it unifies all Pure Storage product into one package. If you learned how to use it for FlashArray it would be the same for FlashBlade or Pure1.
Authentication methods
The Pure Storage Python SDK supports two authentication methods:
- API Token session-based authentication.
- API Client OAuth2-based Authentication.
The authentication methods in this blog can be used for FlashArray or Cloud Block Store (CBS) alike. Both systems are running Purity Operations Environment.
API Token Session-based Authentication
API token-based authentication is the recommended method for authenticating with the Pure Storage Python SDK. API tokens are unique strings that are generated by the Pure Storage system and can be used as a replacement for a password. They are created by a user with administrative privileges and can be revoked at any time.
To generate an API token, Use the Purity GUI (System > Access > Users > Create API Token). Alternatively, you can use CLI:
~# pureadmin create --api-token
Name Type API Token Created Expires
pureuser local 66fexxx7-xx3f-xxxx-xxxx-ac3da9f856xx 2023-03-21 03:18:54 PDT -
Or, you can use curl
to run an REST API 1.x call using username/password to generate the API Token.
username='pureuser'
password='pureuser'
PURE_ENDPOINT='10.x.x.x'
PURE_API_TOKEN=$(curl -X POST -k -H "Content-Type: application/json" -d '{"username": '$username',"password": '$password'}' 'https://'$PURE_ENDPOINT'/api/1.19/auth/apitoken')
API token-based Example
import pypureclient
client = pypureclient.flasharray.Client('10.x.x.x', api_token='token from above')
resp = client.get_volumes()
for item in resp.items:
print(item.name)
API Client OAuth2-based Authentication
OAuth2 is an industry-standard protocol used for authentication and authorization. OAuth2-based authentication is another method for authenticating with the Pure Storage Python SDK. This method requires developers to create an API Client in FlashArray or CBS, generate a client ID and secret, and authenticate using these credentials.
To authenticate using OAuth2 identity, follow these steps:
Generating a RSA key pair
On client machine:
$ openssl genrsa -out fa2xprivate.pem 2048
openssl rsa -in fa2xprivate.pem -outform PEM -pubout -out fa2xpublic.pem
Creating an API Client
To create a client there are four roles to choose from that will limit the scope of the API client permissions: readonly
, ops_admin
, storage_admin
, and array_admin
.
$ pureapiclient create --max-role array_admin --public-key pyClient
Paste public key from above here than Enter followed by Ctrl+D
Do not forget to enable the client.
$ pureapiclient enable pyClient
And last thing is to save the value of the created parameters
$ pureapiclient list pyClient
Name Enabled Max Role Issuer Access Token TTL Client ID Key ID
pyClient True array_admin pyClient 1d xxxxxxxx-a5e0-4b83-xxxx-8064d3f8f5xx xxxxxxxx-a090-xxxx-b5e1-01a551af4cxx
At this stage there are two approaches to use the API Client to authenticate:
Pass API Client to Client Constructor
After creating a client using pureapiclient
on the array, you can pass the various parameters generated from the above step directly into the Client constructor.
This approach would require access to the private key file.
from pypureclient import flasharray
client = flasharray.Client('flasharray.example.com',
private_key_file=[...],
private_key_password=[...],
username=[...],
client_id=[...],
key_id=[...],
issuer=[...])
Example:
from pypureclient import flasharray
client = flasharray.Client('10.x.x.x.',
private_key_file='/Users/amazouz/.ssh/fa2xprivate.pem',
private_key_password='1234',
username='pureuser',
client_id='xxxxxxxx-a5e0-4b83-xxxx-8064d3f8f5xx',
key_id='xxxxxxxx-a090-xxxx-b5e1-01a551af4cxx',
issuer='pyClient')
response = client.get_arrays()
arrays = list(response.items)
print(arrays)
Pre-generate API Access Token: Python Script Option
You can generate the Access token pragmatically and pass it directly to the Client Constructor using the Postman collection option or fa2_token_factory.py
python script. The example below shows how to use the python script.
The figure illustrate the process for REST 2.x API authentication. For instance, when you are using the python script, step 1, and 2 are part of the the script functionality itself and it will generate an Access token that can be used to access the array.
Note that using a pre-generated Access token will cause the client to fail when the ID token expires.
Download the python script fa2_token_factory.py
from the official knowledge base
Run it by passing the created API Client parament as arguments
python3 fa2_token_factory.py <api_client_id> <api_key_id> <api_client_issuer> <api_username> <flasharray_host_or_ip> <path_to_private_key_file>
As an example:
python3 fa2_token_factory.py xxxxxxxx-a5e0-4b83-xxxx-8064d3f8f5xx xxxxxxxx-a090-xxxx-b5e1-01a551af4cxx pyClient pureuser flasharray.purestorage.com /Users/amazouz/.ssh/fa2xprivate.pem
The output value of the script is similar to:
Access token for pyClient:
eyJraWQiOiJnbUdMYkRQU1ZMOVRBY3hNTEhNVXc4QktiUkpsIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.ey
JhdWQiOiI5MDEyOTA3ZS0yOGZlLTQwMTktODZhYi02NjRlMWQ0N2ZiMzYiLCJzdWIiOiJwdXJldXNlciIsInJvbGU
iOiJhcnJheV9hZG1pbiIsImFwaWNsaWVudC1yb2xlIjoicmVhZG9ubHkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0
OjkwMDAiLCJpYXQiOjE1NjcwMzkzMjMsImV4cCI6MTU2NzEyNTcyMywianRpIjoiMzJkM2JjMjEtZGM4My00NmZi
LWE0ZTEtNzk3NjNhMjgxZWZlIn0.NKNE-5FSrZdeFFUb0k12CFQlfe0DpZMuWnhZ8ehWJhZf37FeydX9FEbLVUZnW
uoiOlg6MucuMYX6gO-8xKf8ovid8vkqmTEdhaT66dQvoZIyu-FEke01A2IVi18maYX3oTuwPky2c9fruaFE2a4s1YA
UG5lCeG1ZyHxjiM1wRvZX_iHbeQBVEmr9KSk8KUJQLKSj9SA
4CWOoG1ValqFoVeZDKxBcdjRxyZ919Gvy1LgB_kJ-ogAPmK6XjuqRL9Kx1tMH_B4s_CYZWyq_xFIAAKDZJdrz4Fjr_TY0w0NOO56zhcz2TaCLHg4G4XzdNl0CgnU2wB7G8g08yh_9RDqjag
Example:
from pypureclient import flasharray
client = flasharray.Client('flasharray.example.com', id_token=<token_from_above>)
client.get_rest_version()
Which Method to Use?
The table below summarizes and compares both methods based on a couple of feature sets:
Features | API Client | API Token | Note |
---|---|---|---|
Security | ✅ | ⚠️ | API Client method is based on OAuth, which only establish authentication between two trusted parties. |
Simplicity | ⚠️ | ✅ | API Tokens are easy to generate. API Clients are more complex and requiring a couple of steps to generate them. |
RBAC | ✅ | ⚠️ | Both methods provides different roles to choose from. The only differentiation is API Token are tied to the user. So if an app is using the API Token, you can not distinguish or audit who made the request, the user or the app. |
Time To Live (TTL) | ✅ | ⚠️ | API Client uses a temporary access token that expires after a set period of time, after that the app needs to re-authenticate, No need to recreate the API Client. On the other hand, User API Tokens can be set to expire at certain period of time, once expired the user has to recreate the API Token. |
Conclusion
In this blog, we explored the two authentication methods that the Pure Python SDK supports. API session-based authentication involves generating an API token from the Pure Storage arrays, which is similar to REST 1.x API authentication process. OAuth2-based authentication requires creating an API Client in the array and obtaining a client ID and secret, which can be used to authenticate with the Pure Storage Python SDK. With these authentication methods, storage admins and developers can securely and programmatically interact with Pure Storage Arrays.
comments powered by Disqus