【ComputeEngine】VMのport全開放なんて許さない！！【Firewall】

# はじめに
クラウドを使う上でVMのセキュリティには注意したいですよね。
特に不特定多数が利用するプロジェクトには監視ツールやセキュリティチェッカーを仕込んでおくのが良いかと思います。

自分にもそんな環境があり、みんなが少しでも安全に利用できるに何か仕組みを作れないかと思い、今回Firewallのチェッカーを作ってみました。ただ、お手製なのでもっとイケてる方法があったらコメントで教えてもらえると嬉しいです。

# 作ったもの
VMのセキュリティで一番気を付けたいのはポートフルオープン(Ex. port:22 IP範囲:0.0.0.0/0)だと思います。
なので、すべてのFirewallを取得し、FirewallルールのオープンしているIP範囲に0.0.0.0/0がないかどうかチェックをしています。


もちろん、ある程度の知識がある人はこんなことしないと思いますが、念には念をって感じです。

## アーキテクチャ
というほどの物でもないですが、簡単に図にしておきます。

![スクリーンショット 2020-01-25 0.56.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148317/093f2526-387e-f0d8-2ea7-d94f67c1a7dd.png)


# Firewallの取得
gcloudコマンドでFirewallの情報を取得します。

```python:fw_checker.py
import subprocess as sb

def get_fwlist():
  fwlist = []
  cmd = 'gcloud compute firewall-rules list'
  res = sb.check_output(cmd.split())

  for vpc_info in res.split('\n')[1:-1]:
    if vpc_info.split()[2] == 'INGRESS':
      cmd = 'gcloud compute firewall-rules describe ' + vpc_info.split()[0]
      des = sb.check_output(cmd.split()).split('\n')
      fw_name = [[name for name in des if 'name' in name] for content in des if '0.0.0.0' in content]
      if len(fw_name) > 0:
        fwlist.append(fw_name[0][0])
  return fwlist
```

何をやっているかというと、

```
$ gcloud compute firewall-rules list

NAME                    NETWORK              DIRECTION  PRIORITY  ALLOW                         DENY
dev-humi-fw             dev-hum-vpc          INGRESS    1000      tcp:22
```

Firewallの一覧を取得して、

```
$ gcloud compute firewall-rules describe dev-humi-fw

allowed:
- IPProtocol: tcp
  ports:
  - '22'
creationTimestamp: '2020-01-22T23:01:37.304-08:00'
description: "firewall"
direction: INGRESS
disabled: false
id: '789797940564670'
kind: compute#firewall
logConfig:
  enable: true
name: dev-humi-fw
network: https://www.googleapis.com/compute/v1/projects/project/global/networks/dev-hum-vpc
priority: 1000
selfLink: https://www.googleapis.com/compute/v1/projects/project/global/firewalls/dev-humi-fw
sourceRanges:
- 123.123.0.1
- 123.123.0.2
```

各Firewallの情報を取得しています。
この情報を処理して、sourceRagesの値を取得し、その中に0.0.0.0/0を含むかどうかを確認しています。
今回はINGRESSに対して設定してある情報を対象としています。

# 0.0.0.0/0の検知後のメール通知
上記で検知の仕組みができたので、次に検知した場合の通知の仕組みを作りました。
ただ、ComputeEngineではメール送信ができないようなのでStackdriverMonitoringを経由する方法にしました。
(全然いけてない方法なのですが・・・(笑))

概要が下記になります。
Firewallルールを調べて0.0.0.0/0を発見した場合にStackdriverMonitoringで検知できるアクションを起こします。
StackdriverMonitoringには設定した異常を検知した場合に特定のアドレスにメールを送る設定をしています。

![スクリーンショット 2020-01-28 18.29.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148317/6ab2b6cb-cffc-79cb-3b1a-75ddfb935245.png)


## StackdriverMonitoringの設定
MonitoringのComputeEngineで監視できるのはCPU使用率やディスクの読み書きのバイト数などです。
この中に指定のComputeEngineのネットワークの送信バイト数を監視できるメトリクスがあります。

このメトリクスを使用して、ある程度の域値を設定し、この値を超えたら通知を飛ばします。
(適当なファイルを用意して外のサーバーに転送することで域値を超えるようにしています。)

「StackdriverMonitoring」から「アラート」を選択、「CREATE POLICY」でポリシーを作成します。

![スクリーンショット 2020-01-28 23.51.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148317/a327943b-402a-5e4c-cab8-6de2776efb20.png)

今回は「Sent bytes」にしてVPC外に送信されたバイト数でポリシーを作成します。

![スクリーンショット 2020-01-28 23.52.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148317/f72f0eb8-c246-4a0a-08ae-ea72c0cb3682.png)

最後に「ADD NOTIFICATION CHANNEL」で通知をできるようにします。

## 通知チャンネルの設定
下記コマンドで通知チャンネルを作成します。

```:Terminal
$ gcloud alpha monitoring channels create --channel-content-from-file="email-channel.json" 
```

ここで指定しているjsonファイルの中身が下記になります。

```email-channel.json
{
  "type": "email",
  "displayName": "test e-mail channel",
  "description": "E-mail channel created by gcloud as a test",
  "labels": {
    "email_address": "user@example.com(通知したいメールアドレス)"
  },
  "enabled": true
}
```

これで通知チャンネルができたかと思います。
アラート設定画面の「ADD NOTIFICATION CHANNEL」で「Email」を選択して先ほど通知したいメールアドレスに記載したものをここで入力すると通知ができるようになります。

![スクリーンショット 2020-01-29 0.10.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148317/2c6c0706-1fb5-e1ea-f4a1-15caf802efab.png)

## 挙動確認
最後に簡単に挙動を確認してみます。
上記で書いたプログラムをcronで仕掛けます。(今回は5分間隔にしました。）

試しに適当なVPCにIP範囲を0.0.0.0/0で開放したFirewall ruleを作成します。(作成する際、ターゲットを「指定されたターゲットタグ」にしてVMに設定されていないタグを指定します。)

時間差は多少ありますが、Monitoringで検知すると下記のようになります。

![スクリーンショット 2020-01-30 1.18.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148317/9e57adf6-b4fe-0829-f51d-7a1dfd8e1d4b.png)

通知メールもちゃんときました！！

![スクリーンショット 2020-01-30 1.22.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148317/84d6b9d8-7683-0f4c-e9dc-f394d197968f.png)

ちゃんと動いたことを確認できたので以上とします。

# さいごに
クラウドは便利なだけにルールを徹底しないと痛い目に会うことが多々あると思います。
個人のルール厳守に任せるだけでなく、今回のようなプログラム的なものでもルール厳守の補助をすることが大事かなと思いました。

もっと良いセキュリティ監視がありましたらコメントお願いします。