OPS

Backlogタスクの定期チェックと通知をSlackで受け取る方法

2022.02.18

本記事のポイント

本記事では、Backlogの通知をSlackで受け取る方法をご紹介します。

流れとしては、APIを活用してBacklogに割り当てられたタスクを検索し、ヒットした場合にSlackへ通知するための処理を、Lambdaで設定していきます。Lambdaを定期的に実行することでタスクをチェックする手間を減らし、対応漏れを防ぐことが可能です。

なお、定期実行するためにAmazon EventBridgeをLambdaに連携したり、ほかにもAPIキーをコードに平文で記述しないためにAWS Key Management Service (KMS)を使用したりするなど複数のAWSサービスを活用しています。

初心者の方でも設定いただけるよう、画像付きの分かりやすい手順書形式で解説します。



はじめに

国内外170万人以上が利用するプロジェクト管理ツール「Backlog」ですが、チームの課題やタスク管理、お客様のやりとりなどで利用される方も多いと思います。

このBacklogですが、日々テンプレート化されたようなタスクを数多く受け取っており、タスクがないかチケットを検索して確認するのが面倒だと、手間に感じる方もいらっしゃるのではないでしょうか?

そこで今回は、Backlog APIとAWSのサービスを活用して、backlogのタスクを自動で定期チェックし、ビジネスチャットツールslackへ通知する方法をご紹介します。

> Amazon Web Services (AWS) 運用監視 – 代行サービス 詳細はこちら

対応事項 概要

「サーバ設定変更依頼」というキーワードでBacklogの課題を検索し、ヒットしたものの中から「未対処」もしくは「処理中」の状態の課題をタスクとしてslackで通知できることを目標にします。また、この処理を平日AM10:00に定期実行するよう設定します。

本記事では以下のサービス・言語を使用しています。

AWSサービス

  • AWS Lambda
  • Amazon EventBridge
  • KMS (AWS Key Management Service)
  • AWS IAM

  • 言語

  • Python


  • 事前準備

    Slackの Webhook URLを取得

    まずはじめに、Slack に通知するために必要な『Incoming Webhook』を設定します。

    Slackのデスクトップアプリを使用している場合は、左上の『メニューボタン』→『開始』→『App』と進みます。



    検索欄に「incoming webhook」を入力して、利用可能なアプリに表示された『Incoming WebHooks』をクリックすると、Webブラウザで設定ページが開きます。



    『Slack』に追加をクリックして設定画面に進みます。



    通知するチャンネルを指定し、『Incoming Webhook インテグレーションの追加』をクリックします。



    遷移した画面で『Webhook URL』をコピーして控えておき、『設定を保存する』をクリックします。
    ※名前やアイコンは必要に応じて適宜設定してください。



    Backlogの APIキーを取得

    ユーザーのアイコンをクリックし、『個人設定』を選択します。



    画面左の『API』を選択し、『登録』でAPIキーを発行後、コピーして控えておきます。



    KMSキーを作成

    APIキーを平文でコードに埋め込むことを避けるために、AWS KMSの「KMSキー」を使用します。
    APIキーをLambdaの設定画面上で環境変数として設定し暗号化します。コード内で環境変数を呼び出して復号化させる処理を行います。

    AWSのコンソールにログインし、KMSの画面に遷移後、『カスタマー管理型のキー』より『キーの作成』をクリックします。



    キーの作成画面で以下の通り選択し、『次へ』をクリックして進みます。

  • キーのタイプ:対称
  • キーマテリアルオリジン:KMS
  • リージョンごと:『単一』or『マルチ』使用用途に応じて選択



  • 『エイリアス』に任意の名前を設定し、『次へ』をクリックして進みます。



    『キーの管理アクセス許可』画面では、以下の通り設定し、『次へ』をクリックして進みます。

  • キー管理者:任意のユーザーを指定
  • キーの削除:必要に応じてチェック



  • 『キーの使用アクセス許可』画面では、Lambdaを実行するユーザーを指定し、『次へ』をクリックして進みます。



    確認画面で『完了』をクリックしてKMSキーを作成します。



    作成したKMSキーのARNを控えます。
    次にKMSで復号するためのIAMポリシーを作成します。

    IAMポリシーの画面に進み、『ポリシーを作成』をクリックします。



    以下の通り設定し、『次のステップ: タグ』をクリックして進みます。

  • サービス:KMS
  • アクション:Decrypt
  • リソース:指定にチェックを入れ、『ARNの追加』をクリックして、KMSのARNを入力



  • ARNの追加の画面では、『KMS keyのARNの指定』に作成したKMSキーのARNを入力し、『変更の保存』をクリックして元の画面に戻ります。
    ※ARNを入力すれば、『Region』『Account』『Key id』は自動入力されます。



    タグの設定画面は必要に応じて設定し、『次のステップ: 確認』をクリックして進みます。
    『ポリシーの確認』画面では『名前』に任意のポリシー名を入力し、『ポリシーの作成』をクリックします。



    本作業

    コーディング

    import requests
    import json
    import boto3
    import os
    from base64 import b64decode
    
    def lambda_handler(event, context):
        backlog_apikey = apikey
        backlog_api_url = '〓https://xxxxxxxx.backlog.jp〓/api/v2/issues'
    
        slack_url = "〓slackのwebhook URL〓"
        backlog_search_url = "〓Backlogの対象プロジェクトのURL〓"
    
        #---------------------------------------------------------------------------------
    
        # 検索フィルタ
        payload_check = {
            'apiKey': backlog_apikey,
            'projectId[]': '〓プロジェクトID〓',
            'issueTypeId[]': '〓種別ID〓',
            'keyword': '〓サーバ設定変更依頼〓',
            'statusId[]': ['1', '2'] #(4:完了, 3:処理済み, 2:処理中, 1:未対応)
        }
    
        # チケット検索
        search_issues = requests.get(backlog_api_url, params=payload_check)
    
    
        # slack通知用の関数
        def slack_message(msg):
            requests.post(slack_url, data=json.dumps(msg))
    
    
        # slack通知内容
        ## 要確認
        info_msg = {
            "text":f"〓未対応の<{backlog_search_url}|サーバ設定変更依頼>があります。〓",
            "username":"〓Task Checker〓",
            "icon_emoji":"〓:warning:〓"
        }
    
    
        # チケットを検索し、該当するチケットが存在する場合は、slack通知
        try:
            get_issue = search_issues.json()[0]['issueKey']
            slack_message(info_msg)
    
        except IndexError:
            pass
    

    コードの補足説明

    コード内の〓で括った個所は環境に応じて編集が必要な個所です。

  • backlog_apikey:BacklogのAPIキー。ただし、平文での記述を避けるため、apikeyとしておきます。
    ※後ほど、Lambdaの環境変数で設定します。

  • backlog_api_url:Backlogにアクセスする際のURL『 https://xxxxxxxx.backlog.jp 』(x部分は、ご利用の環境によって異なります)に『/api/v2/issues』を足したものを記述。

  • slack_url:slackのwebhook URLを記述。

  • backlog_search_url:後述の「▼Backlogの『プロジェクトID』などを取得する方法」にて検索結果の画面で取得できる『短いURL』を記述。
    ※slackのメッセージにこのリンクを含めるために使用します。
    ※短縮URLでなくても問題ありません。

  • # 課題検索フィルタ

  • ・projectId[]:『プロジェクトID』
    ・issueTypeId[]:『種別ID』
    ・keyword:課題の検索ワードを入力(本記事では『サーバ設定変更依頼』とする)
    ・statusId[]:『状態ID』を取得して記述。
    ※各IDについては「▼Backlogの『プロジェクトID』などを取得する方法」を参照

  • # slack通知内容

  • ・text:ここにメッセージの内容を記述します。
    ・username:通知するユーザー名を指定します。
    ・icon_emoji:アイコンを指定することができます。
    ※アイコンの文字コードは https://www.webfx.com/tools/emoji-cheat-sheet/ を参照

    通知例)

    Backlogの『プロジェクトID』などを取得する方法

    BacklogAPIを実行するためには、プロジェクトIDなどを取得する必要があります。
    例として以下の条件に該当する課題が検索で見つかった場合にslackで通知する想定で課題を検索してCSVを出力します。

    状態:『未対処』or『処理中』
    種別:『その他』
    キーワード:『サーバ設定変更依頼』



    CSVに各IDが含まれているので『プロジェクトID』『種別ID』『状態ID』を控えておき、コードに記述します。
    ※『状態ID』はデフォルトで[1:未対応/2:処理中/3:処理済み/4:完了]になっていると思われます。



    Lambda関数作成

    AWSコンソールでLambdaの画面を開き、『関数』→『関数の作成』と進みます。



    『一から作成』を選択し、以下の通り設定して『関数の作成』をクリックします。

  • 関数名:任意の名前をつけます
  • ランタイム:最新のサポート対象のPython3.xを選択
  • 実行ロール:特に用意がなければ『基本的な Lambda アクセス権限で新しいロールを作成』を指定



  • 作成後、レイヤーの設定を行います。

    レイヤー作成

    LambdaでPythonの外部ライブラリであるrequestsを使用するために、レイヤーを作成します。

    まずは、外部ライブラリのzipファイルを作成します。
    ※作業はpipがインストールされているマシンで実施してください。

    最初に任意のディレクトリに移動し、以下のコマンドを実行してください。

    # mkdir python
    ※ディレクトリ名はpythonとしてください。
    # pip install -t ./python requests
    # zip -r layer.zip ./python
    ※zipファイルは任意のファイル名で構いません。

    AWSコンソールのLambdaの画面より『レイヤーの作成』をクリックします。



    作成画面では以下の通り設定して『作成』をクリックします。

  • 名前:任意のレイヤー名
  • .zipファイルをアップロードにチェック
  • 『アップロード』よりzipファイルを選択してアップロード
  • 互換性のあるランタイム:Python3.xを全て選択



  • 関数の画面に戻り、



    『レイヤーの追加』をクリックします。
    遷移した画面で以下の通り設定して『追加』をクリックし、レイヤーを追加します。

  • レイヤーソース:カスタムレイヤー
  • カスタムレイヤー:先ほど作成したレイヤー名を選択
  • バージョン:レイヤー作成直後は1のみ選択可能



  • 次にLambdaでKMSキーを使用するための設定を行います。

    『設定』→『アクセス権限』→割り当てられたロールをクリックしてIAMロールの画面に進みます。



    『ポリシーをアタッチします』をクリックします。



    先ほど用意した、KMSで復号化するためのポリシーを選択し、『ポリシーのアタッチ』をクリックしてポリシーを付与します。





    ポリシーが追加されたことを確認し、Lambda関数の画面に戻ります。
    『設定』→『環境変数』→『編集』をクリックして進みます。



    以下の通り設定後、『暗号化』をクリックしてAPIキーを暗号化します。

  • キー:『apikey』と入力
  • 値:事前に取得したBacklogのAPIキーを入力
  • 転送時の暗号化:チェック入れる
  • 保管時に暗号化するAWS KMSキー:『カスタマーマスターキーの使用』にチェックし、事前に作成したKMSキーのARNを入力



  • 転送時の暗号化の画面では、KMSキーを指定し、『シークレットスニペットの復号』に表示されているコードを控えてから、『暗号化』をクリックします。



    ▼コード修正
    復号化の処理をコードに追加する。

    import requests
    import json
    import boto3
    import os
    from base64 import b64decode
    
    def lambda_handler(event, context):
        backlog_apikey = apikey
        backlog_api_url = '〓https://xxxxxxxx.backlog.jp〓/api/v2/issues'
    
        slack_url = "〓slackのwebhook URL〓"
        backlog_search_url = "〓Backlogの対象プロジェクトのURL〓"
    
        #---------------------------------------------------------------------------------
    
        # APIキー復号化    
        ENCRYPTED = os.environ['apikey']
        backlog_apikey = boto3.client('kms').decrypt(
            CiphertextBlob=b64decode(ENCRYPTED),
            EncryptionContext={'LambdaFunctionName': os.environ['AWS_LAMBDA_FUNCTION_NAME']}
        )['Plaintext'].decode('utf-8')
        
        
        #---------------------------------------------------------------------------------
        
    
        # 検索フィルタ
        payload_check = {
            'apiKey': backlog_apikey,
            'projectId[]': '〓プロジェクトID〓',
            'issueTypeId[]': '〓種別ID〓',
            'keyword': '〓サーバ設定変更依頼〓',
            'statusId[]': ['1', '2'] #(4:完了, 3:処理済み, 2:処理中, 1:未対応)
        }
    
        # チケット検索
        search_issues = requests.get(backlog_api_url, params=payload_check)
    
    
        # slack通知用の関数
        def slack_message(msg):
            requests.post(slack_url, data=json.dumps(msg))
    
    
        # slack通知内容
        ## 要確認
        info_msg = {
            "text":f"〓未対応の<{backlog_search_url}|サーバ設定変更依頼>があります。〓",
            "username":"〓Task Checker〓",
            "icon_emoji":"〓:warning:〓"
        }
    
    
        # チケットを検索し、該当するチケットが存在する場合は、slack通知
        try:
            get_issue = search_issues.json()[0]['issueKey']
            slack_message(info_msg)
    
        except IndexError:
            pass
    
    

    修正後、Lambdaのコードソースに貼り付けて、『Deploy』をクリックして適用する。



    最後に定期実行のための『EventBridge』の設定を行います。
    Lambda関数の画面で『+トリガーを追加』をクリックします。



    トリガーの設定画面で以下の通り設定して、『追加』をクリックする。

  • 使用するサービスは『EventBridge』を選択
  • ルール:『新規ルールの作成』を選択
  • ルール名:任意の名前を入力
  • ルールタイプ:スケジュール式
  • スケジュール式:cron(0 10 ? * MON-FRI *) ※平日10時の場合

  • cron式については公式ドキュメントを参照ください。
    https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html



    EventBridgeがトリガーに追加され、全ての設定が完了しました。



    動作確認

    コードソースの画面で『Test』をクリックします。



    『テストイベントの設定』画面で任意のイベント名を入力し、『作成』をクリックします。



    元の画面に戻り、再度『Test』をクリックしてコードがLambdaで動作することを確認します。



    『Status: Succeeded』が表示されればテストは成功です。



    slackにもメッセージが届いたことを確認できました。



    おわりに

    無事に動作させることができました。
    今回、Lambdaということもあり定期実行にはEventBridgeを活用していますが、サーバ上で実行する場合は、Linuxであればcron、Windowsであればタスクスケジューラで設定することになるかと思います。

    本記事ではタスクを通知するところまでの処理としていますが、タスクの内容次第では、それらの処理と課題クローズまでワンストップで自動化することも可能ですので、興味がある方はぜひ挑戦してみてください。

    最後に、当社はシステムの監視・運用代行サービスをご提供している会社です。もしご興味がございましたらお気軽にご相談ください。最後までお読みいただきありがとうございました。

    > Amazon Web Services (AWS) 運用監視 – 代行サービス 詳細はこちら