GASを使ってALBのIPアドレス変更を検知しSlackへ通知する

世の中の数多くのサービスがAWSやAzure,GCPなどのクラウドにホストされることが普通になり,オンプレの時に比べてサーバや各種リソースのIPアドレスが動的に変わることが増えてきた.そんななか,業務でどうしてもクラウドで動作中のリソースに紐づいているIPアドレスの変更を検知して通知する仕組みが必要だったので,今日はその方法を紹介しようと思う.

前提

今回はAWSのロードバランサの1つであるApplication Load Balancer(以降ALB)を検知対象とする.ALBを立てると多くの場合,1つのDNS名に対して複数のIPアドレスを持つ状態となる,ここでは2つIPアドレスを持つ場合を考える.

やりたいこと

ALBが持つ2つのIPアドレスのうち,片方を事前に記録しておく.ALBのIPアドレスの変更により,その記録したIPアドレスがALBのIPアドレスと異なる状態になったとき通知を行う.

検知と通知方法

スプレッドシートGoogle Apps Script(以降GAS)を使い,Slackへ通知する方法で実現する. まずはシートに初期値として現状のALBのIPアドレスをメモしておく.また検知した日新しいIPアドレスを記録するように列を用意しておく.

f:id:a-mochan:20191128234922p:plain
ALBの初期IPアドレスをメモ

GASで実装する内容は主に以下の2つ.

  1. DNS over HTTPSを使ってクラウド上のALBのIPアドレスを取得
  2. もし今記録しているIPアドレスと違ったら変更履歴をシートに記録しSlackへ通知

まずはDNS over HTTPSを使って名前解決する.DNS over HTTPSとは,文字通りHTTPSを用いてDNSの通信を行う技術である.今回はGoogleが提供してくれているGoogle Public DNS over HTTPSという全世界の人が無料で使えるフルリゾルバを使用する.どんなものかというのは,以下のURLを叩くと雰囲気がわかると思う.

https://dns.google.com/resolve?type=A&name=example.com

次に,Slack通知を行う部分を書く.以下のブログが参考になった.

qiita.com

Incoming WebhookをSlackのチャンネルに設定して,hookするURLさえ分かれば通知できる.完成版のGASは以下のようになる.

function resolveName() {
  var ss = SpreadsheetApp.getActiveSheet();
  var apiUrl = 'https://dns.google.com/resolve'; // Google Pubic DNS API URL
  var type = 'A'; // Aレコードを指定
  var name = 'hogehoge.com'; // 検知するドメイン名

  // 名前解決
  var requestUrl = apiUrl + '?name=' + name + '&type=' + type;
  var response = UrlFetchApp.fetch(requestUrl);
  var responseText = response.getContentText();
  
  // レスポンスをパース
  var json = JSON.parse(responseText);
  var newIpList = json.Answer.map(function(ans) {
      return ans.data
    });
  
  // 登録IPアドレス取得
  var oldIp = ss.getRange(2,1).getValue();

  // IPが変更したか確認
  if (newIpList.indexOf(oldIp) !== -1) {
    return;
  }
  
  // 文字列としてパース
  newIpList.sort();
  var ipAddr = newIpList.join('\n');

  // 変更日時とIPアドレスを記録
  var date = new Date();
  Utilities.formatDate( date, 'Asia/Tokyo', 'yyyyMMdd: hhmm');
  var lastRow = ss.getLastRow();
  ss.getRange(lastRow + 1, 3).setValue(date);
  ss.getRange(lastRow + 1, 4).setValue(ipAddr);

  // Slackへ通知
  notifySlack(name,ipAddr);
}

function notifySlack(name,ip_addr) {
  var postUrl = 'https://hooks.slack.com/services/hoge/fuga/moge';
  var username = 'IP報告する男';
  var message = name + 'のIPアドレスが変わりました\n' + ip_addr;

  var jsonData =
  {
     "username" : username,
     "text" : message
  };
  var payload = JSON.stringify(jsonData);

  var options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : payload
  };

  UrlFetchApp.fetch(postUrl, options);
}

テストとしてGAS上のタブから「実行」を選んでresolveName関数を実行する.IPアドレスが変わっていればスプレッドシート検知した日新しいIPアドレスが記録され,Slackへ通知が届く.

f:id:a-mochan:20191128234446p:plain
変更履歴が追加されたシート

f:id:a-mochan:20191128233942p:plain
Slack通知画面

あとは,GAS上のタブから「編集」->「現在のプロジェクトのトリガー」をクリックし,このスクリプトを時間ベースで定期実行するようにしておけば,IPアドレスが変わったタイミングでSlackに通知が届く.Slackに気づいたら,シートの初期値として設定したIPアドレス通知された新しいIPアドレスに手動で書き換える運用をしている.もちろんGASで自動的に書き換えてもらってもよい.

f:id:a-mochan:20191129100746p:plain
定期実行設定画面

まとめ

  • GASを使ってALBのIPアドレス変更を検知してSlackへ通知した
  • GASからSlack通知も便利だが,Google Public DNS over HTTPSも便利だった
  • 今回の対象はALBだったが,他の対象にも使えそうな手段だと思う