[Heroku] Private Space Peering の設定手順 [AWS VPC]

[Heroku Private Space](https://www.heroku.com/private-spaces)では、AWSの[Virtual Private Cloud](https://aws.amazon.com/vpc/)とピアリング接続をして、相互に内部的に接続し安全な通信を行うことができます。この機能を[Private Space Peering](https://devcenter.heroku.com/articles/private-space-peering)と言います。

# [Private Space Peering](https://devcenter.heroku.com/articles/private-space-peering)してみよう

そんな[Private Space Peering](https://devcenter.heroku.com/articles/private-space-peering)の設定方法についてまとめたものです。リンク先に事細かに手順は書いてありますが

- 英語キツイ
- Herokuしか使ってないからawsコマンド入れてなかった
- awsコマンドでどうしてもうまくいかない

のような人たちに向けて、日本語のaws consoleでの設定手順をまとめました。

## 前提条件

1. heroku enterprise契約で、Private Spaceを購入していること
2. AWSアカウントがあること
3. heroku CLIが利用できること
4. Heroku側でSPACEがすでに作成されていること
5. AWS側でVPCがすでに作成されていること

１つ目の前提条件のハードルが一般的な利用では難しいのですが、それさえクリアしておけばカンタンに構成できます。

# 設定手順

次の4つの手順で設定します。

1. Heroku側でVPCの構成を確認する
2. AWS側でピアリングする
3. Heroku側で受け入れる
4. AWS側でルーティングテーブルを作成する

## 1. Heroku側でVPCの構成を確認する

まず、AWS側からピアリング設定を行うために、Heroku側の設定を確認します。GUIでもCUIでもカンタンです。

GUIのダッシュボードから確認する場合は、作成されているPrivate Spaceの`Network`タブを見るだけです。

<img width="998" alt="Screen Shot 2019-02-04 at 14.33.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/ec7580d5-f6d7-24de-278b-7f46741847fb.png">
※ 特にそこまで問題になると思いませんが、一応 `AWS Account`IDは隠してます。

CUIの場合は、`heroku spaces:peering:info ＜スペース名＞` を実行するだけです。次のような結果が帰ってきます。

```
AWS Account ID:    
AWS Region:        ap-northeast-1
AWS VPC ID:        vpc-b39527d4
AWS VPC CIDR:      10.0.0.0/16
Space CIDRs:       10.0.144.0/20, 10.0.128.0/20, 10.0.0.0/20, 10.0.16.0/20
Unavailable CIDRs: 10.1.0.0/16
```
※ ここでも`AWS Account ID`を消してます

### 注意事項

ここで、`AWS VPC CIDR`と`Unavailable CIDRs`のいずれかと、接続するAWS VPCのCIDRがかぶっていないことを確認しておきます。Private SpaceもVPCも作成後にCIDRの変更はできませんので、いずれも作成時にIPアドレスレンジがバッティングしないように構成しましょう。

なお、Heroku Private SpaceのCIDRを変更する際は[Choosing Private Network CIDR Range](https://devcenter.heroku.com/articles/private-spaces#choosing-private-network-cidr-range)をごらんくださいませ

## 2. AWS側でピアリングする

awsマネージメントコンソールを開いて、おもむろにVPCの項目へ移動しましょう。ここでは何も考えずに「ピアリング接続」を選択し、「ピア接続の作成」ボタンをクリックします。まちがえて「ぴあ」って変換されるとアレですね。

<img width="977" alt="Screen Shot 2019-02-04 at 14.41.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/66397584-d601-9dd7-0729-fc259eca5fff.png">

`ピア接続の作成`画面では、次のように設定します。

<img width="962" alt="Screen Shot 2019-02-04 at 14.46.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/17954455-29ff-0eff-c691-3aaa60617078.png">

- `ピア接続ネームタグ` どうぞ好きにしてください
- `ピア接続するローカルVPCを選択` 今回接続したいAWS側のVPCを選択します。プルダウンで出てくるはずです。
- `ピア接続するもう一つのVPCを選択`
    - `アカウント` まずまちがいなく別のアカウントになりますから、「別のアカウント」を選択します。`アカウントID` が手入力できますので、先程確認をした `AWS Account ID`をここに入れます。
    - `リージョン` Heroku Private Spaceのリージョンを選択します。先程確認した中の`AWS Region`にも記載があります。リージョンが異なる場合は`別のリージョン`にして、リージョンを選択します
    - `VPC(アクセプタ)*` 先程書くにした`AWS VPC ID`をここに入れます。

すべてを入れたら「ピア接続の作成」ボタンをクリックしましょう。設定上ミスがなければ、次の「成功」画面が出てくるでしょう。「OK」しといてください。

<img width="977" alt="Screen Shot 2019-02-04 at 14.46.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/ee1bfbc5-5af3-5e8a-7e0a-b317643445c0.png">

## 3. Heroku側で受け入れる

設定がうまく行っていれば、awsマネジメントコンソール上では、次のように「承認の保留中」となっているでしょう。Heroku側の`acceptance`を待っている状況です。

<img width="989" alt="Screen Shot 2019-02-04 at 14.48.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/83967803-e19e-602d-7b46-f30866da42f5.png">

heroku CLIで受け入れを行う前に、正しくHeroku側に承認要求が来ているかどうかを調べます。`heroku spaces:peerings ＜スペース名＞`を実行しましょう。

```
=== enablement-jp Peerings
PCX ID                 Type            CIDR Blocks    Status              VPC ID                 AWS Region  AWS Account ID  Expires
─────────────────────  ──────────────  ─────────────  ──────────────────  ─────────────────────  ──────────  ──────────────  ────────────────────
pcx-01f31cfb89521de9c  unknown         172.16.0.0/16  pending-acceptance  vpc-0cb1a66017eed9372  us-east-1                   2019-02-11T05:46:14Z
******                 heroku-managed  10.1.0.0/16    active              ******                 ******      ******
```

このように、「Status」が`pending-acceptance`となっているものがあれば、正しく承認要求が来ています。ここでの「PCX ID」を元に受け入れを行います。`heroku spaces:peerings:accept pcx-01f31cfb89521de9c --space ＜スペース名＞`を実行します。`スペース名`の前に`--space`が必要なことに気をつけましょう。
うまく行けば次の結果が帰ってきます。

```
Accepting and configuring peering connection pcx-01f31cfb89521de9c
```

設定されたかどうか、もう一度`heroku spaces:peerings ＜スペース名＞`を実行して確認してみましょう。

```
=== enablement-jp Peerings
PCX ID                 Type              CIDR Blocks    Status   VPC ID                 AWS Region  AWS Account ID  Expires
─────────────────────  ────────────────  ─────────────  ───────  ─────────────────────  ──────────  ──────────────  ───────
pcx-01f31cfb89521de9c  customer-managed  172.16.0.0/16  active   vpc-0cb1a66017eed9372  us-east-1   435886841536
******                 heroku-managed    10.1.0.0/16    active   ******                 ******      ******
```

設定されてそうですね。これは、GUIのダッシュボーでも確認できます、先程設定を確認したダッシュボードをリロードしてみましょう。

<img width="1224" alt="Screen Shot 2019-02-04 at 14.50.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/13d80e4d-b86e-163e-404d-272a8f380e25.png">

ね。

## 4. AWS側でルーティングテーブルを作成する

heroku側では受け入れたVPCのCIDRにあわせて静的経路が作成されますが、AWS側では準備しておいて上げる必要があります。

<img width="1107" alt="Screen Shot 2019-02-04 at 15.07.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/23eee42c-681f-0a0b-eea5-5f2d08518e4f.png">

VPCダッシュボードの「ルートテーブル」をクリックして、対象となるAWS VPCのルートテーブルを選択します。したらば、下の方にある「Routes」タブをクリックします。

<img width="901" alt="Screen Shot 2019-02-04 at 15.16.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/c2b0902f-90f3-b5c8-f729-1ba5a880f9d9.png">

「Edit routes」ボタンがありますから、それをクリックして静的経路を使いしましょう。

新たに経路を追加しますので、「Add route」で新しく行を追加します。

<img width="868" alt="Screen Shot 2019-02-04 at 15.14.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/37263/6a188172-250c-adcd-0b97-a6cc129482e5.png">

新しい行で、次の２つを設定しましょう。

- `Destination` 最初に内容を確認した`AWS VPC CIDR`を設定します。
- `Target` 「Peering Connection」を指定すると、対象のIDのものが出てきますから、それを指定します。

あとは「Save routes」ボタンをクリックするだけです。

# 設定完了

Heroku→AWS VPCへ接続する場合には、Security Groupの「Inbound Rules」にソースIPアドレスレンジとターゲットへのポート番号を開けて上げる必要があります。

AWS VPC→Herokuへは、[Internal Routing](https://devcenter.heroku.com/articles/internal-routing)設定されたWeb Dynoへしかアクセスができません。くわしくは[heroku 上級編 - Private Space でできること -](https://qiita.com/sho7650/items/10904c9be7ab20e82513#6-internal-routing)にも記述していますので、こちらもご参考になさってください。

試しに、VPC内のEC2からInternal RoutingされたHeroku Web Dynoへアクセスしてみると、こんな感じで疎通できていることが確認できます。

```
[ec2-user@ip-172-16-0-8 ~]$ hostname
ip-172-16-0-8.ec2.internal

[ec2-user@ip-172-16-0-8 ~]$ curl -s -D - -o /dev/null test-vpn-compute.herokuapp.com
HTTP/1.1 200 OK
Cache-Control: no-cache, private
Content-Type: text/html; charset=UTF-8
Date: Mon, 04 Feb 2019 06:25:31 GMT
Server: Apache
Via: 1.1 spaces-router (3e6fc26c45df)
Transfer-Encoding: chunked

[ec2-user@ip-172-16-0-8 ~]$ dig test-vpn-compute.herokuapp.com

; <<>> DiG 9.9.4-RedHat-9.9.4-61.amzn2.1.1 <<>> test-vpn-compute.herokuapp.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14933
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;test-vpn-compute.herokuapp.com.        IN      A

;; ANSWER SECTION:
test-vpn-compute.herokuapp.com. 60 IN   A       10.0.25.212
test-vpn-compute.herokuapp.com. 60 IN   A       10.0.15.133

;; Query time: 30 msec
;; SERVER: 172.16.0.2#53(172.16.0.2)
;; WHEN: Mon Feb 04 06:27:25 UTC 2019
;; MSG SIZE  rcvd: 91
```