【初心者向け】AWS Health イベントをBacklog 課題として自動起票する

記事タイトルとURLをコピーする

本記事は、「AWS Health イベントをBacklog 課題として自動起票する」方法について知りたい方向けの記事です。

こんにちは!エンタープライズクラウド部クラウドコンサルティング課の日高です。
もし私のことを少しでも知りたいと思っていただけるなら、私の後輩が書いてくれた以下のブログを覗いてみてください。

sabawaku.serverworks.co.jp

はじめに

普段ご支援させていただいているお客様から、以下のような声を頂戴しました。
「AWS Health の通知が多すぎて重要なイベントを見逃してしまうことがある。失念を防ぐため、特定の AWS Health イベントを Backlog に自動で起票できる仕組みが欲しい!」

こちらを手動起票するのは大変なので、AWS サービスを用いて自動起票する仕組みについて本ブログでご紹介させていただきます。
本ブログで構築する仕組みの全体像は以下の通りです。

自動起票の仕組みの構築(AWS リソース前編)

全体像の解説

以下で、それぞれの役割を簡単に説明します。

1.AWS Personal Health Dashboard

  • AWS のサービスに問題が発生したり、メンテナンスの予定がある場合に通知を受け取ることができるサービスです。
  • これが、今回の自動化の起点となります。特定のイベント(例えば障害やメンテナンス)が発生した時に、このダッシュボードから情報を受け取ります。

2.Amazon EventBridge

  • AWS Personal Health Dashboard で発生したイベントを検知し、次に何をするかを決めるのがこのサービスです。
  • EventBridge では「ルール」を設定し、特定のイベントが発生した場合に自動的に処理を行うようにしています。
  • 今回は、特定の AWS Health イベントを検知して、自動的に処理を開始します。

3.AWS Lambda

  • EventBridge から送られてきたイベント情報を受け取り、Backlog に課題を自動的に作成する役割を担っています。
  • Lambda はサーバーレスのコンピューティングサービスで、自動起票の仕組みを実現しているプログラムを Lambda 上で動作させています。

4.AWS Secrets Manager

  • セキュリティを保つための認証情報(例えば API キーやパスワード)を安全に管理するサービスです。
  • Lambda が Backlog にアクセスする際、この Secrets Manager から認証情報を取得して、セキュリティを確保しています。

5.Backlog

  • Backlog API を用いて、課題の自動起票が行われます。

AWS Lambda 用の IAM Role の作成

AWS Lambda が他の AWS サービス(今回の場合は EventBridge や Secrets Manager)と安全にやり取りできるように、適切な権限を持った IAM Role を作成します。IAM Role は、AWS リソースに対するアクセス権限を定義するものです。

まず、AWS マネジメントコンソールで IAM のダッシュボードを開き、「ロールを作成」を選択します。
信頼されたエンティティでは「AWSのサービス」→「Lambda」を選択してください。

許可ポリシーでは以下 3 つのポリシーを選択して付与します。

  • AWSLambdaBasicExecutionRole:Lambda が実行されるために必要な基本的な権限です。(Lambda 関数が CloudWatch Logs にログを書き込む etc...)
  • AmazonEventBridgeFullAccess:EventBridge から Lambda をトリガーするのに必要な権限を持っています。今回は検証用途なので、「FullAccess」を付与します。(※)
  • SecretsManagerReadWrite:Secrets Manager の読み書きに必要な最低限の権限を提供しますが、フルアクセス権限(SecretsManagerFullAccess)ほど広くはありません。このポリシーを適用することで、Lambda 関数が必要な認証情報を取得し、Secrets Manager に対して適切にアクセスできるようにします。

IAM ロール名は今回は「LambdaBacklogAutomationRole」として、必要なポリシーが付与されていることを確認したら「ロールを作成」を選択します。

Backlog API 利用の準備

Backlog 利用の準備

Backlog APIを使用して課題を自動で作成するためには、APIキーを取得する必要があります。
以下の手順に従って、Backlog APIキーを生成してください。

support-ja.backlog.com

※メモには、「LambdaIntegration」など、用途に応じた名前を設定しておくと後々分かりやすくなります。

この後に、API キーを利用するのでコピーしておいてください。

シークレットの作成

AWS Secrets Manager のシークレットの作成

AWS Secrets Manager を使って、Backlog API にアクセスするための認証情報(API キーなど)を安全に管理します。

マネジメントコンソールで「Secrets Manager」に移動し、「新しいシークレットを保存する」を選択し、以下の設定値で「次」を選択します

  • シークレットのタイプ:その他のシークレットのタイプ
Key Value
backlog_api_key <コピーしていた API キーを貼り付けます>
backlog_project_id <※Backlogのプロジェクト ID を貼り付けます>

※BacklogのプロジェクトIDの調べ方は、プロジェクトのIDは、「プロジェクト設定」ページに移動した際のURLを見ると書いてあります。
https://{スペースの名前}.backlog.jp/EditProject.action?project.id=xxxxxxxx

シークレットに名前を付けます。たとえば「backlog-api-key-secret」とします。

上記以外はデフォルトで次のページに遷移し続け「保存」を選択します。
また、マネジメントコンソールの Secrets Manager で、シークレットの詳細ページに移動し、シークレットの ARN をコピーしておきます。

AWS Lambda 関数の作成

AWS Lambda の準備

IAM Role の設定が完了したら、次に AWS Lambda 関数を作成します。
Lambda 関数は、EventBridge からトリガーされた際に実行され、Backlog に自動的に課題を起票する処理を行います。

AWS マネジメントコンソールで Lambda のダッシュボードに移動し、以下の設定を行ったのち「関数の作成」を選択します。

  • 関数名: BacklogAutoTicketFunction(この名前は用途が分かりやすいように付けます)
  • ランタイム: ご希望の言語を選択します。ここでは例として Python (Python 3.12)を使います。
  • 実行ロール: 「既存のロールを使用する」を選択し、先ほど作成した IAM ロール「LambdaBacklogAutomationRole」を割り当てます。

タイムアウト値の変更

Lambda 関数の作成が完了したら、タイムアウト値の変更を行います。
デフォルトで、3 秒経ったらタイムアウトしコードの処理が中断されてしまうためです。

  1. Lambda 関数の「設定」タブを開き、「一般設定」のセクションに移動します。
  2. 編集を選択し、タイムアウトを 1 分に設定します。
  3. 保存して設定完了です。

環境変数の指定

次の章で利用する変数をあらかじめ、Lambda の環境変数設定に追加しておきます。

  1. Lambda 関数の「設定」タブを開き、「環境変数」のセクションに移動します。
  2. KEY に 以下の表に記載のある通りに入力します
  3. 保存して設定完了です。
Key Value
SECRET_ARN <先ほどコピーした値を貼り付け>
REGION ap-northeast-1
ASSIGNEE_ID <Backlogの課題担当者に設定したい方の担当者 ID を記載(※)>
ISSUE_TYPE_ID <課題の種別 ID の記載(※)>
PRIORITY_ID <課題の優先度の数字を記載(※)>

※.Backlog の各種IDの調べ方は以下のとおりです。( Mac の場合のコマンドになる点に注意してください)

  • 担当者 ID :curl -X GET "https://{your-backlog-space-name}.backlog.jp/api/v2/projects/{projectId}/users?apiKey={your-api-key}" の実行結果から課題担当者に設定したい方の担当者 ID を探す。(実行結果 から user id ではなく、id になる点にご注意ください。)
  • 種別 ID :curl -X GET "https://{your-backlog-space-name}.backlog.jp/api/v2/projects/{projectId}/issueTypes?apiKey={your-api-key}" の実行結果から設定したい種別 ID を探す
  • 課題の優先度の数字:優先度中が「3」

※2024年10月28日追記
backlog.jp ではなく、backlog.com の場合もあるためご注意ください。

自動起票の仕組みの構築(コード編)

関数のコード

関数のコードの準備

Lambda 関数のコードでは、AWS Secrets Manager から API キーを取得し、Backlog の API を呼び出して課題を自動的に作成する処理を行います。このコードは Python を使って実装していますが、他の言語でも同様の流れで実装できます。

※backlog_url だけ適切な形に修正をした上でご利用ください。

import json
import boto3
import os
import urllib3
from datetime import datetime

# Secrets Manager から Backlog の API キーとプロジェクトIDを取得
def get_secret():
    secret_arn = os.environ['SECRET_ARN']  # 環境変数からシークレットの ARN を取得
    region_name = os.environ['REGION']  # 環境変数からAWSリージョンを取得
    client = boto3.client("secretsmanager", region_name=region_name)
    response = client.get_secret_value(SecretId=secret_arn)
    secret = json.loads(response["SecretString"])
    
    # キーが存在しない場合のエラーハンドリング
    if "backlog_api_key" not in secret or "backlog_project_id" not in secret:
        raise KeyError("Secrets Manager に 'backlog_api_key' または 'backlog_project_id' が含まれていません")
    
    return secret["backlog_api_key"], secret["backlog_project_id"]

def format_event_details(event_detail):
    """
    Health イベントの詳細を整形して読みやすい形に変換する関数
    """
    service = event_detail.get('service', '不明なサービス')
    event_type = event_detail.get('eventTypeCode', '不明なイベント')
    start_time = event_detail.get('startTime', '開始時間なし')
    end_time = event_detail.get('endTime', '終了時間なし')
    status_code = event_detail.get('statusCode', 'ステータスなし')
    event_region = event_detail.get('eventRegion', '不明なリージョン')  
    event_scope = event_detail.get('eventScopeCode', '不明なスコープ')  
    affected_account = event_detail.get('affectedAccount', '不明なアカウント')  
    communication_id = event_detail.get('communicationId', '不明な通信ID')  
    description = event_detail.get('description', '詳細なし')

    # 読みやすい形にフォーマット
    event_info = (
        f"サービス: {service}\n"
        f"イベントタイプ: {event_type}\n"
        f"ステータス: {status_code}\n"
        f"リージョン: {event_region}\n"
        f"スコープ: {event_scope}\n"
        f"影響を受けたアカウント: {affected_account}\n"
        f"通信ID: {communication_id}\n"
        f"開始時間: {start_time}\n"
        f"終了時間: {end_time}\n"
        f"詳細:\n{description}\n"
    )
    
    return event_info

def convert_to_iso_format(date_str):
    """
    AWS Health イベントの日付を ISO 8601 形式 (YYYY-MM-DD) に変換する関数
    """
    try:
        # AWS Health イベントの日付は ISO 8601 タイムスタンプ形式 (例: 2024-10-15T08:00:00Z)
        dt = datetime.strptime(date_str, '%Y-%m-%dT%H:%M:%SZ')
        return dt.strftime('%Y-%m-%d')
    except Exception as e:
        return None  # 日付が無効な場合は None を返す

def lambda_handler(event, context):
    try:
        # Secrets Manager から Backlog の API キーとプロジェクトIDを取得
        api_key, project_id = get_secret()
        backlog_url = f"https://<プロジェクト名に書き換えてください>.backlog.jp/api/v2/issues?apiKey={api_key}"

        # 環境変数から設定を取得
        issue_type_id = os.environ['ISSUE_TYPE_ID']  # 環境変数から課題タイプIDを取得
        priority_id = os.environ['PRIORITY_ID']  # 環境変数から優先度IDを取得
        assignee_id = os.environ['ASSIGNEE_ID']  # 環境変数から課題担当者IDを取得

        # Healthイベントの情報を取得
        event_detail = event.get('detail', {})
        formatted_event_info = format_event_details(event_detail)

        # 開始日と終了日を取得し、ISOフォーマットに変換
        start_time = event_detail.get('startTime', None)
        end_time = event_detail.get('endTime', None)
        start_date = convert_to_iso_format(start_time) if start_time else None
        due_date = convert_to_iso_format(end_time) if end_time else None

        # Backlog に作成する課題のデータ
        issue_data = {
            "projectId": project_id,  # Secrets Manager から取得したプロジェクトIDを使用
            "summary": f"AWS Health イベント: {event_detail.get('eventTypeCode', '不明なイベント')}",  # 課題のタイトル
            "description": formatted_event_info,  # フォーマットしたHealth イベントの詳細を本文に挿入
            "issueTypeId": issue_type_id,  # 環境変数から取得した課題タイプIDを使用
            "priorityId": priority_id,  # 環境変数から取得した優先度IDを使用
            "assigneeId": assignee_id,  # 環境変数から取得した課題担当者IDを設定
            "startDate": start_date,  # Healthイベントの開始日を設定
            "dueDate": due_date  # Healthイベントの終了日を設定
        }

        # Backlog API にリクエストを送信して課題を作成
        http = urllib3.PoolManager()
        headers = {'Content-Type': 'application/json'}
        response = http.request(
            'POST',
            backlog_url,
            body=json.dumps(issue_data).encode('utf-8'),
            headers=headers
        )

        # レスポンスの確認
        if response.status == 201:
            return {
                "statusCode": 200,
                "body": json.dumps("課題が正常に作成されました!")
            }
        else:
            return {
                "statusCode": response.status,
                "body": json.dumps(f"エラー: {response.data.decode('utf-8')}")
            }
    except KeyError as e:
        return {
            "statusCode": 400,
            "body": json.dumps(f"エラー: {str(e)}")
        }

関数のコード解説

以下に、Lambda 関数のコードのポイントを説明します。

1.Secrets Manager からの認証情報の取得

  • get_secret() 関数では、AWS Secrets Manager から Backlog の API キーやプロジェクトIDを安全に取得します。この方法で認証情報をコードに直接記述せず、セキュリティを保ちながら運用できます。
  • secret_arn は環境変数から取得され、AWS SDK(boto3)を使ってシークレット情報を安全に取得しています。

2.イベントの詳細の整形

  • format_event_details() 関数では、AWS Health イベントの情報(※)をわかりやすい形式に整形しています。
  • Health イベントのサービス名やイベントタイプ、開始時間などの情報を整形し、課題の説明に入れ込みます。
  • 例えば、"サービス: EC2" や "イベントタイプ: メンテナンス" などを表示します。

※AWS Health イベントの Amazon EventBridge スキーマを元にコードを記載しています。詳しくは以下の公式ドキュメントをご覧ください。

docs.aws.amazon.com

3.開始日と終了日の整形

  • AWS Health イベントで提供される startTime と endTime は、ISO 8601 フォーマット(YYYY-MM-DDTHH:MM:SSZ)で提供されるため、それを YYYY-MM-DD 形式に変換するための関数が convert_to_iso_format() です。
  • この関数は、イベントの日付を Backlog の課題の開始日(startDate)と終了日(dueDate)として設定します。

  • Backlog 課題データの作成

  • issue_data という変数に、Backlog 課題に必要なデータを詰め込んでいます。

  • このデータには、課題のタイトル(summary)、課題の説明(description)、課題の種別ID(issueTypeId)、優先度ID(priorityId)、担当者ID(assigneeId)が含まれています。
  • 課題の開始日と終了日も、Health イベントに基づいて自動的に設定されます。

5.Backlog API へのリクエスト

  • 最後に、urllib3 を使って Backlog API へ HTTP POST リクエストを送信し、自動で課題を作成します。
  • 成功時にはステータスコード 200(成功メッセージ)を返し、失敗時にはステータスコードとエラーメッセージを返します。

関数のテスト

Lambda 関数のテストイベントに、以下のような形のイベント(テスト用の Helth イベント)を作成・保存します。

{
  "version": "0",
  "id": "12345678-1234-1234-1234-123456789012",
  "detail-type": "AWS Health Event",
  "source": "aws.health",
  "account": "123456789012",
  "time": "2024-10-15T08:00:00Z",
  "region": "ap-northeast-1",
  "resources": [],
  "detail": {
    "eventTypeCode": "AWS_EC2_SYSTEM_MAINTENANCE_EVENT",
    "service": "EC2",
    "eventTypeCategory": "scheduledChange",
    "startTime": "2024-10-15T08:00:00Z",
    "endTime": "2024-10-15T09:00:00Z",
    "statusCode": "open",
    "description": "EC2インスタンスのメンテナンスが予定されています。"
  }
}

実際にテストを実行してみます。

結果として、以下のような出力がコンソールから出れば成功です。

Test Event Name
(unsaved) test event

Response
{
  "statusCode": 200,
  "body": "\"\\u8ab2\\u984c\\u304c\\u6b63\\u5e38\\u306b\\u4f5c\\u6210\\u3055\\u308c\\u307e\\u3057\\u305f\\uff01\""
}

Function Logs
START RequestId: c206acbb-b211-4e7a-8717-affb29bbb86a Version: $LATEST
END RequestId: c206acbb-b211-4e7a-8717-affb29bbb86a
REPORT RequestId: c206acbb-b211-4e7a-8717-affb29bbb86a  Duration: 3538.29 ms    Billed Duration: 3539 ms    Memory Size: 128 MB Max Memory Used: 77 MB  Init Duration: 300.11 ms

Request ID
c206acbb-b211-4e7a-8717-affb29bbb86a

実際に Backlog に課題が起票されていることも確認できました。

自動起票の仕組みの構築(AWS リソース後編)

Amazon EventBridge の設定

Amazon EventBridge を使用して、AWS Health イベントをトリガーにして、Lambda 関数を自動的に実行するように設定します。
以下の手順に従って、EventBridge の設定を行います。

ステップ 1: ルールを作成

  • マネジメントコンソールから Amazon EventBridge の画面に遷移し、「ルールを作成」を選択します。
  • ルールの名前と説明を入力します。
  • ルールタイプにて「イベントパターンを持つルール」を選択します。

ステップ 2: イベントパターンの定義

  • イベントソース:「AWSのサービス」を選択します。
  • AWSのサービス: 「Health」を選択します。
  • イベントタイプ: 「特定のヘルスイベント」を選択します。(今回は、Direct Connect 関連のイベントを通知するように設定してみます。)
  • イベントタイプの仕様1:「特定のサービス」を選択します。
  • 特定のサービス:「DIRECTCONNECT」を選択します。
  • それ以外はデフォルトのまま次へを選択します。

ステップ 3: ターゲットの設定

  • 次に、ルールのターゲットを指定します。
  • ターゲットとして AWS Lambda 関数 を選択し、先ほど作成した Lambda 関数「BacklogAutoTicketFunction」を選択します。

ステップ 4: その他の設定

  • その他のオプションはデフォルトのままで「ルールを作成」をクリックして保存します。

これで、AWS Health イベントが発生した際に、EventBridge がそのイベントをトリガーとして Lambda 関数を自動的に実行する設定が完了しました。

まとめ

AWS Health イベントをBacklog 課題として自動起票する仕組みについて解説してみました。
本記事が誰かの助けになれば幸いです。

日高 僚太(執筆記事の一覧)

2024 Japan AWS Jr. Champions / 2024 Japan AWS All Certifications Engineers

EC部クラウドコンサルティング課所属。2022年IT未経験でSWXへ新卒入社。
記事に関するお問い合わせや修正依頼⇒ hidaka@serverworks.co.jp