ServiceNow로 알람 관리

이 항목에서는 알람이 실행될 때마다 자동 ServiceNow 티켓을 제출하는 방법에 대해 설명합니다.

이 시나리오에서는 CPU 사용량이 알람으로 지정된 임계값을 초과할 때마다 호출 중인 엔지니어를 위해 ServiceNow 티켓이 생성됩니다.

Oracle Cloud Infrastructure 콘솔, API 또는 CLI를 통해 클라우드 리소스에 설명, 태그 또는 친화적인 이름을 지정할 때 기밀 정보를 입력하지 마십시오.

이 시나리오에서는 ServiceNow 티켓을 제출(및 ServiceNow 자격 증명을 저장할 암호 만들기), 해당 기능 및 선택적 전자 메일을 토픽구독으로 추가하고, 알람 임계값이 초과될 때 해당 토픽으로 메시지를 전송하는 알람을 만드는 작업이 포함됩니다. 메시지는 해당 기능과 함께 그룹 전자메일 주소를 포함하는 토픽의 구독으로 팬아웃됩니다. 메시지 수신 시 함수가 호출됩니다.

기능을 제외한 모든 항목을 콘솔에서 설정할 수 있습니다. 또는 Oracle Cloud Infrastructure CLI 또는 API를 사용하여 개별 작업을 직접 실행할 수도 있습니다.

다음 다이어그램은 일반 프로세스 플로우를 보여줍니다.



서비세노우 통지-oracle.zip

암호에 ServiceNow 인증서 저장

나중에 함수를 생성할 때 참조할 암호를 생성합니다.

콘솔을 사용하여 암호를 만듭니다. CLI(명령줄 인터페이스) 또는 API(응용 프로그램 프로그래밍 인터페이스)를 사용하여 암호를 만들 수도 있습니다.

  1. 탐색 메뉴를 열고 ID 및 보안을 누른 다음 저장소를 누릅니다.
  2. List Scope(목록 범위) 아래의 Compartment(구획) 목록에서 암호를 만들려는 구획의 이름을 누릅니다.
  3. 구획의 저장소 목록에서 다음 중 하나를 수행합니다.
    • 암호를 만들 저장소의 이름을 누릅니다.
    • 암호에 대한 새 저장소를 만든 다음 저장소 이름을 누릅니다.
  4. username 암호를 만듭니다.
    1. 암호를 누른 다음 암호 생성을 누릅니다.
    2. Create Secret 대화 상자의 Create in Compartment 목록에서 구획을 선택합니다. 암호는 저장소가 있는 구획 외부에 존재할 수 있습니다.)
    3. 이름을 누른 다음 암호를 식별할 이름을 입력합니다. 이 필드에는 기밀 정보를 입력하지 마십시오.
      이름 예: servicenow_username_plain_text
    4. 설명을 누른 다음 식별에 도움이 되는 암호에 대한 간단한 설명을 입력합니다. 이 필드에는 기밀 정보를 입력하지 마십시오.
      설명 예: servicenow_username_plain_text
    5. 저장소로 임포트되는 동안 보안 콘텐츠를 암호화하는 데 사용할 마스터 암호화 키를 선택합니다(키가 동일한 저장소에 속해야 함).
    6. 암호 유형 템플리트의 경우 일반 텍스트를 선택합니다.
    7. 비밀 콘텐츠를 누른 다음 ServiceNow 사용자 이름을 입력합니다.
      <your-servicenow-username>
    8. 암호 생성을 누릅니다.
    9. 암호 OCID를 확인합니다.

함수 생성

아래 샘플 코드로 시작하여 ServiceNow 티켓을 제출하는 함수를 생성한 다음 Oracle Cloud Infrastructure Vault 서비스를 사용하여 생성된 암호에서 ServiceNow 인증서에 액세스할 수 있는 권한을 부여합니다.

코드 예제에는 가상 함수에 사용되는 SNOW_URL, SNOW_USER_ID_SEC 및 SNOW_USER_PWD_SEC 변수가 포함됩니다. 대신 함수에서 직접 이러한 값을 읽거나 값을 사용자 정의 구성 매개변수로 전달하도록 선택할 수 있습니다.

#####################################################
# THIS SAMPLE CODE IS FOR DEMO PURPOSES ONLY
#*************************************************
# ******** DO NOT USE IN PRODUCTION *************
# ************************************************
#####################################################
import io
import sys
import oci
import json
import base64
import requests
from fdk import response
SNOW_URL = '<Provide Service Now URL here>'
SNOW_USER_ID_SEC = '<Provide the OCID of OCI Secret for Service Now User ID>'
SNOW_USER_PWD_SEC = '<Provide the OCID of OCI Secret for Service Now User Password>'
OCI_TO_SNOW_SEV_MAP =
{    'CRITICAL'  : '1',    'WARNING'   : '2',    'ERROR'     : '3',    'INFO'      : '4' }
def handler(ctx, data: io.BytesIO = None):
    try:
        funDataStr = data.read().decode('utf-8')
        funDataJSON =  json.loads(funDataStr)
        alarmData = {}
        alarmData['type'] = funDataJSON['type']
        alarmData['metaDataList'] = funDataJSON['alarmMetaData']
        alarmData['title'] = funDataJSON['title']
        alarmData['body'] = funDataJSON['body']
        alarmData['sev'] = OCI_TO_SNOW_SEV_MAP[funDataJSON['severity'].upper()]
        if alarmData['type'].upper() == 'OK_TO_FIRING':
            snowURL = SNOW_URL
            snowUsrIDSec = SNOW_USER_ID_SEC
            snowUsrPwdSec = SNOW_USER_PWD_SEC
            ociResPrncplSigner = oci.auth.signers.get_resource_principals_signer()
            ociSecSvc = oci.secrets.SecretsClient(config={}, signer=ociResPrncplSigner)
            snowUserID = readSecValueFromSecSvc(ociSecSvc, snowUsrIDSec)
            snowPswd = readSecValueFromSecSvc(ociSecSvc, snowUsrPwdSec)
            snowData = getSNOWData(alarmData)
            sendDataToSnow(snowURL, snowUserID, snowPswd, snowData)
    except Exception as e:
        sys.stderr.write("Exception : " + str(e))
        sys.stderr.write("Exception Class : " + str(e._class_))
    return response.Response(ctx, response_data="", headers={"Content-Type": "application/json"})
def sendDataToSnow(snowURL, uid, pwd, snowData):
    try:
{ 
snowHdrs =
      "Content-Type" : "application/json",
counter = 0
for sd in snowData:
"Accept" : "application/json"         }
        snowResp = requests.post(snowURL, auth=(uid, pwd), headers=snowHdrs, data=json.dumps(sd))
except Exception as e:
    sys.stderr.write("Exception : " + str(e))
    sys.stderr.write("Exception Class : " + str(e._class_))
   def getSNOWData(alarmData):
       snowData = []
       if alarmData['type'].upper() == 'OK_TO_FIRING':
           alrmMD = alarmData['metaDataList'][0]
           for d in alrmMD['dimensions']:
               snowDataElem = {}
               snowDataElem['node'] = d['resourceDisplayName']
               snowDataElem['source'] = 'OCI'
               snowDataElem['severity'] = alarmData['sev']
               snowDataElem['description'] = alarmData['body']
               snowDataElem['type'] = alarmData['title']
               snowData.append(snowDataElem)
       return snowData
   def readSecValueFromSecSvc(ociSecSvc, secID):
       secResp = ociSecSvc.get_secret_bundle(secID)
       secContent = secResp.data.secret_bundle_content.content
       secret_content = base64.b64decode(secContent).decode('utf-8')
       return secret_content

동적 그룹을 사용하여 암호 읽기 기능을 함수에 부여합니다. 이전에 생성한 암호에 저장된 ServiceNow 인증서에 액세스하려면 함수에 이 권한 부여가 있어야 합니다.

  1. 함수 OCID를 찾아서 다음 형식으로 확인합니다.
    ocid1.fnfunc.oc1.iad.<exampleuniqueID>

    다음 규칙을 지정하여 관련 동적 그룹에 함수를 포함시키십시오.

    resource.id = '<function-ocid>'

    또는 모든 함수를 포함하는 동적 그룹을 생성할 수 있습니다.

    ALL{resource.type=’fnfunc’, resource.compartment.id=’<compartment_OCID>’}
  2. 다음 정책을 추가하여 암호에 대한 동적 그룹 액세스 권한을 부여합니다.
    allow dynamic-group <dynamic-group-name> to read secret-family in tenancy

    컴퓨트 인스턴스와 같은 다른 Oracle Cloud Infrastructure 리소스에 대한 액세스 권한을 부여하려면 함수를 동적 그룹에 포함하고 동적 그룹에 해당 리소스에 대한 액세스 권한을 부여하는 정책을 생성합니다.

항목 생성

구독 및 알람에 사용할 토픽을 생성합니다.

토픽은 구독에 메시지를 전송하는 데 사용되는 통신 채널입니다. 각 토픽 이름은 테넌시에서 고유합니다. 콘솔, CLI(명령줄 인터페이스) 또는 API(응용 프로그램 프로그래밍 인터페이스)를 사용하여 항목을 만들 수 있습니다.

기능을 토픽과 함께 사용하려면 먼저 배포해야 합니다.

  1. 콘솔을 사용하여 항목을 생성하려면 다음과 같이 하십시오.
    1. 탐색 메뉴를 열고 개발자 서비스를 누릅니다. [애플리케이션 통합]에서 통지를 누릅니다.
    2. 주제 목록 상단에 있는 주제 생성을 누릅니다.
    3. 항목 생성 대화 상자에서 항목을 구성합니다.
      • 이름: 친숙한 항목 이름을 지정합니다. 테넌시에서 고유해야 하며, 검증은 대소문자를 구분합니다. 기밀 정보를 입력하지 마십시오.
      • 설명: 선택적으로 항목에 대한 설명을 입력합니다. 기밀 정보를 입력하지 마십시오.
    4. 생성을 누릅니다.
  2. CLI를 사용하여 항목을 만들려면 명령 프롬프트를 열고 다음과 유사한 명령을 입력합니다.
    oci ons topic create
    --name "My Topic"
    --compartment-id "<compartment-ocid>"
  3. API를 사용하여 항목을 생성하려면 다음과 유사한 작업을 사용합니다.
    POST /20181201/topics
    Host: notification.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "name": "My Topic",
      "compartmentId": "<compartment_OCID>"
    }
    

구독 생성

토픽에 대한 구독을 생성합니다.

서브스크립션은 항목의 엔드포인트입니다. 게시된 메시지는 토픽의 각 구독에 전송됩니다.

기능을 구독과 함께 사용하려면 먼저 함수를 배포해야 하며 기능을 토픽에 구독으로 추가하려면 기능에 대한 FN_INVOCATION 권한이 있어야 합니다.

  1. 콘솔을 사용하여 함수 가입을 생성하려면 다음과 같이 하십시오.
    1. 탐색 메뉴를 열고 개발자 서비스를 누릅니다. [애플리케이션 통합]에서 통지를 누릅니다. 구독을 추가할 주제의 이름을 누릅니다.
    2. 토픽 세부정보 페이지에서 구독 생성을 누릅니다.
    3. [구독 생성] 대화상자에서 함수 구독을 구성합니다. 함수 가입에는 확인이 필요하지 않습니다.
      • Subscription 프로토콜의 경우 함수를 누릅니다.
      • 함수 구획의 경우 해당 함수를 포함하는 구획을 누릅니다.
      • 함수 응용 프로그램에 대해 함수가 포함된 응용 프로그램을 누릅니다.
      • 함수의 경우 함수를 클릭합니다.
    4. 생성을 누릅니다.
  2. 콘솔을 사용하여 선택적 전자 메일 가입을 생성하려면 다음과 같이 하십시오.
    1. 탐색 메뉴를 열고 개발자 서비스를 누릅니다. [애플리케이션 통합]에서 통지를 누릅니다. 구독을 추가할 주제의 이름을 누릅니다.
    2. 토픽 세부정보 페이지에서 구독 생성을 누릅니다.
    3. 구독 생성 대화 상자에서 전자메일 구독을 구성합니다.
      • 구독 프로토콜의 경우 전자메일을 누릅니다.
      • 전자메일의 경우 전자메일 주소를 지정합니다.
    4. 생성을 누릅니다.
      전자 메일 가입이 생성되고 가입 확인 URL이 지정된 전자 메일 주소로 전송됩니다. 구독은 확인될 때까지 보류 중 상태입니다. 새 이메일 구독을 확인하려면 이메일을 열고 확인 URL을 클릭하십시오.
  3. CLI를 사용하여 구독을 만들려면 다음을 수행합니다.
    1. 함수 가입을 생성하려면 명령 프롬프트를 열고 다음과 유사한 명령을 입력합니다.
      oci ons subscription create
      --compartment-id "<compartment-ocid>"
      --topic-id "<topic-ocid>" 
      --protocol "ORACLE_FUNCTIONS"
      --subscription-endpoint "<function-ocid>"
    2. 전자 메일 가입을 생성하려면 명령 프롬프트를 열고 다음과 유사한 명령을 입력합니다.
      oci ons subscription create
      --compartment-id "<compartment-ocid>"
      --topic-id "<topic-ocid>" 
      --protocol "EMAIL"
      --subscription-endpoint "team@example.com"
  4. API를 사용하여 구독을 생성하려면 다음을 수행합니다.
    1. API를 사용하여 함수 가입을 생성하려면 다음과 유사한 작업을 사용합니다.
      POST /20181201/subscriptions
      Host: notification.us-phoenix-1.oraclecloud.com
      <authorization and other headers>
      {
        "topicId": "<topic_OCID>",
        "compartmentId": "<compartment_OCID>",
        "protocol": "ORACLE_FUNCTIONS",
        "endpoint": "<function_OCID>"
      } 
    2. API를 사용하여 전자 메일 가입을 생성하려면 다음과 유사한 작업을 사용합니다.
      POST /20181201/subscriptions
      Host: notification.us-phoenix-1.oraclecloud.com
      <authorization and other headers>
      {
        "topicId": "<topic_OCID>",
        "compartmentId": "<compartment_OCID>",  
        "protocol": "EMAIL",
        "endpoint": "team@example.com"
      
      } 

알람 생성

알람 임계값이 초과될 때마다 토픽에 메시지를 전송하는 알람을 생성합니다. 그러면 통지가 해당 토픽의 활성 구독에 메시지를 전달합니다.

  1. 콘솔을 사용하여 알람을 만들려면 다음과 같이 하십시오.
    1. 탐색 메뉴를 열고 관찰 가능성 및 관리를 누릅니다. 모니터링에서 알람 정의를 누릅니다.
    2. 알람 생성을 누릅니다.
    3. 알람 생성 페이지의 알람 정의에서 임계값을 설정합니다.
      Metric 설명 아래:
      • 컴파트먼트: 원하는 컴퓨트 인스턴스를 포함하는 구획을 선택합니다.
      • 측정항목 이름 공간: oci_computeagent
      • 측정항목 이름: CpuUtilization
      • 간격: 1m
      • 통계: 개수
      트리거 규칙 아래:
      • 운영자: greater than
      • 값: 90
      • 트리거 지연 시간(분): 1
    4. 알람 통지를 정의하려면 이전에 생성한 토픽을 대상으로 추가합니다.
      대상 아래:
      • 대상 서비스: Notifications
      • 구획: (토픽이 포함된 구획 선택)
      • 항목: (항목 선택)
    5. 알람 저장을 누릅니다.
  2. CLI를 사용하여 알람을 만들려면 명령 프롬프트를 열고 다음과 유사한 명령을 입력합니다.
    oci monitoring alarm create
    --display-name "My Alarm"
    --compartment-id "<compartment-ocid>" 
    --metric-compartment-id "<compartment-ocid>" 
    --namespace "oci_computeagent" 
    --query-text "CPUUtilization[1m].count() > 90"
    --severity "CRITICAL"
    --destinations "<topic-ocid>"
    --is-enabled true
  3. API를 사용하여 알람을 생성하려면 다음과 유사한 작업을 사용합니다.
    POST /20180401/alarms
    Host: telemetry.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "displayName": "My Alarm",
      "compartmentId": "<compartment_OCID>",
      "metricCompartmentId": "<compartment_OCID>",
      "namespace": "oci_computeagent",
      "query": "MemoryUtilization[1m].max() > 90",
      "severity": "CRITICAL",
      "destinations":
        [
          "<topic_OCID>"
        ],
      "isEnabled": true
    }