エンジニア

2016.10.18

セキュリティーグループが変更されたらSlackに通知する

10月からハンズラボにJoinしました鹿倉です!
ただいま、AWSをシコシコ触っているところです!
今日はタイトル通りセキュリティーグループが追加されたり変更されたりした時に
Slackに通知するっていうのをやってみました。
流れは以下の図の通りです。
aws-design-11
 

  1. 1.CloudTrailとCloudWatchを連携する
  2. 2.ログを受け取ってSlackに通知するLambdaを作成する
  3. 3.サブスクリプションを使用してLambdaにログデータを流す


それでは実際にやってみます。
1.CloudTrailとCloudWatchを連携する
まずは、CloudTrailからCloudWatchへ配信するようにします。
1.コンソールTOPから「CloudTrail -> 証跡情報」をクリックします。
2.任意の証跡情報を選択します。
3.[CloudWatch Logs]の「設定」ボタンをクリックします。
4.新規または既存のロググループを入力して「次へ」ボタンをクリックします。(デフォルトでCloudTrail/DefaultLogGroupと入っているはずなので今回はそのまま)
5.CloudWatchにログ送っちゃうぞーって言われますのでそのまま「許可」ボタンをクリック
これでCloudWatchにCloudTrailのログが配信されているはずです。
実際に確認してみます。
コンソールTOPから「CloudWatch -> ログ -> CloudTrail/DefaultLogGroup」をクリックします。
お、なんかログが来ています!
cloudwatch-management-console
では次はLambdaを作成してみます。
2.ログを受け取ってSlackに通知するLambdaを作成する
今回はLambdaのruntime(言語)にはNode.jsを選びました。
Lambdaは実行するプログラムをコンソール上で書くか、実行ファイル群をzipにしてアップロードする必要があります。
外部ライブラリなどを使っている場合は後者で行う必要がありますが、
また毎度手動でデプロイするのも面倒なので今回はgulpを使ってデプロイするようにしました。
まずはプロジェクト作成。

mkdir sample-project
cd sample-project
npm init

package.jsonは下記のようにしました。

{
  "name": "lambda sample",
  "version": "1.0.0",
  "description": "lambda sample",
  "repository": "https'//xxx.xx.xx",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "awsLambda"
  ],
  "author": "shuta kakura",
  "license": "ISC",
  "devDependencies": {
    "aws-sdk": "^2.6.8",
    "del": "^2.2.2",
    "gulp": "^3.9.1",
    "gulp-install": "^0.6.0",
    "gulp-zip": "^3.2.0",
    "node-aws-lambda": "^0.1.8",
    "run-sequence": "^1.2.2"
  },
  "dependencies": {
    "async": "^2.1.1",
    "slackbots": "kakura/slack-bot-api"
  }
}

これでライブラリをインストール。

npm install

次にgulpでデプロイできるようにgulpfile.jsとlambda-config.jsを作成が必要ですが
その辺はQiitaDevelopers.IOなどでも情報はたくさんあるのでここでは省きます。
次にLambdaが呼び出すプログラム(index.js)を作成します。

const async = require('async');
const zlib = require('zlib');
const SlackBot = require('slackbots');
const bot = new SlackBot({
    token: <Slackのアクセストークン>,
    name: <SlackのBot名>,
},false);
exports.handler = function(event, context, callback) {
  var payload = new Buffer(event.awslogs.data, 'base64');
  zlib.gunzip(payload, function(e, result) {
    if (e) {
      callback(e);
      return false;
    }
    result = JSON.parse(result.toString('ascii'));
    async.map(result.logEvents, function(data, callback){
      noitify2slack(data,callback);
    },function(err, results){
      console.log(results);
      callback(null, 'success');
    });
  });
}
const noitify2slack = function(data, parent_callback){
  var log = JSON.parse(data.message);
  var message = null;
  if (log.eventName == 'AuthorizeSecurityGroupIngress' ||
      log.eventName == 'RevokeSecurityGroupIngress')
     message = 'セキュリティーグループが変更されました。'
  }else if(log.eventName == 'CreateSecurityGroup'){
     message = 'セキュリティーグループが追加されました。'
  }else if(log.eventName == 'DeleteSecurityGroup') {
     message = 'セキュリティーグループが削除されました。'
  }
  async.waterfall([
    function(callback){
      if (message != null) {
        bot.postMessageToChannel(<Slackの通知するチャンネル>),
           message,
           {icon_emoji: <Slack 絵文字アイコンコード>},
           function(data){
             callback(null,data.ok);
           }
         );
      }
    }
  ], function(err,result){
    if(result){
      parent_callback(null, result);
    }else{
      parent_callback(null, false);
    }
  }
  );
}

最後にデプロイ

./node_modules/.bin/gulp deploy

これで、コンソールから新しいFunctionが作成されていることが確認できると思います。
3.サブスクリプションを使用してLambdaにログデータを流す
最後に先ほど作成したLambdaにCloudWatchからログを配信してみましょう。
1.コンソールTOPから「CloudWatch -> ログ -> CloudTrail/DefaultLogGroupのチェックボックス」をクリックします。
2.「アクション -> Lambdaサービスへのストリーミングの開始」をクリックします。
3.先ほど作ったLambda関数を選択して「次へ」ボタンをクリック。
4.ログの形式でAWS CloudTrailを選択します。
5.すると「サブスクリプションフィルタのパターン」という入力ボックス出てくると思います。こちらには下記のように入力します。

{ ($.eventName = "CreateSecurityGroup") || ($.eventName = "DeleteSecurityGroup") || ($.eventName = "AuthorizeSecurityGroupIngress") || ($.eventName = "RevokeSecurityGroupIngress")}

これはCloudTrailのログはすごい量になるのであくまでセキュリティーグループの変更操作のログだけを抽出してLambdaで流すようにするためのフィルタになります。
6.最後に「ストリーミングの開始」ボタンをクリック。
あとは試しにセキュリティーグループを追加してみて、しばらく(CloudTrailの保存間隔は5分)待ってみると・・・あ!
来た〜。
times_kakura-hands-lab-slack
 
まとめ
今回Lambdaを作るのに毎回デプロイしてアップロードして確認するのめんどくさいなーと思っていたらlambda-localというライブラリがあって大変助かりました。
今後、もっとお勉強してハンズラボならではのAWSハウツーブログを書いていこうと思いますのでよろしくお願いいたします!
 

一覧に戻る