Connecting to a Private Heroku Postgres Database from an Amazon VPCの記事を書こうと思ったんですが、DevCenter の記事がやっぱりよくできているので、ざっくり翻訳してみました。そのほうが便利。なんか英語部分で違和感を感じる部分を、わいの感覚で修正していますが、まちがってはないはずです。
AWS PrivateLinkを使って、AWS VPCとPrivate Space内で動作する Heroku Postgres データベースを安全に接続する方法について紹介します。主に次の3つのステップでできちゃいます。
- Private Space 内の Heroku Postgresに Endpointを作成
- AWS VPC側に Endpoint Network Interfaceを作成
- それぞれのEndpointの接続
接続の設定で、許可されているアカウントのリストを指定して、VPCからPostgresへのアクセスを制御できます。
この機能を利用するには、接続先のHeroku Postgresと同じリージョンのサブネットで Amazon VPC Endpointを作成できなければなりません
Heroku 前提条件
PrivateLinkのEndpointを作成するためには、次の前提条件を満たす必要があります
- Private Spaceが必要 - Heroku ダッシュボードかCLIで、Private Spaceを作れること
- Private Space 内で動作する Heroku Postgresを利用するHerokuアプリがあること - privateプランのHeroku Dynoが対象の Private Space内で動かせること
Heroku側にEndpointを作成する
1. PrivateLink CLIプラグインを導入する
heroku plugins:install pg-privatelink
2. AWSのAccount ID情報を取得する
次のAWS CLIコマンドでAccount ID情報を取得できます。
aws sts get-caller-identity --output text --query 'Account'
123456789101
'123456789101'というAccount IDはサンプルです
AWSのダッシュボードからでも、Account Settings
からAccount IDを取得することができます。
3. PrivateLink endpointを作成する
PrivateLink endpointを作成するには、次のコマンドを実行します(置き換える値については気をつけること)。
heroku pg:privatelink:create POSTGRESQL_ADDON_NAME --aws-account-id ACCOUNT_ID --app APP_NAME
-
POSTGRESQL_ADDON_NAME
は、今回接続先となる Heroku Postgresのデータベース名です(例えばpostgresql-sushi-12345
みたいな)。 -
APP_NAME
は、対象のHerokuアプリ名です。 -
ACCOUNT_ID
は、先程確認したAWS Account IDです。このIDは次のいずれかのパターンにマッチしたものです。 - account-id
- account-id:user/username
- account-id:role/rolename
--aws-account-id
フラグを複数指定することで、複数のアカウントの指定が可能です
出力結果は、次のようなものになります
heroku pg:privatelink:create postgresql-sushi-12345 --aws-account-id 123456789101:user/abc.xyz --app privatelink-vpc-endpoint-demo
Creating privatelink... done
Service Name: Provisioning
Status: Provisioning
The privatelink is now being provisioned for postgresql-sushi-12345.
Run heroku pg:privatelink:wait -a APP to check the creation process.
だいたい 5分から10分でPrivateLink endpointが利用可能になります。Provisionの状況は
heroku pg:privatelink:wait --app APP_NAME
でわかります。
4. endpoint のサービス名を取得する
PrivateLinkのendpointが利用可能になったら、次のコマンドで詳細を確認できます。
heroku pg:privatelink POSTGRESQL_ADDON_NAME --app APP_NAME
POSTGRESQL_ADDON_NAME
は該当のPrivate Space内の Heroku Postgres名へ、APP_NAME
は該当のHerokuアプリ名へ置き換えてください
実行すると、次のような結果が帰ってきます
heroku pg:privatelink postgresql-sushi-12345 --app privatelink-vpc-endpoint-demo
=== privatelinks for postgresql-sushi-12345
Service Name: com.amazonaws.vpce.us-east-1.vpce-svc-0410a2e25933fe8ec
Status: Operational
=== Whitelisted Accounts
ARN Status
arn:aws:iam::123456789101:user/abc.xyz Active
Your privatelink is now operational.
You must now copy the Service Name and follow the rest of the steps listed in https://devcenter.heroku.com/articles/heroku-postgres-via-privatelink.
Service Name
項目の内容(ここでは com.amazonaws.vpce.us-east-1.vpce-svc-0410a2e25933fe8ec
となっている部分)をコピーしておいてください。Amazon VPC endpointを作成するときに必要になります。
Amazon VPC endpointを作成する
次に、Amazon VPCダッシュボードで以下の手順を実行していきます。
1. セキュリティグループの設定
endpointには、適切なセキュリティルールを持つセキュリティグループが必要になりますので、Amazon VPCダッシュボードの[Security Groups]タブで[Create security group]をクリックしましょう。
ここで、適切な(テキトーな)セキュリティグループ名と詳細を入力して、[Create]ボタンをクリックします
次に、できあがったセキュリティグループを選択して、[Actions]から[Edit inbound rules]を実行します
接続元のIPアドレス(CIDR)を入力して、Port Range
内に5432-5433
と指定したら[Save rules]をクリックします。
2. endpointを作成する
VPCダッシュボードから[Endpoints]タブを選択して、[Create Endpoint]をクリックします。
Create Endpoint
画面になったら、Find service by name
を選択して、 Service Name
項目へ、先程確認(コピー)した Service Name
を入力(ペースト)します。
次に、Verify
ボタンをクリックして、利用可能なサブネットリストを確認します。
[Security group]で、先ほど作成したセキュリティグループを指定して、[Create endpoint]ボタンをクリックします。
endpointの作成して Available
になるまで、だいたい5分から10分程度かかります。
Amazon VPC endpointからHerokuへ接続する
Amazon VPC endpointが利用可能(Available)になったら、VPCがPrivate Space内のHeroku Postgresへ接続するためのURLを取得できるようになります。
まず、PrivateLink endpoint から、後半の17桁のEndpoint ID
を取得します。また、このIDは大文字にして利用します。
もしEndpoint ID
がvpce-01c87ae3c05563935
だったときは、01C87AE3C05563935
というようになります。
次のコマンドを実行して、必要なIDを取得します。
heroku config --app your_app_name | grep ENDPOINT_ID_HERE
このコマンドを実行することによって、接続先のHeroku Postgresへ接続するためのAWS VPC Endpoint URLが、次のフォーマット形式で表示されます。
postgres://user:password@vpc-endpoint-dns-name:5432/database
このURLを使用して、AWS VPC内のアプリケーションからPrivate Heroku Postgresへ接続できます。コマンドの実行例は次の通り。
訳者補足:
privatelink-vpc-endpoint-demo
がHerokuアプリ名、01C87AE3C05563935
が先程取得した Endpoint IDの後半17桁を大文字に変換したもの、です。
heroku config --app privatelink-vpc-endpoint-demo | grep 01C87AE3C05563935
DATABASE_ENDPOINT_01C87AE3C05563935_URL: postgres://abcdefghijklmn:abcdefghijklmnopqrstuvwxyz123456789101112131415161718192021222324@ec2-3-83-63-168.compute-1.amazonaws.com:5432/dd0k757ojc5qt
この機能を利用する場合に懸念事項があれば、サポートチケットを上げてください
VPC endpointでEC2からHeroku Postgresへ接続する
VPC endpointが設定できたら、Heroku Postgresへ接続するためのEC2インスタンスを作成しましょう。
EC2ダッシュボード内のLaunch Instance
をクリックして、AMIとインスタンスタイプを選択します。ここでは、Ubuntu t2.micro
インスタンスを指定しています。
インスタンスの詳細を設定するときに、VPCネットワークでは、先ほど作成したセキュリティグループを指定します。まちがいないことを確認できたら、Review and Launch
をクリックしてEC2インスタンスを起動します。
インスタンスのステータスがrunning
になったら、インスタンス作成時に指定したSSHキーペアを使ってインスタンスへssh接続してみましょう。
最初の段階で、postgresクライアントコマンドを次のようにインストールして設定します。
sudo apt-get -qq update && sudo apt-get install -y curl ca-certificates
curl -s https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
sudo apt-get -qq update
sudo apt-get install -y postgresql-client-10
EC2インスタンスから、Heroku Postgresへ接続するには、次のコマンドを実行します。
psql postgres://user:password@vpc-endpoint-dns-name:5432/database
正常に接続できると、次の画面のようになります。
制限事項
- 作成するAmazon VPC endpointは、Heroku Postgresデータベースと同一リージョンにあるsubnetへ作成しなければなりません
- 共通するAmazon VPCとHeroku Postgres VPCのAZ内に存在する Private Space Heroku Postgresへ接続できます
- Heroku Postgresへ安全にアクセスできるように、VPCのセキュリティを担保するのは、お客さまの役割となります
Private Space trusted IP ranges
との違い
Private Spaces では、trusted IP ranges for data services
をβサービスとしてサポートしています。この機能は、Private Space外からHeroku Postgresへ接続する場合のオプションです。しかし、この機能を利用するにはHerokuチームへ依頼することが必要で、細かいアクセス制御を実施することができません。
AWS PrivateLinkで接続することによって、Heroku PostgresはVPCの一部として扱われ、ユーザー・ロールによるアクセス制御を実施できます。PrivateLinkにより接続できる場合には、この方式での接続を推奨します。
怪しい意訳があったら、とっととご連絡を。