VPC内にElasticsearchを置く時の注意点

VPC内のプライベートサブネットにElasticsearchを置いたはいいけど、LambdaからAPI叩けないしKibanaもアクセスできなくて困ったときのメモです。

解決策

  • BastionServerとして同VPC内にEC2(パブリックサブネット)を置く

   - EC2にSSH接続してダイナミックフォワードを行う(ダイナミックフォワードあまりわかっていない...)

  • Lambdaを同じVPC内に置く

   - 仕様によってプライベートかパブリックかを選択する

  • それぞれのリソースに適切なセキュリティグループ(後述)を設定する

セキュリティグループ設定

EC2

Lambda

  • 今回はインバウンドの設定は不要(仕様による)

Elasticsearch

ハマりポイント

ElasticsearchのアクセスコントロールでEC2のプライベートIPを許可しようとしたが以下のエラーが出ました。

UpdateElasticsearchDomainConfig: {"message":"You can’t attach an IP-based policy to a domain that has a VPC endpoint. Instead, use a security group to control IP-based access."}

解決策が見つからず2時間くらいはまりましたが、ちゃんと公式に書いてありました。

VPCs ではセキュリティグループを通じてドメインへのアクセスを管理できます。多くのユースケースでは、このセキュリティ機能の組み合わせで十分となり、ドメインにオープンなアクセスポリシーを安心して適用できます。

Amazon Elasticsearch Service ドメインの VPC サポート - Amazon Elasticsearch Service

どうやらセキュリティグループでの制限で十分のようです。

つまりVPC内にElasticsearchを置くケースだとオープンアクセスを選択しておいて、アタッチしているセキュリティグループのみでアクセスの制限を行う形になります。

追記(2021/1/16)

CDKでElasticsearchを作成する時は明示的にオープンアクセスを設定しなければいけないみたいです。
以下がオープンアクセスのポリシーステートメントです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "{domain ARN}/*"
    }
  ]
}

またKibanaにアクセスするためにSOCKSプロキシを用いたダイナミックフォワード方式ではなく、ローカルフォワード方式でSSHトンネルを掘るときには、EC2にアタッチするセキュリティグループにローカルマシンからの443ポートアクセスを許可し、8157ポートを閉じておきましょう。
コマンドもこちらに残しておきます。

$ ssh -i xxxxxxxx.pem ec2-user@{dns} -N -L 9200:{elasticsearch-domain}:443

https://localhost:9200/_plugin/_kibanaへアクセスすると、Kibanaが表示されるはずです。

参考

github.com

aws.amazon.com

docs.aws.amazon.com