User Access Management
The User Access Management page allows administrator role users to manage REST API keys and additional privileges, such as partition management, for all users. The page lists all users along with their role, any additional privilege granted, and the number of active and expired REST API keys.
IBM Storage Insights allows administrator and monitor users to perform partition migration and management. IBM Storage Insights controls the access of partition management and enhances security by using the concept of additional privileges. The administrator users can use the User Access Management page to configure the user's additional privilege by using the Partition Management option. The page allows administrator users to manage users' additional privileges and generate, revoke, and rotate/renew API keys. The page lists all the users along with the status of additional privilege, role, number of active and expired API keys, and other details.
Manage additional privileges
Only IBM Storage Insights administrators have access to the Manage additional privileges option. An admin user can assign it to themselves or to other admin and monitor users. Only admin and monitor users can use the Partition Management feature. Logged in admin and monitor users can also check the Partition Management access status of their account.
- Login to IBM Storage Insights by using administrator credentials.
- Go to .
- Click the overflow menu with three vertical dots, and select the Manage additional privileges option from the menu for a user.
- On the Manage additional privileges page, select, or
deselect the Partition Management check-box.Note: If the role of a user is reduced from administrator to monitor, the Partition Management privilege is restricted for the user. If the role of a user is upgraded from monitor to administrator, the Partition Management privilege remains unchanged.
- Click Save.
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.
- 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:
- 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 Generate API Key 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.
- Navigate to .
- Select the user from the list whose access you want to revoke.
- 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.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.
- 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 option to rotate or renew
the API key for the user. Note: If the user selects multiple API keys, the Rotate/Renew Key and Copy Key options get disabled.
- Select the Unit of time in days or years.
- 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=7d
In
the preceding example:insights.ibm.com/restapi/v1/tenants/01eb8cb2-d32d-1e60-88ae-c35e5b3b9751/storage-systems/3b82a330-b90e-11eb-8322-49470b9950db/metrics
is the API pathtypes=used_capacity
andduration=7d
are 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.ini
with 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()