VPC作る時のメモ(RouteTable,NetWorkACL, NAT, InternetGateway)

VPC作成するときにルートテーブルとネットワークACLでよく迷うのでメモ

ルートテーブル

  • サブネットに付くもの
  • いわゆるルーティング
  • IGWとかNATへの行き先はここで指定する
  • サブネット側から選べるが何も指定しないとメインルートテーブルが選択される
  • privateとpublicでサブネット分けるならルートテーブルを分ける
    • private側のルートテーブルで0.0.0.0/0をNATに向ける
    • public側のルートテーブルで0.0.0.0/0をIGWに向ける

ネットワークACL

  • サブネットに付くもの
  • いわゆるファイヤーウォール
  • デフォルト設定で全開放
    • なのここは全開放のままでSGで適切的に開放して行くでいいと思ってる

NatGateway

  • サブネット単位
  • publicサブネットに付与する必要あり
  • private側の0.0.0.0/0をNatに刺してpublic側はIGWを指す

InternetGateway

  • VPCにアタッチする
  • 実際に使用するのはルートテーブル側

おまけ

  • enableDnsHostnames
  • enableDnsSupport デフォルトでオフになってるのでオンにするかは確認したほうがいい。 Glue使うときはonになってる必要がある

ALB + ACM + EC2 + SES + RDS + ElastiCacheでre:dash環境を構築する

マネージドサービスを使うのにECSは使わずにEC2な理由

なんとなくなのだが、ECSに持って行くのが面倒。workerとかその辺。 永続データさえちゃんと残しておけば最悪redash server自体は作り直しでもいいかなーと思い。

ソースはこちら github.com

ここに載ってる通りcloneして来てdocker-compose upすればとりあえず起動するが、 production readyな環境としてはセットアップスクリプトを使用する様子 redash.io

セットアップスクリプトはこちら github.com

って事でやってみる

前提

  • SESはSMTP認証で送信可能な状態
  • EC2, RDS(postgresql9.5) ElastiCache(Redis)はセットアップ済み
  • VPC,SecurityGroup的に
    • EC2からpostgresqlとElastiCacheに接続可能な状態(psql,redis-cliで接続を確認する)
    • ALBからEC2へ5000portで接続可能な状態にしておく
  • EC2は公式推奨のubuntu16で起動
  • ACMssl証明書取得済み
  • ALBにACMセット済み

思ったより前提が多いが。手馴れてれる内容ではある。

setup

EC2にsudo可能なユーザーでログインしたら

# redash起動場所
sudo mkdir /opt/redash
chown ubunt:ubuntu /opt/redash
# setup script取得
git clone https://github.com/getredash/redash.git

cloneして来たsetup.shをちょっと修正

https://github.com/getredash/setup/blob/master/setup.sh

環境変数の修正,DB接続のパスワードはRDS起動した時のパスワードを使う

# ここコメントアウトしちゃう
#POSTGRES_PASSWORD=$(pwgen -1s 32)
# RDSで設定したパスワード
POSTGRES_PASSWORD="postgresユーザーパスワード"
REDASH_DATABASE_URL="postgresql://postgres:${POSTGRES_PASSWORD}@RDSエンドポイント/postgres"

echo "REDASH_REDIS_URL=redis://ElastiCacheエンドポイント:6379/0" >> $REDASH_BASE_PATH/env
echo "POSTGRES_PASSWORD=$POSTGRES_PASSWORD" >> $REDASH_BASE_PATH/env

echo "REDASH_MAIL_DEFAULT_SENDER=SESで送信元に使うメールアドレス" >> $REDASH_BASE_PATH/env
# バージニアなら email-smtp.us-east-1.amazonaws.com
# https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/smtp-connect.html
echo "REDASH_MAIL_SERVER=SESエンドポイント" >> $REDASH_BASE_PATH/env
echo "REDASH_MAIL_USERNAME=SMTPユーザーネーム" >> $REDASH_BASE_PATH/env
echo "REDASH_MAIL_PASSWORD=SMTPパスワード" >> $REDASH_BASE_PATH/env
echo "REDASH_MAIL_USE_SSL=false" >> $REDASH_BASE_PATH/env
echo "REDASH_MAIL_USE_TLS=true" >> $REDASH_BASE_PATH/env
# TLS送信するから指定, デフォルト25だとエラー
echo "REDASH_MAIL_PORT=587" >> $REDASH_BASE_PATH/env

環境変数周りはここに載ってる redash.io

shellを変更し終わったら実行

sh ./setup/setup.sh

これでredashサーバは起動可能

ssl接続する場合

ALBの下に入れてしまうのが簡単 ACMssl証明書をセットして、 port 443 -> 5000でフォワードする

CloudWatchLogsのサブスクリプションフィルターでkinesis firehoseへ流すとjsonのダブルクオートがバックスラッシュでエスケープされる

CloudWatch Logs サブスクリプションフィルタの使用 - Amazon CloudWatch Logs

仕様らしい。

cw-logs自体がjson invalidで出力したいから、 messagesという中に含まれるユーザー側が出力する値はstringとして扱うためにダブルクォーテーションをエスケープされてしまう。

firehoseのlambda変換スクリプト内部でどうにかするしかなさそうである。

不便だなー。

s3のレプリケーションは機能有効化した後のデータしかレプリケートしない

Amazon S3 は何をレプリケートしますか - Amazon Simple Storage Service

デフォルトでは、Amazon S3 は以下をレプリケートします。 レプリケーション設定の追加後に作成されたオブジェクト。

既存のオブジェクトのレプリケーション

というメニューもあるようだが、サポート依頼なので あくまでオプション的な機能のようだ。

S3 バッチオペレーション の実行 - Amazon Simple Storage Service

aws.amazon.com

aws cli使うかbatch operationを使う感じで。 いずれにせよ設定しただけでどうにかなるものではないみたい。

IAM PassRoleについて理解する(なんとなく)

AWSを使ってるとなんとなくしかわかっていないIAMのPassRole

IAM: 特定の AWS サービスに IAM ロールを渡す - AWS Identity and Access Management

dev.classmethod.jp

dev.classmethod.jp

安定のクラメソさんと公式の一部

まず。何となくEC2とRDSで運用。みたいな感じだとそのサーバーがアクセスしたいリソースへのアクセス権をアタッチしておくのがIAM Roleという理解。 「EC2からS3へアクセスしたい」とかが良い例。

んで。クラメソさんのEC2の例だと。 何かしらの理由で自由にEC2へアタッチされるRoleが選ばれると困るから「EC2へアタッチできるRoleはこのロールだけね」って感じの設定をしてるんだと思う。

大前提としてPassRoleしてないサービスへはRoleは付与できないと言う事なのかな。

んで。

次の例として出してるCodePipelineの例。

AWSCodePipelineFullAccess

        {
            "Action": [
                "iam:PassRole"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:iam::*:role/service-role/cwe-role-*"
            ],
            "Condition": {
                "StringEquals": {
                    "iam:PassedToService": [
                        "events.amazonaws.com"
                    ]
                }
            }
        },
        {
            "Action": [
                "iam:PassRole"
            ],
            "Effect": "Allow",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:PassedToService": [
                        "codepipeline.amazonaws.com"
                    ]
                }
            }
        },

自分のIAMから同じのをコピってきた。 まず下段の

            "Resource": "*",
            "codepipeline.amazonaws.com"

これでこのポリシーをアタッチされたCodePipelineリソース自身がCodePipelineリソースへのアクセス権(作成とか削除とか)を持つことになる。 (当たり前すぎて逆に混乱するのだがそう言うこと)

そして上段側の

                "arn:aws:iam::*:role/service-role/cwe-role-*"
                 "events.amazonaws.com"

これによってアタッチされたCodePipelineリソースがイベントブリッジにアタッチできるロールはワイルドカードで指定されているようなroleのみとなる。

何となくGlueとかLambdaとかでもこの辺が出てくるのだが。 使いたいサービスが他のサービスに依存しているときに(CloudWatchとかS3とか)、 GlueサービスとかLambdaサービスのリソースにアタッチされているRoleにcloudwatchとかの作成や修正の権限が無いと動かせない。

って事なのかなと理解してる。

違ってたら修正したい。

次はAssumeRole

AWS WAFを導入するための最低限必要な知識

AWS WAF(new)

古いものはclassicと表記されている。 今回検証対象としないため対象外

いわゆるWeb Application FireWallで。 SQLインジェクションとかXSSみたいな怪しいhttpリクエストをblockしてくれたりログ出してくれたりメトリクスを出してくれたりする。

設定対象

CloudFrontかALB(CLBは不可)にアタッチする。 akamaiやinacpsulaのようなCDN型みたいにCNAMEで指定するようなやり方では無い。 なのでオンプレとか他クラウドにアタッチはできない(ACMみたいなもん)

WEB ACL

名前の通りウェブアクセスコントロールリスト。 ブロックするアルゴリズムを設定する。 このACL自体にデフォルトアクションとしてallowとblockがある。

外部向けサービスなら基本的にallow 社内向けサービスとかで閉じたいならblock(cloudfront + s3みたいな構成でも使える。もちろんバケットポリシーでもいいが)

RuleGroup

ルールグループはルールの塊。 SQLインジェクションのルールとか。作る。 まずはマネージドルールを適用するところから始める。

自分でルールをカスタマイズもできるのでその場合はルールグループを作成することになる。

IP Sets

IPのホワイトリストブラックリストを作成するにはここで作成する。 RuleGroupとは別管理になるが。 WEB Acl側から見ると適用するルールの一つということになるのでこれもWEB ACLにセットすることになる。

AWSマネージドルール

AWSがあらかじめ用意してくれてるルールで、 terminatingRuleMatchDetails というSQLインジェクションXSSにおいて bodyのログを出してくれるのはマネージドルールだけ。

dev.classmethod.jp

今回はAMRsからCore rule setとSQL databaseを利用します。セットアップ方法は下記を参照してください。

クラスメソットさん参照

この後はWAF Charmとfirehose & s3を使ったログについて

s3のVPCエンドポイント情報

基本機能

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-endpoints.html

  • サブネット単位で設定可能 -- 実際はRouteTable単位

インターフェースエンドポイントとゲートウェイエンドポイントがある。 s3はゲートウェイエンドポイント。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpce-gateway.html

プレフィックスリストの ID の形式は pl-xxxxxxx で、プレフィックスリストの名前の形式は「com.amazonaws.region.service」

作るとこいう感じのリソースができるので、 これをサブネットのRouteTBLに追加すると設定される。

エンドポイントにはエンドポイントポリシーが割振れて、これでアクセスコントロールが出来る。 今はまだ全許可しかしてない。 (アウトバウンドを抑制するようなセキュリティ要件が厳しい場合に使用するのか?)

1 つの VPC 内に複数のエンドポイントを (複数のサービス用などに) 作成できます。また、1 つのサービス用に複数のエンドポイントを作成し、複数のルートテーブルを使用して、この同じサービスに複数のサブネットから異なるアクセスポリシーを適用することもできます。

なるほど。S3とDynamoDBと両方ともをVPCエンドポイントにする場合二つのエンドポイントを一つのRouteテーブルに紐付ける形になると。

きになる制限

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-endpoints-s3.html

エンドポイントポリシーでは、Docker イメージレイヤーを保存するために Amazon ECR で使用される Amazon S3 バケットへのアクセスを許可する必要があります。詳細については、Amazon Elastic Container Registry ユーザーガイドの「インターフェイス VPC エンドポイント (AWS PrivateLink)」を参照してください。

ECR使ってる場合ECRのバケットへの許可を明示的にやる必要がありそう。

特定の S3 バケットへのアクセスを制限するポリシーを作成できます。これは、VPC で S3 バケットを使用する他の AWS サービスがある場合に便利です。my_secure_bucket のみへのアクセスを制限するポリシーの例を次に示します。

なるほど。VPCエンドポイント側の設定でVPC内部のリソースからのアクセスを制御できると。

Amazon S3 バケットポリシーの使用

バケットポリシー側でもできると。 リクエストを出す側と受け付ける側。どちら側でやるかは好みだと思うけど。

それなりに複雑になってきてる構成の場合エンドポイントルールでやるのはそれなりに効率良さそう。