ユーザー・アクセス管理
「ユーザー・アクセス管理」 ページでは、管理者ロールのユーザーが、すべてのユーザーの REST API キーおよび追加の特権 (パーティション管理など) を管理できます。 このページには、すべてのユーザーが、そのロール、付与されている追加特権、およびアクティブな REST API キーと期限切れの REST API キーの数とともにリストされます。
IBM Storage Insights により、管理者とモニター ユーザーはパーティションの移行と管理を実行できます。 IBM Storage Insights はパーティション管理のアクセスを制御し、追加特権の概念を使用してセキュリティを強化します。 管理者ユーザーは、ユーザーアクセス管理ページで、パーティション管理オプションを使用して、ユーザーの追加権限を設定できます。 このページでは、管理者ユーザーは、ユーザーの追加特権を管理したり、API 鍵を生成、取り消し、およびローテート/更新したりすることができます。 このページには、すべてのユーザーが、追加特権の状況、ロール、アクティブおよび期限切れの API キーの数、およびその他の詳細とともにリストされます。
追加特権の管理
IBM Storage Insights 管理者のみが、Manage additional privileges オプションにアクセスできます。 管理者ユーザーは、自分自身に割り当てることも、他の管理者やモニター・ユーザーに割り当てることもできます。 パーティション管理 機能を使用できるのは、管理者とモニターのユーザーのみです。 ログインした管理者およびモニター ユーザーは、自分のアカウントの Partition Management アクセス ステータスを確認することもできます。
- 管理者認証情報を使用して、IBM Storage Insights にログインします。
- に移動します。
- 垂直ドットが 3 つあるオーバーフロー・メニューをクリックし、ユーザーのメニューから 「追加特権の管理 (Manage additional privileges)」 オプションを選択します。
- 「追加特権の管理」 ページで、 「区画管理」 チェック・ボックスを選択または選択解除します。注: ユーザーの役割が管理者からモニターに削減された場合、そのユーザーの 「パーティション管理」 特権は制限されます。 ユーザーの役割がモニターから管理者にアップグレードされた場合、 「パーティション管理」 特権は変更されません。
- 「保存」をクリックします。
REST API の管理
このページでは、REST API にアクセスできるため、お客様の運用ダッシュボードと統合するためのストレージ・システム構成およびパフォーマンス・データの消費が容易になります。 IBM Storage Insights REST API は、REST の原則に従うことで、統合運用管理者を含む外部アプリケーションにスムーズな統合経路を提供します。 これらのAPIは予測可能なリソース指向のURLを使用し、フォームエンコードされたリクエストボディを受け入れ、JSONエンコードされたレスポンスを生成し、標準の HTTP レスポンスコード、認証方法、および動詞に準拠しています。 また、着信要求のバーストを管理するための安全機能を組み込んで、システム全体の安定性を向上させます。 IBM Storage Insights 管理者および監視担当者は、REST API を効率的に使用して、指定されたテナント内の関連データを取得することができます。
- ストレージ・システムの正常性、容量、およびパフォーマンスの統計を Integrated Operations Dashboard と統合します。
- ストレージ・システムから生成されたアラートおよび通知をインシデント管理システムと統合します。
- セキュリティー・アラートを SOAR ツール (セキュリティー・オーケストレーション、自動化、および対応) と統合して、サイバー・レジリエンシー・ワークフローの自動化を実現します。
- API キーを作成します。
- API キーを使用してトークンを生成します。
- トークンを使用して REST API にアクセスします。
REST API キーの生成
「ユーザー・アクセス管理」 ダッシュボードにアクセスすると、既に作成されている REST API キーのリストが表示されます。
- 管理者認証情報を使用して、IBM Storage Insights にログインします。
- にナビゲートします。
- 「ユーザー・アクセス管理」 ページで、鍵を生成するユーザーの 3 つの垂直ドットがあるオーバーフロー・メニューをクリックし、 「REST API 鍵の作成 (Create REST API Key)」を選択します。
- 以下のフィールドに詳細を入力します。
- タグ(オプション) :オプションのタグを入力してください。 例えば、タグを使ってAPIキーの目的を特定することができる。
- 時間単位 (Unit of time): API キーをユーザーに提供するまでの時間制限を選択します。 オプションには、「日」、「1 年」、および「2 年」があります。
- 期間/日: 「時間単位」 フィールドで「日/日」オプションを選択した場合に、ユーザーに API キーを提供するまでの日数を示します。
- 「API キーの生成」 ボタンをクリックします。
- 「API キー」 フィールドの右隅にある 「コピー」 ボタンから API キーをコピーします。
- E メールまたはその他の適切な方法を使用して、API キーをユーザーと共有します。
REST API 鍵の取り消し
- 管理者認証情報を使用して、IBM Storage Insights にログインします。
- に移動します。
- 取り消したいアクセス権を持つユーザーをリストから選択します。
- リストの上部にある 「キー・アクセスの取り消し (Revoke key access)」 をクリックするか、3 つの垂直ドットがあるオーバーフロー・メニューをクリックして、選択したユーザーの行で 「アクセスの取り消し (Revoke access)」 を選択します。注: 一度に複数のユーザーを選択して、アクセス権限を取り消すことができます。
- ポップアップ・ウィンドウで 「鍵アクセスの取り消し」 をクリックします。
REST API キーのローテーション/更新
- 管理者認証情報を使用して、IBM Storage Insights にログインします。
- に移動します。
- 「REST API キー」 列で、ユーザーの REST API キー・カウントをクリックします。 「REST API キー」 ウィンドウが表示され、ユーザーのすべての API キーの詳細が示されます。 「REST API 鍵 (REST API Keys)」 ウィンドウには、 「取り消し」、 「鍵のローテート/更新 (Rotate/Renew Key)」、および 「鍵のコピー (Copy Key)」 の各オプションがあります。注: カウント付きの緑色のアイコンはユーザーのアクティブな API キーの数を示し、カウント付きの赤色のアイコンはユーザーの期限切れの API キーを示します。
- APIキーを選択し、 Rotate/Renew Keyをクリックします。 以下のフィールドに詳細を入力します。
- タグ(オプション) :オプションのタグを入力してください。 例えば、タグを使ってAPIキーの目的を特定することができる。
- 時間単位 (Unit of time): API キーをユーザーに提供するまでの時間制限を選択します。 オプションには、「日」、「1 年」、および「2 年」があります。
- 期間/日: 「時間単位」 フィールドで「日/日」オプションを選択した場合に、ユーザーに API キーを提供するまでの日数を示します。
注: ユーザーが複数の API キーを選択した場合、 「キーのローテート/更新 (Rotate/Renew Key)」 オプションと 「キーのコピー (Copy Key)」 オプションは無効になります。 - 「作成 +」 ボタンをクリックして、新しい鍵を生成します。 既存の API キーが無効であり、新しいキーが生成されます。
- 「コピー」 ボタンをクリックして、新しい鍵をコピーします。
API トークンの生成
IBM Storage Insights GUI で API キーを生成した後、IBM Storage Insights Token API を実行して API トークンを作成する必要があります。 残りの IBM Storage Insights REST API を実行するには、API トークンが必要です。 トークンAPIを実行するには、生成されたAPIキーをx-api-keyヘッダーに設定する必要があります。 トークンAPIの詳細については、 Swagger ドキュメントを参照のこと。
API トークンを生成したら、残りの IBM Storage Insights REST API を実行できます。 他のREST APIを実行する際には、APIトークンをx-api-tokenヘッダーに設定する必要があります。
REST API ストリングのビルド
https://<REST API PATH>?<parameter1>=<value1>&<parameter2>=<value2>&<parameter3>=<value3>&....例: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上記の例では、insights.ibm.com/restapi/v1/tenants/01eb8cb2-d32d-1e60-88ae-c35e5b3b9751/storage-systems/3b82a330-b90e-11eb-8322-49470b9950db/metricsは API パスです。types=used_capacityとduration=7dは、2 つの照会パラメーターです。
上記の例では、REST API 呼び出しは、指定されたパラメーター ( type および duration) に基づいて、特定のストレージ・システムのメトリック・データをフィルタリングします。 REST APIの詳細については、 Swaggerドキュメントを参照してください。
Python を使用して IBM Storage Insights REST API にアクセスする
Python アプリケーションでは、IBM Storage Insights REST API サービスと対話できます。 CLI コマンドは、サービスの REST API を通じて IBM Storage Insights 機能を使用します。
- サンプル・アプリケーションには、 Python 3.6+ ランタイム環境が必要です。
- ZIP ファイルをダウンロードして、Python で IBM Storage Insights REST API を呼び出すプロセスを示すサンプル コードを確認してください。 ZIP ファイルには、Python インストールの前提条件も含まれています。
- 必要な依存関係をインストールします。
pip install -r requirements.txt
- IBM Storage Insights テナントIDを検索します。
インスタンスのテナントID。 IBM Storage Insights インスタンスのテナントID。 IBM Storage InsightsURL が https://insights.ibm.com/gui/ abcd-efgh-ijkl-mnop-xyz のように見える場合、 URL の最後の部分、 abcd-efgh-ijkl-mnop-xyz があなたのテナントIDです。
- IBM Storage Insights REST API キーを取得します。
- Python スクリプトを実行する前に取得した値で構成ファイル
config.iniを更新します。
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()