最近、不正アクセスや、設定ミスにより、情報漏洩のニュースを見る機会が多くなりました。 弊社でも機密情報を扱っており、どのようなニュースがあるのか日々注視しています。
そこで、 ScanNetSecurity が RSS で公開されている情報を日に1度 Slack 通知する Google Apps Script(GAS) を作成してみました。 公式に Slack に RSS フィードを追加する 方法がありますが、今回は AI で記事を要約したものを通知したかったので、自作することにしました。 (が、実装の時間が足りず AI 利用に関しては断念しました。)
ScanNetSecurity とは
ScanNetSecurity は、1998年に創刊された日本初の情報セキュリティ専門サイトで信頼性の高い情報源であることと、RSS が公開されていることから選びました。
方針
- GAS で 日に1度、通知する。
- Feed の日付から25時間以内の記事を通知する。 ( GAS では 日に1度、起動させる場合、1時間範囲内でしか選択できないので、24 + 1 時間 の記事を通知する。)
- メッセージは以下のようなイメージで通知する。
コード解説
1. スクリプト プロパティ に ScanNetSecurity の RSS の URL、Slack の Webhook URL を追加します。
2. 以下のコードで、RSS を XML としてパースします。 XML は RSS1.0 として取得できます。(RSS1.0 の資料はこちら)
const RSS_URL = PropertiesService.getScriptProperties().getProperty('RSS'); // スクリプト プロパティ に 設定した ScanNetSecurity の RSS URL const xml = UrlFetchApp.fetch(RSS_URL).getContentText(); const document = XmlService.parse(xml);
3. ScanNetSecurity 内の個々の記事のタイトル、リンク、日付は item に含まれます。XML から item 部分を取り出し、タイトル、リンク、日付を取り出します。
const RSS = XmlService.getNamespace('', 'http://purl.org/rss/1.0/'); // RSS1.0 const DC = XmlService.getNamespace('dc', 'http://purl.org/dc/elements/1.1/') // Dublin Core const root = document.getRootElement(); const items = root.getChildren('item', RSS); // item 部分を取り出し items.forEach(function(item) { // item は以下のようになっているのでそれに合わせてパースします。 // <item rdf:about="https://scan.netsecurity.ne.jp/article/2024/07/08/51264.html"> // <title>Proofpoint Blog 38回「生成 AI の影響で日本はビジネスメール詐欺が増加」</title> // <link>https://scan.netsecurity.ne.jp/article/2024/07/08/51264.html</link> // <dc:date>2024-07-07T23:10:03Z</dc:date> // </item> const title = item.getChildText('title', RSS); // タイトル const link = item.getChildText('link', RSS); // リンク const date = new Date(item.getChildText('date', DC)); // 日付 }
4. Slack に Webhook URL に POST し、メッセージを通知します。 attachments は、通知メッセージを装飾する際に利用します。 詳細は、こちら。
const WEB_HOOK_URL = PropertiesService.getScriptProperties().getProperty('WEB_HOOK_URL'); // attachments で Slack のメッセージを装飾が可能です。 // 今回は、以下のように装飾します。 const payload = { 'attachments': [ { 'title': 'ScanNetSecurity - RSS', // 通知するメッセージのタイトル 'title_link': 'https://scan.netsecurity.ne.jp/', // タイトルリンク 'text': 'hogehoge' // メッセージ本体 } ] }; const body = { 'method' : 'post', 'contentType' : 'application/json', 'payload' : JSON.stringify(payload) }; UrlFetchApp.fetch(WEB_HOOK_URL, body);
コード全体
const RSS_URL = PropertiesService.getScriptProperties().getProperty('RSS'); const WEB_HOOK_URL = PropertiesService.getScriptProperties().getProperty('WEB_HOOK_URL'); const RSS = XmlService.getNamespace('', 'http://purl.org/rss/1.0/'); const DC = XmlService.getNamespace('dc', 'http://purl.org/dc/elements/1.1/') const TODAY = new Date(); const RANGE_OF_TIME = 24 + 1; // 通知範囲:24 + 1 時間 const TARGET_DATE = new Date(TODAY - RANGE_OF_TIME * 60 * 60 * 1000); function myFunction() { const xml = UrlFetchApp.fetch(RSS_URL).getContentText(); const document = XmlService.parse(xml); const root = document.getRootElement(); const items = root.getChildren('item', RSS); let str = ''; // メッセージ構築用 items.forEach(function(item) { const title = item.getChildText('title', RSS); const link = item.getChildText('link', RSS); const date = new Date(item.getChildText('date', DC)); if(TARGET_DATE <= date){ const dateStr = Utilities.formatDate(date, 'JST', 'yyyy/MM/dd HH:mm'); str += `| ${dateStr} | <${link}|${title}>\n`; } }); if(0 < str.length) notifySlack(str); } function notifySlack(msg) { const payload = { 'attachments': [ { 'title': 'ScanNetSecurity - RSS', 'title_link': 'https://scan.netsecurity.ne.jp/', 'text': msg } ] }; const body = { 'method' : 'post', 'contentType' : 'application/json', 'payload' : JSON.stringify(payload) }; UrlFetchApp.fetch(WEB_HOOK_URL, body); }
終わりに
- RSS の 要素 dc:date を date型 として取り出すには、自分で 日付の書式を指定して変換する必要があるのか、決まった取り出し方があるのか分からず調査することにしました。
- 結果、Dublin Core を利用することで date型 として取り出せることが分かり、追加調査してよかったです。
- やはり、記事の要約を AI で作成して slack 通知できるようになると、記事に飛ばなくても内容確認でき、さらに便利になりそうなので、時間があればチャレンジしてみたいと思います。