11

Currently we have a static site deployed to ECS (Elastic Container Service) and fronted by an ELB (Elastic Load Balancer). This model doesn't really make sense, since the container is just running NGINX to serve static assets.

However, what we do get from this model, is VPN-only access to the website (our VPN client forwards all 10.x traffic to our VPC), and an HTTPS listener on the ELB, which are both things that we want to keep.

What's the best way to migrate this static site currently accessible only through VPN to being served from S3/Cloudfront via HTTPS and accessible only through VPN?

We have the same VPN configuration as in this answer. That answer would work for us, but it doesn't address the question of S3 bucket IPs possibly changing (which would invalidate the proposed routing rule on the VPN client), and I'm not clear on how to get HTTPS to work with this (AFAIK, you would need to put CF in front of the S3 static site, but I'm not sure how to route traffic to Cloudfront through our VPN.)

Community
  • 1
  • 1
yangmillstheory
  • 1,055
  • 13
  • 31
  • 1
    This can be done, but it's going to seem a little bit messy when you see how to make it happen. If the site uses HTTPS, then what is the reason for accessing it over the VPN? It would be much easier to use CloudFront + [WAF](https://aws.amazon.com/waf/) to simply restrict access to whatever public IPs are in use by the VPN clients. Of course, if they're not in fixed locations with static IP addresses, then perhaps that's the reason. Please explain. – Michael - sqlbot Feb 16 '17 at 12:35
  • Actually, wait... there's a problem with this plan that we need to be sure doesn't run afoul of your policies. When a bucket is in web site hosting mode, the transport between S3 and the next upstream system is not HTTP. The content will be transported between S3 and whatever is before it (e.g. CloudFront or a proxy in your VPC) in the clear, before the HTTPS is added on. This will be on the AWS network but not encrypted end-to-end. Is that an acceptable limitation? – Michael - sqlbot Feb 16 '17 at 12:44
  • @Michael-sqlbot unencrypted traffic between S3 and CF is OK, if it's on the AWS network. VPN clients don't have static IPs; only traffic to 10.x (VPC) and 172.x (private office network) go through our AWS VPC/VPN gateway, and Cloudfront is public. Does that make sense? – yangmillstheory Feb 16 '17 at 17:07
  • If the S3 bucket had a static IP, I could route traffic from the VPN client through our VPN/VPC tunnel, and use a bucket policy that allowed access only from our VPN/VPC connection, but I'd lose HTTPS. So for HTTPS, I'd have to use Cloudfront. However, this doesn't really make sense either, since it's an internal-only company website, so the problem then becomes how to make this accessible only through the VPN. – yangmillstheory Feb 16 '17 at 17:25
  • I am in a similar situation. We have an internal only static site on S3 Hosting. The bucket has a Policy that restricts traffic only from the VPC and we have Direct Connect so the site is only accessible via our network. But we now have a need to integrate with Cognito (For SSO Federation) but Cognito doesn't allow HTTP callback URLs. Not really sure how to resolve this. – Anjan Biswas Aug 23 '19 at 00:27

1 Answers1

2

I decided to use VPC endpoints to control ingress. There's an internal load-balancer (private subnet) accessible only through VPC/VPN that routes traffic to a VPC endpoint.

Bucket policy looks like (Terraform template)

{
  "Version": "2012-10-17",
  "Id": "Policy1415115909152",
  "Statement": [
    {
      "Sid": "deny-get-if-not-from-vpce",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Deny",
      "Resource": [
        "arn:aws:s3:::${bucket}",
        "arn:aws:s3:::${bucket}/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:sourceVpce": "${vpce_id}"
        }
      },
      "Principal": "*"
    },
    {
      "Sid": "allow-get-if-from-vpce",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::${bucket}",
        "arn:aws:s3:::${bucket}/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:sourceVpce": "${vpce_id}"
        }
      },
      "Principal": "*"
    }
  ]
}

And it works! We get an SSL connection, and the load balancer zero access outside the VPN (load balancer DNS won't resolve, and 403 on the S3 static site itself).

See http://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies-vpc-endpoint.html.

bschlueter
  • 3,817
  • 1
  • 30
  • 48
yangmillstheory
  • 1,055
  • 13
  • 31
  • Hi, would be useful to know how the ELB routes traffic to the VPC endpoint? As far as I can tell you can only add instances to ELBs. Did you point the ELB at an instance running some proxy software? – lukewm Jun 29 '17 at 13:13
  • 2
    There needs to be an entry in the route table that directs traffic to S3 to the VPC Endpoint. See the diagram in http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-endpoints.html. We use Terraform (Infrastructure As Code) to do this, so that entry is created automatically with https://www.terraform.io/docs/providers/aws/d/vpc_endpoint.html. – yangmillstheory Jun 29 '17 at 22:01
  • Thanks @yangmillstheory – lukewm Jul 05 '17 at 10:59
  • 5
    I still don't understand how the traffic gets from the Load balancer to the S3 bucket. A VPC endpoint with route table allows traffic from within a subnet to access the S3 bucket, and a load balancer is inside a subnet, but as far as I can tell there is nothing which exists that allows traffic received from a load balancer to be directed to the bucket. – apdm Dec 13 '18 at 16:54
  • Hello, did you remove CloudFront completely in this scenario? or the load balancer is being hit through CloudFront? – Daniel Jun 29 '21 at 19:21