사용자 액세스 관리
‘사용자 액세스 관리’ 페이지에서는 관리자 역할 사용자가 모든 사용자의 REST API 키를 관리할 수 있습니다. 이 페이지에는 모든 사용자와 해당 사용자의 역할, 그리고 유효한 REST API 키와 만료된 REST API 키의 수가 나열되어 있습니다.
이 페이지를 통해 관리자는 API 키를 생성, 취소, 순환 또는 갱신할 수 있습니다. 이 페이지에는 모든 사용자와 해당 사용자의 역할, 활성 및 만료된 API 키 수, 그 외 세부 정보가 나열되어 있습니다.
REST API 관리
이 페이지에서는 고객 운영 대시보드와의 통합을 위해 스토리지 시스템 구성 및 성능 데이터의 이용을 용이하게 하는 REST API에 대한 액세스를 허용합니다. IBM Storage Insights REST API는 REST 원칙을 준수하여 통합 운영 관리자를 비롯한 외부 애플리케이션을 위한 원활한 통합 경로를 제공합니다. HTTP 이 API는 예측 가능한 리소스 지향 URL을 사용하고, 양식 인코딩 요청 본문을 수용하며, JSON 인코딩 응답을 생성하고, 표준 HTTP 응답 코드, 인증 방법, 동사를 준수합니다. 또한 수신 요청의 버스트를 관리하는 안전 장치를 통합하여 전반적인 시스템 안정성을 향상시킵니다. IBM Storage Insights 관리자와 모니터링 담당자는 REST API를 효율적으로 사용하여 지정된 테넌트 내에서 관련 데이터를 검색할 수 있습니다.
- 스토리지 시스템 상태, 용량 및 성능 통계를 통합 운영 대시보드와 통합
- 스토리지 시스템에서 생성된 경보 및 알림을 인시던트 관리 시스템과 통합
- 사이버 복원력 워크플로우 자동화를 위해 SOAR 도구 (보안 오케스트레이션, 자동화 및 응답) 와 보안 경보 통합
- API키를 작성하십시오.
- API키를 사용하여 토큰을 생성하십시오.
- 토큰을 사용하여 REST API에 액세스하십시오.
REST API키 생성
사용자 액세스 관리 대시보드에 액세스하면 이미 작성된 REST API키 목록이 표시됩니다.
- 관리자 자격 증명을 사용하여 IBM Storage Insights에 로그인합니다.
- 클래식 UI에서 [ 로 이동합니다.
현대식 UI에서 ’로 이동합니다.
- 사용자 액세스 관리 페이지에서 키를 생성할 사용자에 대해 세 개의 세로 점이 있는 오버플로우 메뉴를 클릭하고 REST API키 작성을 선택하십시오.
- 다음 필드에 세부사항을 입력하십시오.
- 태그(선택 사항) : 참조를 위해 선택 사항으로 태그를 입력합니다. 예를 들어 태그를 사용하여 API 키의 용도를 식별할 수 있습니다.
- 시간 단위: 사용자에게 API키를 제공할 때까지의 시간 한계를 선택하십시오. 옵션에는 일, 1년및 2년이 포함됩니다.
- 지속 기간/일: 시간 단위 필드에서 일 수 옵션을 선택한 경우 사용자에게 API키를 제공할 때까지의 일 수를 표시합니다.
- ‘만들기 +’ 버튼을 클릭하세요.
- API키 필드의 오른쪽 구석에 있는 복사 단추에서 API키를 복사하십시오.
- 이메일 또는 기타 적합한 방법을 통해 사용자와 API키를 공유하십시오.
REST API키 취소
- 관리자 자격 증명을 사용하여 IBM Storage Insights에 로그인합니다.
- 클래식 UI에서 [ 로 이동합니다.
현대식 UI에서 ’로 이동합니다.
- 액세스 권한을 취소할 사용자를 목록에서 선택하십시오.
- 클래식 UI에서는 목록 상단의 ‘키 액세스 취소’를 클릭하거나, 세 개의 수직 점으로 표시된 오버플로 메뉴를 클릭한 후, 선택한 사용자의 행에서 ‘액세스 취소’를 선택하세요.
현대식 UI에서는 목록 상단에 있는 ‘키 액세스 취소’를 클릭하세요.
주: 한 번에 여러 사용자를 선택하여 액세스를 취소할 수 있습니다. - 팝업 창에서 키 액세스 취소 를 클릭하십시오.
REST API 키 순환/갱신
- 관리자 자격 증명을 사용하여 IBM Storage Insights에 로그인합니다.
- 클래식 UI에서 [ 로 이동합니다.
현대식 UI에서 ’로 이동합니다.
- REST API키 열에서 사용자의 REST API키 수를 클릭하십시오. REST API키 창이 사용자에 대한 모든 API키의 세부사항과 함께 표시됩니다. REST API키 창은 취소, 키 순환/갱신및 키 복사 옵션을 제공합니다.참고: 개수가 있는 초록색 아이콘은 사용자의 활성 API키 수를 지정하고 개수가 있는 빨간색 아이콘은 사용자의 만료된 API키를 지정합니다.
- API 키를 선택하고 키 회전/갱신을 클릭합니다. 다음 필드에 세부사항을 입력하십시오.
- 태그(선택 사항) : 참조를 위해 선택 사항으로 태그를 입력합니다. 예를 들어 태그를 사용하여 API 키의 용도를 식별할 수 있습니다.
- 시간 단위: 사용자에게 API키를 제공할 때까지의 시간 한계를 선택하십시오. 옵션에는 일, 1년및 2년이 포함됩니다.
- 지속 기간/일: 시간 단위 필드에서 일 수 옵션을 선택한 경우 사용자에게 API키를 제공할 때까지의 일 수를 표시합니다.
참고: 사용자가 여러 API키를 선택하는 경우 키 회전/갱신 및 키 복사 옵션을 사용할 수 없습니다. - 작성+ 단추를 클릭하여 새 키를 생성하십시오. 기존 API키가 올바르지 않으며 새 키가 생성됩니다.
- 복사 단추를 클릭하여 새 키를 복사하십시오.
API 토큰 생성
IBM Storage Insights GUI에서 API 키를 생성한 후, IBM Storage Insights 토큰 API를 실행하여 API 토큰을 생성해야 합니다. 나머지 IBM Storage Insights REST API를 실행하려면 API 토큰이 필요합니다. 토큰 API를 실행하려면 생성된 API 키를 x-api-key 헤더에 설정해야 합니다. 토큰 API에 대한 자세한 내용은 Swagger 문서를 참조하십시오.
API 토큰을 생성한 후, 나머지 IBM Storage Insights REST API를 실행할 수 있습니다. 다른 REST API를 실행할 때는 x-api-token 헤더에 API 토큰을 설정해야 합니다.
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는 두 개의 조회 매개변수입니다.
이전 예제에서 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를 찾습니다.
IBM Storage Insights 인스턴스의 테넌트 ID입니다. 예를 들어, IBM Storage Insights URL 의 URL이 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()