APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

GitHub Advanced SecurityのAlertを、Azure Functions経由でいい感じにSlackに飛ばす

はじめに

ACS事業部でEngineering Managerもとい中間管理職をしている谷合です。
Managerになってからというものの、めっきり手を動かす機会が減り、その過程でのエンジニアとしてのワクワクを感じなくなってきたなと思う今日この頃。
中間管理職だってワクワクしたい!!!というピュアピュアな想いで本ブログを書いてみました。

弊社はGitHub社とMicrosoft社のパートナー企業として日夜皆様の内製化をご支援しています。
そこで、案件を通してGitHub Advanced Securityの導入に際し、Code ScanningやSecret ScanningのAlertをどこに飛ばす?といった議論や技術検証を行っていたりします。
Payloadのフォーマットにクセがあり、Alert飛ばす設定は大変だったりしますので、GitHub Advanced Securityの導入後の一山になるかなと思っています。

今回はそんなAlertをAzure Functions経由でSlackに飛ばしてみようと思います。

なぜAzure Functions経由?

GitHubから外部にAlertを通知する場合、E-MailやWebhookを使うことを検討するかと思います。
E-Mailはデフォルトで飛ぶのですが、如何せんOrganizationやRepositoryなどの管理者にしか通知が飛びません。
ですが、GitHub Advanced SecurityのCode ScanningやSecret ScanningのAlertは、もっといろんな人に通知してほしい場合もありますよね。
できれば、チャットでリアルタイムに。

このようなシチュエーションでは、Webhookを使います。
Webhookは、OrganizationやRepositoryのSettingsで設定します。

そんなWebhookですが、Payloadのフォーマットが、単なるKey-ValueなJsonなんですよね...
Slackに飛ばす場合、Textフィールドなどを含める必要がありますが、含まれていないため、GitHubから直接Slackに飛ばす場合、missing_text_or_fallback_or_attachments のエラーが発生してしまいます。
使いづらい...

そこで、Azure Functionsなんですよ!
Azure Functionsを経由させて、フォーマット整形しちゃいましょう。ついでに通知をシンプルに見やすくしちゃいます。 なお、AWSではAWS Lambda、Google CloudではCloud Functionsあたりでも代用できるかと思います。

いざ実装

SlackにIncommig Webhookをインストール

Slackでは、Alertを最終的に受け取るIncommig Webhookをインストールします。
MarketpalceにIncommig Webhookがあるので、これを利用するといいでしょう。 インストールに、Webhook URLが表示されるので、どこかに控えておきましょう。

Azure Functionsの実装

GitHubからのWebhookを受信、Payloadのフォーマット整形、SlackへのAlert通知をAzure Functionsで実施します。
Azure Functions自体は特別な設定はしませんが、以下の前提の元、実装します。

  • ランタイムスタックはNode.js
  • トリガーはHTTP

コードは以下の通りです。
コードのコメント通りですが、GitHubからのWebhook Payloadを取得し、bodyの内容でCode ScanningとSecret ScanningのAlertを判断しています。
今回の場合は、必要最低限のメッセージにしましたが、これだけあれば十分Alertとしては機能するでしょう。
GitHubからAzure FunctionsのURLに向かってPOSTメソッドのリクエストが発報されたら、関数がトリガーされるようになっています。

注意点としてaxiosパッケージを利用してSlackにAlertを飛ばすので、package.jsにもaxiosを追加してください。
また、SlackのIncommig WebhookのURLを、Azure Functionsの環境変数SLACK_WEBHOOK_URLとして設定しておいてください。

const axios = require('axios');
const { app } = require('@azure/functions');

app.http('ghasHttpTrigger', {
    methods: ['POST'],
    //authLevel: 'function',
    handler: async (req, context) => {
        context.log('GitHub alert received.');

        // GitHubからのリクエストボディを取得
        const github = await req.json();

        // code-scannigとsecret-scanningのアラートを判別
        const result = github.alert.hasOwnProperty('rule');
        let message = null;
        if (result) {
            message = `Code vulnerability detected!
repository name: ${github.repository.name}
description: ${github.alert.rule.description}
alert url: ${github.alert.html_url}`;
        } else {
            message = `Secret detected!
repository name: ${github.repository.name}
secret type: ${github.alert.secret_type}
alert url: ${github.alert.html_url}`;
        }

        // Slackにメッセージを送信
        const slackWebhookUrl = process.env.SLACK_WEBHOOK_URL; // 環境変数からWebhook URLを取得
        const payload = { text: message };

        context.log('Sending to Slack:', payload);

        try {
            await axios.post(slackWebhookUrl, payload);
            context.log('Alert processed successfully');
            context.res = {
                body: "Alert processed successfully"
            };
            return context.res;
        } catch (error) {
            context.log.error('Failed to send alert to Slack:', error);
            context.res = {
                body: "Failed to send alert to Slack"
            };
            return context.res;
        }
    }
});

GitHub Webhookの実装

最後はGitHub Webhookの実装です。
詳細なWebhook設定方法は以下を参照ください。

docs.github.com

WebhookはOrganizationやRepositoryのSettingsで設定可能です。

Webhookの飛ばし先やトリガーを設定することで、実に簡単に使用することができます。
今回はAzure FunctionsのURLを飛ばし先に設定しておきましょう。

トリガーは、以下のものがあり、GitHub Advanced SecurityのCode ScanningやSecret ScanningのAlertでは、Let me select individual events.を選択します。

  • Just the push event.
  • Send me everything.
  • Let me select individual events.

Let me select individual eventsでは、BranchやTagの作成/削除や、Pushなど細かいイベントをトリガーにすることができます。
GitHub Advanced Securityでは以下のトリガーを選ぶことになるでしょう。

  • code_scanning_alert
  • secret_scanning_alert
  • secret_scanning_alert_location

他のトリガーの種類は以下を参照ください。

docs.github.com

secret_scanning_alert_locationは、検出されたSecretの場所をAlertとしてあげてくれます。
ただ、AlertのページにもSecretの場所は記載されているので、個人的にsecret_scanning_alertで十分と思っていますので、今回はsecret_scanning_alert以外をトリガーにします。

Alertを飛ばしてみよう

GitHubで、脆弱性のあるコードをPushしたり、コードにSecretを含ませることでAlertが発報されます。
すると、Slackに以下のように通知が飛ぶようになります。
何が発生したかや、AlertのURLが見れて最高ですね。
しいて言うならメンション先を設定してもいいかもしれません。

最後に

いかがでしたでしょうか?
GitHub Advanced SecurityのAlertは非常に大切であり、発見を1秒でも早くしたいですよね。
そんな時のチャットへのAlert発報です。簡単に実装できるので、是非皆さんもチャレンジしてみてください!

そして、私は久々に手を動かしてみて、やはりエンジニアリングは楽しいなと原点回帰した気分になりました。

PR

私達 ACS 事業部は Azure・GitHub などのクラウドネイティブ技術を活用した内製化のご支援をしております。 www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
我々の事業部のCultureDeckはコチラ。

www.ap-com.co.jp 今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。 www.ap-com.co.jp

本記事の投稿者: 谷合純也
AKS/ACA、GitHubをメインにインフラ系のご支援を担当しています。
junya0530さんの記事一覧 | Zenn