LoginSignup
3
4

More than 3 years have passed since last update.

S3の静的ウェブサイトホスティングをRoute53のプライベートホストゾーンからエイリアスする

Posted at

はじめに

S3の静的ウェブサイトホスティングは便利。
でもエンドポイントがhttp://バケット名.s3-website-ap-northeast-1.amazonaws.comになってしまったりhttps://s3-ap-northeast-1.amazonaws.com/バケット名.comになってしまってイケてない。内部通信くらいはちゃんとしたサービス名をつけてあげたいけど内部通信にドメイン使用量は払いたくない。

そんなワガママなあなたに、良い感じの名前でアクセスするコツを書いておく。

さらに、今回の記事では、作った静的ウェブサイトホスティングに対してクロスアカウントでセキュアにアクセスする方法まで書いておく。

Route53のプライベートホストゾーンを使おう

良い感じの名前を付けるのであれば、Route53のプライベートホストゾーンを使えば良い。

プライベートホストゾーンを設定する方法は以前の記事に書いている。

一つ注意しなければいけないのは、S3のエイリアスを作る場合は、「ホスト名=バケット名」になっている必要があるということだ。これをやっておかないと、Route53のホストゾーンでAレコードをS3に紐付けることができない。

Terraformで格納であればこんな感じになる。name = aws_s3_bucket.my.idとしているのがキモだ。
lifecycleについては後述する。

resource "aws_route53_zone" "s3" {
  provider = aws.to_account

  name = local.zone_name

  vpc {
    vpc_id = data.aws_vpc.to.id
  }
}

resource "aws_route53_record" "s3" {
  provider = aws.to_account

  zone_id = aws_route53_zone.s3.zone_id
  name    = aws_s3_bucket.my.id
  type    = "A"

  alias {
    name                   = aws_s3_bucket.my.website_domain
    zone_id                = aws_s3_bucket.my.hosted_zone_id
    evaluate_target_health = true
  }
}

作ったエイリアスレコードを他のAWSアカウントと共有してクロスアカウントアクセスを可能にする

さて、せっかく作ったエイリアスレコードなのだから、複数のサービスで共通で使用したくなることがあるかもしれない。ないかもしれないしその可能性が高い。

だが、もしそういう事態が訪れた時には、AWS公式がやり方を紹介してくれている
このリンクお貼っておくだけでは芸がないので、Terraformで書くとこうなる、を置いておく。

resource "aws_route53_vpc_association_authorization" "s3" {
  provider = aws.to_account

  vpc_id  = data.aws_vpc.from.id
  zone_id = aws_route53_zone.s3.id
}

resource "aws_route53_zone_association" "s3" {
  provider = aws.from_account

  vpc_id  = aws_route53_vpc_association_authorization.s3.vpc_id
  zone_id = aws_route53_vpc_association_authorization.s3.zone_id
}

これでterraform applyすると、aws_route53_zoneに指定したVPCが追加される。
しかし、VPCが追加されるということは、aws_route53_zone.s3の.tfファイルとプロパティが合わなくなってしまうということだ。
すると、何が起こるかと言うと、次にapplyするタイミングで、実際のリソースとの差分を検知して、せっかく設定したVPCの設定が削除されてしまう。

これを避けるために、aws_route53_zone_association でクロスアカウント設定する場合は、aws_route53_zone に以下の設定を追加する。

resource "aws_route53_zone" "s3" {
  provider = aws.to_account

  name = local.zone_name

  vpc {
    vpc_id = data.aws_vpc.to.id
  }

  lifecycle {           ★追加
    ignore_changes = [  ★追加
      vpc,              ★追加
    ]                   ★追加
  }                     ★追加
}

これにより、vpcの変更は無視されるようになるため、次に関係のないリソースをapplyする際に差文検知しなくなる。

クロスアカウントアクセスをセキュアにする

さて、静的Webサイトホスティングの用途は千差万別だが、内部のためにクロスアカウントアクセスを設定したのであれば、以下のようにVPCエンドポイント経由のアクセスにして、該当VPCエンドポイント以外からのアクセスを制限をしよう。バケットポリシーでAllowするのであれば、バケット全体のACL自体はprivateでも問題ない。

resource "aws_vpc_endpoint" "s3" {
  provider = aws.from_account

  vpc_id       = data.aws_vpc.from.id
  service_name = "com.amazonaws.ap-northeast-1.s3"
}

resource "aws_vpc_endpoint_route_table_association" "s3" {
  provider = aws.from_account

  route_table_id  = data.aws_route_table.from.id
  vpc_endpoint_id = aws_vpc_endpoint.s3.id
}

resource "aws_s3_bucket_policy" "my" {
  provider = aws.to_account

  bucket = aws_s3_bucket.my.id

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowVPCEndPointRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::${local.bucket_name}",
        "arn:aws:s3:::${local.bucket_name}/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:sourceVpce": "${aws_vpc_endpoint.s3.id}"
        }
      }
    }
  ]
}
POLICY
}
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4