User Access Management
The User Access Management page allows administrator role users to manage REST API keys for all users. The page lists all users along with their role and the number of active and expired REST API keys.
The page allows administrators to generate, revoke, and rotate or renew API keys. The page lists all users along with their role, the number of active and expired API keys, and other details.
Manage REST APIs
The page allows access to REST APIs, facilitating the consumption of storage systems configuration and performance data for integration with customers operational dashboards. IBM Storage Insights REST APIs offer a smooth integration pathway for external applications, including integrated operation managers, by adhering to REST principles. These APIs use predictable resource-oriented URLs, accept form-encoded request bodies, generate JSON-encoded responses, and adhere to standard HTTP response codes, authentication methods, and verbs. Also, they incorporate safeguards to manage bursts of incoming requests, enhancing overall system stability. IBM Storage Insights administrators and monitoring persona can efficiently use the REST API to retrieve relevant data within their designated tenant.
- Integrate storage systems health, capacity, and performance statistics with Integrated Operations dashboards
- Integrate alerts and notifications that are generated from storage systems with Incident Management systems
- Integrate security alerts with SOAR tools (Security Orchestration, Automation, and Response) for cyber resiliency workflow automations
- Create an API Key.
- Generate a token by using an API Key.
- Access the REST API by using a token.
Generating a REST API key
When you access the Users Access Management dashboard, the list of already created REST API keys is displayed.
- Login to IBM Storage Insights using administrator credentials.
- In classic UI, navigate to .
In modern UI, navigate to .
- On the Users Access Management page, click the overflow menu with three vertical dots for a user you want to generate the key, and select Create REST API Key.
- Enter the details in the following fields:
- Tag (Optional): Enter an optional tag for your reference. For example, you can use the tag to identify the purpose of the API key.
- Unit of time: Select the time limit until when you want to provide the API key to the user. The options include, Day(s), 1 year, and 2 year.
- Duration/Days: Mention the number of days until when you want to provide the API key to the user if you selected the Days(s) option in Unit of time field.
- Click Create + button.
- Copy the API key from the Copy button on the right corner of the API key field.
- Share the API key with the user through email or other suitable ways.
Revoke REST API key
- Login to IBM Storage Insights using administrator credentials.
- In classic UI, navigate to .
In modern UI, navigate to .
- Select the user from the list whose access you want to revoke.
- In classic UI, click Revoke key access at the top of the list or click
overflow menu with three vertical dots and select Revoke access on the
selected user's row.
In modern UI, click Revoke key access at the top of the list.
Note: You can select multiple users at a time to revoke access. - Click Revoke key access on the pop-up window.
Rotate/Renew REST API key
- Login to IBM Storage Insights using administrator credentials.
- In classic UI, navigate to .
In modern UI, navigate to .
- Under the REST API Keys column, click the REST API key count for a user.
The REST API Keys window appears with the details of all
API keys for the user. The REST API Keys window provides
the Revoke, Rotate/Renew Key, and Copy
Key options. Note: The green icon with count specifies the number of active API keys for the user and the red icon with count specifies the expired API keys for the user.
- Select an API key and click Rotate/Renew Key.
Enter the details in the following fields:
- Tag (Optional): Enter an optional tag for your reference. For example, you can use the tag to identify the purpose of the API key.
- Unit of time: Select the time limit until when you want to provide the API key to the user. The options include, Day(s), 1 year, and 2 year.
- Duration/Days: Mention the number of days until when you want to provide the API key to the user if you selected the Days(s) option in Unit of time field.
Note: If the user selects multiple API keys, the Rotate/Renew Key and Copy Key options get disabled. - Click Create + button to generate a new key. The existing API key is not valid and a new key is generated.
- Click the Copy button to copy the new key.
Generate an API Token
After generating an API key in the IBM Storage
Insights GUI, you need to run the IBM Storage
Insights Token
API to create an API token. An API token is required for running the remaining IBM Storage
Insights REST APIs. Running the Token API requires
setting the generated API key in an x-api-key header. For more information about
the token APIs, see Swagger documentation.
After generating an API token, you can run the remaining IBM Storage
Insights REST APIs. You must set the API token in an
x-api-token header when executing the other REST APIs.
Building REST API string
https://<REST API PATH>?<parameter1>=<value1>&<parameter2>=<value2>&<parameter3>=<value3>&....For
example:https://insights.ibm.com/restapi/v1/tenants/01eb8cb2-d32d-1e60-88ae-c35e5b3b9751/storage-systems/3b82a330-b90e-11eb-8322-49470b9950db/metrics?types=used_capacity&duration=7dIn
the preceding example:insights.ibm.com/restapi/v1/tenants/01eb8cb2-d32d-1e60-88ae-c35e5b3b9751/storage-systems/3b82a330-b90e-11eb-8322-49470b9950db/metricsis the API pathtypes=used_capacityandduration=7dare the two query parameters
In the preceding example, the REST API call filters metrics data for a particular storage system
based on the specified parameters, which are type and duration.
See Swagger
documentation for more REST API details.
Using Python to access IBM Storage Insights REST APIs
The Python application allows to interact with the IBM Storage Insights REST API service. The CLI commands are using the IBM Storage Insights functions through the service's REST API.
- The sample application requires a Python 3.6+ runtime environment.
- Download the ZIP file to review the sample code in Python that demonstrates the process to call the IBM Storage Insights REST APIs. The ZIP file also contains the Python installation prerequisites.
- Install the required dependencies:
pip install -r requirements.txt
- Find your IBM Storage
Insights Tenant ID.
The Tenant ID of your IBM Storage Insights instance, for example, if your IBM Storage Insights URL looks like https://insights.ibm.com/gui/abcd-efgh-ijkl-mnop-xyz, then the last part of the URL, abcd-efgh-ijkl-mnop-xyz is your Tenant ID.
- Get your IBM Storage Insights REST API Key.
- Update the configuration file
config.iniwith the values obtained before running the Python scripts.
import argparse
import json
import os
from datetime import datetime
import click
from ibm_si_rest import si_rest
TOKEN_FILE = 'token.json' # store API token till expiry
def parse_arguments():
parser = argparse.ArgumentParser(description='IBM Storage Insights REST API.')
subparsers = parser.add_subparsers(dest='command', help='Choose a REST API to invoke')
# list of storage systems
parser_list_storage_systems = subparsers.add_parser('list_storage_systems', help='List storage systems')
parser_list_storage_systems.add_argument('--system-type', help='Type of the storage system, e.g., block, filer, '
'object')
# list of volumes
parser_list_storage_system_vol = subparsers.add_parser('list_storage_system_vol', help='List volumes of storage '
'systems')
parser_list_storage_system_vol.add_argument('--system-uuid', help='UUID of the storage system')
# list of alerts
parser_list_alerts = subparsers.add_parser('list_alerts', help='List alerts for a tenant')
parser_list_alerts.add_argument('--duration', help='Alerts requested for particular duration')
parser_list_alerts.add_argument('--severity', help='Alerts requested for particular severity')
# list of notifications
parser_list_notifications = subparsers.add_parser('list_notifications', help='List notifications for a tenant')
parser_list_notifications.add_argument('--duration', help='Notifications requested for particular duration')
parser_list_notifications.add_argument('--severity', help='Notifications requested for particular severity')
return parser, parser.parse_args()
def get_token(rest_api_host, api_key, tenant_id):
"""Fetch API token and save it locally till it expires"""
try:
if os.path.exists(TOKEN_FILE):
with open(TOKEN_FILE, 'r') as token_file:
stored_token = json.load(token_file)
token_expiry = datetime.utcfromtimestamp(stored_token['result']['expiration']/1000.0)
if datetime.utcnow() < token_expiry:
click.secho('Token is valid, re-using it', fg='green')
return stored_token['result']['token']
else:
# Token expired, get a fresh token
click.secho('Token expired, getting a fresh token', fg='red')
token_response = si_rest.get_token(rest_api_host, api_key, tenant_id)
if token_response:
with open(TOKEN_FILE, 'w') as token_file_w:
json.dump(token_response, token_file_w)
return token_response['result']['token']
else:
return None
else:
# fetch token for the first time
click.secho('Token not found, fetching token', fg='blue')
token_response = si_rest.get_token(rest_api_host, api_key, tenant_id)
if token_response:
with open(TOKEN_FILE, 'w') as token_file:
json.dump(token_response, token_file)
return token_response['result']['token']
else:
return None
except Exception as ex:
click.secho("Unexpected error: %s" % str(ex), fg="bright_red")
def process_command():
parser, args = parse_arguments()
if args.command == 'list_storage_systems':
try:
rest_api_host, api_key, tenant_id = si_rest.setup()
token = get_token(rest_api_host, api_key, tenant_id)
if token is None:
raise Exception('Token creation failed')
storage_systems = si_rest.list_storage_systems(rest_api_host, token, tenant_id, args.system_type)
click.secho('Found (%d) storage systems' % len(storage_systems['data']), fg='green')
except Exception as ex:
click.secho("Unexpected error: %s" % str(ex), fg="bright_red")
elif args.command == 'list_storage_system_vol':
try:
if args.system_uuid:
rest_api_host, api_key, tenant_id = si_rest.setup()
token = get_token(rest_api_host, api_key, tenant_id)
if token is None:
raise Exception('Token creation failed')
system_vols = si_rest.list_storage_system_volumes(rest_api_host, token, tenant_id, args.system_uuid)
system_vols_data = []
if system_vols and system_vols['data'] and len(system_vols['data']) > 0:
system_vols_data = system_vols['data']
while system_vols and system_vols['data']:
if 'links' in system_vols:
next_link = next((link for link in system_vols['links'] if link['params']['rel'] == "next"), None)
if next_link:
click.secho('Fetching next set of volumes (%s)' % next_link['uri'], fg="green")
system_vols = si_rest.list_storage_system_volumes(rest_api_host, token, tenant_id, args.system_uuid,
next_link['uri'])
if system_vols is not None and system_vols['data'] is not None and len(system_vols['data']) > 0:
system_vols_data.extend(system_vols['data'])
else:
break
else:
break
click.secho('Found (%d) volumes' % len(system_vols_data), fg='green')
else:
click.secho('Please provide system uuid', fg='red')
except Exception as ex:
click.secho("Unexpected error: %s" % str(ex), fg="bright_red")
elif args.command == 'list_alerts':
try:
rest_api_host, api_key, tenant_id = si_rest.setup()
token = get_token(rest_api_host, api_key, tenant_id)
if token is None:
raise Exception('Token creation failed')
alerts = si_rest.list_tenant_alerts(rest_api_host, token, tenant_id, args.duration, args.severity)
alerts_data = []
if alerts and alerts['data'] and len(alerts['data']) > 0:
alerts_data = alerts['data']
while alerts and alerts['data']:
if 'links' in alerts:
next_link = next((link for link in alerts['links'] if link['params']['rel'] == "next"), None)
if next_link:
click.secho('Fetching next set of alerts (%s)' % next_link['uri'], fg="green")
alerts = si_rest.list_tenant_alerts(rest_api_host, token, tenant_id, args.duration, args.severity,
next_link['uri'])
if alerts is not None and alerts['data'] is not None and len(alerts['data']) > 0:
alerts_data.extend(alerts['data'])
else:
break
else:
break
click.secho('Found (%d) alerts' % len(alerts_data), fg='green')
except Exception as ex:
click.secho("Unexpected error: %s" % str(ex), fg="bright_red")
elif args.command == 'list_notifications':
try:
rest_api_host, api_key, tenant_id = si_rest.setup()
token = get_token(rest_api_host, api_key, tenant_id)
if token is None:
raise Exception('Token creation failed')
notifications = si_rest.list_tenant_notifications(rest_api_host, token, tenant_id, args.duration, args.severity)
notifications_data = []
if notifications and notifications['data'] and len(notifications['data']) > 0:
notifications_data = notifications['data']
while notifications and notifications['data']:
if 'links' in notifications:
next_link = next((link for link in notifications['links'] if link['params']['rel'] == "next"), None)
if next_link:
click.secho('Fetching next set of notifications (%s)' % next_link['uri'], fg="green")
notifications = si_rest.list_tenant_notifications(rest_api_host, token, tenant_id, args.duration,
args.severity,
next_link['uri'])
if notifications and notifications['data'] and len(notifications['data']) > 0:
notifications_data.extend(notifications['data'])
else:
break
else:
break
click.secho('Found (%d) notifications' % len(notifications_data), fg='green')
except Exception as ex:
click.secho("Unexpected error: %s" % str(ex), fg="bright_red")
else:
parser.print_help()
if __name__ == '__main__':
process_command()