My objective
I have a number of domains (e.g. 10 or 20) and I would like to redirect any visitors to anywhere on those pages to one page on another domain (for example my stackoverflow.com profile page).
This includes
- apex domain using
http
(e.g.http://mydomain01.com
) - apex domain using
https
(e.g.https://mydomain01.com
) - sub domains using
http
(e.g.http://www.mydomain01.com
orhttp://blog.mydomain01.com
) - sub domains using
https
(e.g.https://www.mydomain01.com
orhttps://blog.mydomain01.com
) - any paths (e.g.
http://mydomain01.com/some_path
orhttps://www.mydomain01.com/another/path.html
)
plus the same for all my other domains (mydomain02.com
, mydomain03.com
, etc.; each with the above use cases).
My research
- This AWS article explains how to redirect internet traffic from an apex domain to another domain (case #1 in my This includes list above) using AWS S3 and AWS Route 53: This works for
http
, but not forhttps
. - This AWS article explains how to redirect internet traffic for a number of cases (by the looks of it, covering all cases in my This includes list above) using AWS S3, AWS Route 53 and AWS CloudFront: This works for both
http
andhttps
. (Also talks about using an Application Load Balancer, but I guess that's beyond the scope here...) - This AWS article adds some more details on setting up a CloudFront distribution and how to get insight into log files.
- This AWS article documents redirection rules to use advanced conditional redirects: Not sure if I need to go there to accomplish my goal, so haven't really looked into that yet.
Plus, there are obviously plenty of SO questions (see Related to the right of this question) and other posts on the subject; problem with most of those is that they use screenshots from previous versions of the AWS Console UI: Most of the contents should still be the same, but correlating those screenshots to the current UI IMO adds another layer of confusion.
Key takeaways from the AWS (and other) docs:
- I need to create a bucket in AWS S3 and configure redirection in it,
- I need to create a distribution in AWS CloudFront;
- in order to use a custom domain in CloudFront, I need to create a certificate in AWS ACM,
- I need to create a hosted zone in AWS Route 53 and configure records in it.
My work so far
The latest AWS CLI is installed, region
and output
are configured in ~/.aws/config
, credentials are set up in ~/.aws/credentials
(each for every AWS account); AWS_*
environment variables are export
ed.
I am using AWS region US East (N. Virginia) (us-east-1)
for everything to prevent any additional issues caused by AWS resources not being available in a region.
$ aws --version
aws-cli/2.2.23 Python/3.9.6 Darwin/19.6.0 source/x86_64 prompt/off
I omit any shell prompts or >
shell line continuation characters for easier copying from this post into the shell.
Set up an S3 bucket
Warning: This creates an "all public" bucket without any access restrictions. In this case, this should not matter as there is no bucket contents to protect, but such a public bucket is a bad practice in general. Also, I'm using a public bucket to prevent any additional issues caused by access restrictions: First, get it work; second, make it secure.
create the bucket
aws s3api create-bucket --bucket mydomain01.com
- response:
{
"Location": "/mydomain01.com"
}
set up redirection
- AWS
put-bucket-website
docs - no point in redacting my SO profile...
aws s3api put-bucket-website --bucket mydomain01.com --website-configuration \
'{ "RedirectAllRequestsTo": { "HostName": "stackoverflow.com/users/217844/ssc" } }'
- no response
Gotcha: The S3 bucket name must match the apex domain name.
Using any bucket name but mydomain01.com
(for my example) seems to fail without any indication as to the cause. The AWS docs don't really make this very clear - in fact, I am still not sure if I massively misunderstand something here, but from what I can tell, the official AWS documentation is actually somewhat sloppy on that - IMO - crucial key point: For example, #2 just says
- Create an S3 bucket with a global unique name.
which could be any globally unique name. #1 mentions that in some way - once you know how to read those bits...
On a side note, that article #2 continues to confuse me with
If you aren't using a custom domain ...
Why would I not be using a custom domain ?!? The whole point is to redirect my custom domain, isn't it ?!? Well, anyway...
Gotcha: Must not prepend protocol to hostname.
Neither the AWS Console nor the AWS CLI seem to test if a protocol (http://
or https://
) was entered in the Host name UI field / passed in the HostName
JSON string. However, if one is prepended, the redirect fails; see test redirection below.
Gotcha: AWS S3 Console UI bug.
After redirection has been set up, the AWS Console displays clickable link in its UI to the bucket URL (http://mydomain01.com.s3-website-us-east-1.amazonaws.com
) at the very bottom of the bucket's Properties tab, in the Static website hosting section.
Clicking that link fails to open the page, seemingly because the AWS Console messes up the URL and tries to open http://https//stackoverflow.com/users/217844/ssc/
, no matter the protocol.
test redirection
- using
HTTPie
in the shell instead ofcurl
orwget
because that's what the cool kids seem to use nowadays - copy the link from AWS Console in browser to shell
http http://mydomain01.com.s3-website-us-east-1.amazonaws.com/
HTTP/1.1 301 Moved Permanently
Content-Length: 0
Date: Mon, 02 Aug 2021 12:39:09 GMT
Location: http://stackoverflow.com/users/217844/ssc/
Server: AmazonS3
x-amz-id-2: rakAqUMnRraGvo/WkSa6AnbuhWn/9YZX/CAlI/OJQKYoWp/OdQIbyhsvHSwNved3suwMdgglqpE=
x-amz-request-id: C5BBG833Q9TQ9J6X
--> seems to work
- test the redirection if the protocol was erroneously prepended to the host name; note the broken
Location
url:
http http://mydomain01.com.s3-website-us-east-1.amazonaws.com/
HTTP/1.1 301 Moved Permanently
Content-Length: 0
Date: Mon, 02 Aug 2021 12:52:10 GMT
Location: http://https://stackoverflow.com/users/217844/ssc/
Server: AmazonS3
x-amz-id-2: Ee2/ob0faTpRdp6mGITdmClozXNmF1Q2oTbPioms8O91VA8n5VA3MoHhveeFz7v2VS65YKFKlDA=
x-amz-request-id: ZJP653R50YD5HSRS
My questions #1
NOTE: I had these questions when I started out writing this; I think I was able to answer them myself since (see test www
sub domain record below). Someone please correct me if I'm wrong:
- Q: Does the "bucket name == domain name" requirement apply even if I use CloudFront ?
A: Yes. - Q: Do I need to create one bucket each for the apex domain and every subdomain ? so, in my example
mydomain01.com
www.mydomain01.com
blog.mydomain01.com
?
A: Yes.
Set up an Route 53 hosted zone
create the hosted zone
- AWS Route 53
create-hosted-zone
docs caller-reference
must simply be a unique string
aws route53 create-hosted-zone --caller-reference "$(date '+%Y%m%d-%H%M%S')" --name mydomain01.com
- response
{
"Location": "https://route53.amazonaws.com/2013-04-01/hostedzone/Z123456789EXAMPLE0SKX",
"HostedZone": {
"Id": "/hostedzone/Z123456789EXAMPLE0SKX",
"Name": "mydomain01.com.",
"CallerReference": "20210802-150736",
"Config": {
"PrivateZone": false
},
"ResourceRecordSetCount": 2
},
"ChangeInfo": {
"Id": "/change/C1234567890SKXEXAMPLE",
"Status": "PENDING",
"SubmittedAt": "2021-08-02T13:07:37.860000+00:00"
},
"DelegationSet": {
"NameServers": [
"ns-1234.awsdns-12.com",
"ns-5678.awsdns-34.co.uk",
"ns-1234.awsdns-56.net",
"ns-5678.awsdns-78.org"
]
}
}
- take note of the hosted zone ID
Z123456789EXAMPLE0SKX
, needed in the next steps
create a record for the apex domain
- AWS Route 53
change-resource-record-sets
docs - this should work for
http
, but not forhttps
- the JSON to pass is somewhat complex; create a local temp file
change-batch.apex.json
with the contents below - get values for
HostedZoneId
andDNSName
from Amazon S3 website endpoints: Bucket was created inUS East (N. Virginia)
, so useZ3AQBSTGFYJSTF
{
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "mydomain01.com.",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z3AQBSTGFYJSTF",
"DNSName": "s3-website-us-east-1.amazonaws.com",
"EvaluateTargetHealth": false
}
}
}
]
}
Gotcha: Must use verbatim s3-website-us-east-1.amazonaws.com
for DNSName
.
AWS docs talk in all sort of places about example.com
or example.com.s3-website-us-east-1.amazonaws.com
, etc. In this case, this is not some example to be replaced by own values (e.g. mydomain01.com.s3-website-us-east-1.amazonaws.com
), but the verbatim value from the table, i.e. s3-website-us-east-1.amazonaws.com
.
Gotcha: Must not prepend protocol to hostname.
Similar to the gotcha above, both AWS Console and the AWS CLI gladly accept a protocol (http://
or https://
) prepended to the value entered in the Host name UI field / passed as DNSName
. At least, this looks very wrong in the Console, e.g. http\072\057\057mydomain01.s3-website-us-east-1.amazonaws.com.
Both gotchas are somewhat mitigated in the AWS Console where values can be selected from a dropdown box when a record is created or edited; when using the AWS CLI, you must double-check what you send.
The same gotcha and mitigation applies to the Record name UI field / Name
JSON value.
create a record for the apex domain, cont.
- use
jq
for a quick test the temp file contains valid json
jq . < change-batch.apex.json 1> /dev/null
- no output --> valid JSON
aws route53 change-resource-record-sets --hosted-zone-id Z123456789EXAMPLE0SKX \
--change-batch "file://$(pwd)/change-batch.apex.json"
- response
{
"ChangeInfo": {
"Id": "/change/C1234567890EXAMPLESKX",
"Status": "PENDING",
"SubmittedAt": "2021-08-02T14:20:09.370000+00:00"
}
}
test apex domain record
- test
http
http http://mydomain01.com
HTTP/1.1 301 Moved Permanently
Content-Length: 0
Date: Mon, 02 Aug 2021 15:06:08 GMT
Location: http://stackoverflow.com/users/217844/ssc/
Server: AmazonS3
x-amz-id-2: EfDtCxif2iV4eInskirSBAOjQS7o9arzJCeZjscF6mW7cwwmm9Nxb7QJT50x2kjdslX2fOxA+lk=
x-amz-request-id: WM7K9TDEF75A6P1V
--> looks good
- test
http
with a path
http http://mydomain01.com/some/path
... similar output as above ...
- test
https
http https://mydomain01.com
http: error: ConnectionError: HTTPSConnectionPool(host='mydomain01.com', port=443):
Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x101a48100>:
Failed to establish a new connection: [Errno 60] Operation timed out')) while doing a GET request to URL: https://mydomain01.com/
- (response wrapped for readability)
--> times out (after 60s ?) - as expected: redirecting using an S3 bucket does not work with https
(see above)
Gotcha: DNS change propagation delay.
AWS and Google are very fast in terms of propagating changes to DNS settings (as in seconds or minutes), but there might be other, "slower" name servers involved. Bypass them as described here to eliminate that source of confusion. That approach only works in macOS, but the concept is the same for any OS.
Gotcha: Browser cache.
When testing DNS changes not in the shell, but in the browser, the browser might get results from its cache. I do most of my work using Chrome, but use Firefox (or Safari) for testing, so I can clear the entire cache before every test to eliminate that potential issue - without getting logged out of Google, AWS, etc.
create a record for www
sub domain
- the only difference is the
Name
JSON value
sed -e 's|mydomain01.com.|www.mydomain01.com.|g' change-batch.apex.json > change-batch.www.json
aws route53 change-resource-record-sets --hosted-zone-id Z123456789EXAMPLE0SKX \
--change-batch "file://$(pwd)/change-batch.www.json
- response similar as above
test www
sub domain record
- test
http
http http://www.mydomain01.com
HTTP/1.1 404 Not Found
Content-Length: 363
Content-Type: text/html; charset=utf-8
Date: Mon, 02 Aug 2021 15:28:05 GMT
Server: AmazonS3
x-amz-id-2: MGLcynq1iEGKh+pT6N6iRpCuQSN243q/5zm2Y7rXTnM7iW9nvDokF6s20xEUBr7QiEtBPEzZmII=
x-amz-request-id: TK83G35EMYFR8SKX
<html>
<head><title>404 Not Found</title></head>
<body>
<h1>404 Not Found</h1>
<ul>
<li>Code: NoSuchBucket</li>
<li>Message: The specified bucket does not exist</li>
<li>BucketName: www.mydomain01.com</li>
<li>RequestId: TK83G35EMYFR8SKX</li>
<li>HostId: MGLcynq1iEGKh+pT6N6iRpCuQSN243q/5zm2Y7rXTnM7iW9nvDokF6s20xEUBr7QiEtBPEzZmII=</li>
</ul>
<hr/>
</body>
</html>
- I think that answers the second of My questions #1 above: I need one S3 bucket per apex/sub domain to forward.
Set up a CloudFront distribution
- NOTE: AWS Console makes it really easy to request a certificate and validate it using DNS.
create a certificate
- AWS ACM
request-certificate
docs - the certificate is supposed to work for the apex and all sub domains, so need to add another name to this certificate / pass
--subject-alternative-names
; see this AWS article (the upper blue box). - add quotes around
*.mydomain01.com
so the shell does not interpret the*
aws acm request-certificate --domain-name mydomain01.com --validation-method DNS \
--subject-alternative-names '*.mydomain01.com'
- response:
{
"CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/12345678-90ab-cdef-1234-1234567890ab"
}
123456789012
is my AWS account ID; everything aftercertificate/
is just a UUID
get certificate details
- AWS ACM
describe-certificate
docs - save response to temporary local file; extract
ResourceRecord.Name
andResourceRecord.Value
usingjq
- needed for the AWS Route 53 record that proves I own
mydomain01.com
- alternatively, use
--query
parameter withaws acm describe-certificate
aws acm describe-certificate \
--certificate-arn "arn:aws:acm:us-east-1:123456789012:certificate/12345678-90ab-cdef-1234-1234567890ab" \
> describe-certificate.json
jq -r '.Certificate.DomainValidationOptions[0].ResourceRecord.Name' describe-certificate.json
_1234567890abcdef1234567890abcdef.mydomain01.com.
jq -r '.Certificate.DomainValidationOptions[0].ResourceRecord.Value' describe-certificate.json
_1234567890abcdef1234567890abcdef.weirdchars.acm-validations.aws.
create a Route 53 record for certificate validation
- will be automatically checked by AWS ACM and the certificate will be validated once this record is found
- as before, use a temporary local file
change-batch.cert.json
, see e.g. create a record for the apex domain; contents:
{
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "_1234567890abcdef1234567890abcdef.mydomain01.com.",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [
{
"Value": "_1234567890abcdef1234567890abcdef.weirdchars.acm-validations.aws."
}
]
}
}
]
}
- shell command:
aws route53 change-resource-record-sets --hosted-zone-id Z123456789EXAMPLE0SKX \
--change-batch "file://$(pwd)/change-batch.cert.json
- response similar as when creating records above
- NOTE: It might take a couple of minutes for ACM to validate the certificate.
create the CloudFront distribution
- AWS CloudFront
create-distribution
docs - again,
CallerReference
must simply be a unique string; use e.g.date '+%Y%m%d-%H%M%S'
in shell to create and copy into file; see create the hosted zone - as before, use a temporary local file
create-distribution.json
for complex values; contents below MinimumProtocolVersion
: get value from this AWS articleOriginProtocolPolicy
: usinghttp-only
because the origin (the S3 bucket) can do onlyhttp
ViewerProtocolPolicy
: usingredirect-to-https
as the whole point of creating this distribution is to redirect fromhttp
tohttps
- NOTE: I don't know (and the AWS docs don't tell) which fields are mandatorily required; the AWS CLI command displays a clear and detailed message if something about the data sent is missing or wrong.
{
"CallerReference": "20210802-191725",
"Aliases": {
"Quantity": 2,
"Items": ["mydomain01.com", "*.mydomain01.com"]
},
"Origins": {
"Quantity": 1,
"Items": [
{
"Id": "mydomain01.com.s3.us-east-1.amazonaws.com_20210802-191725",
"DomainName": "mydomain01.com.s3.us-east-1.amazonaws.com",
"CustomOriginConfig": {
"HTTPPort": 80,
"HTTPSPort": 443,
"OriginProtocolPolicy": "http-only"
}
}
]
},
"OriginGroups": {
"Quantity": 0
},
"DefaultCacheBehavior": {
"TargetOriginId": "mydomain01.com.s3.us-east-1.amazonaws.com_20210802-191725",
"ForwardedValues": {
"QueryString": false,
"Cookies": {
"Forward": "none"
},
"Headers": {
"Quantity": 0
},
"QueryStringCacheKeys": {
"Quantity": 0
}
},
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"ViewerProtocolPolicy": "redirect-to-https",
"MinTTL": 0,
"AllowedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
],
"CachedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
]
}
},
"SmoothStreaming": false,
"DefaultTTL": 86400,
"MaxTTL": 31536000,
"Compress": false,
"LambdaFunctionAssociations": {
"Quantity": 0
},
"FieldLevelEncryptionId": ""
},
"CacheBehaviors": {
"Quantity": 0
},
"CustomErrorResponses": {
"Quantity": 0
},
"Comment": "",
"Logging": {
"Enabled": false,
"IncludeCookies": false,
"Bucket": "",
"Prefix": ""
},
"PriceClass": "PriceClass_All",
"Enabled": true,
"ViewerCertificate": {
"ACMCertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/12345678-90ab-cdef-1234-1234567890ab",
"MinimumProtocolVersion": "TLSv1.2_2021",
"SSLSupportMethod": "sni-only"
},
"Restrictions": {
"GeoRestriction": {
"RestrictionType": "none",
"Quantity": 0
}
},
"WebACLId": "",
"HttpVersion": "http2",
"IsIPV6Enabled": true
}
- shell command:
- NOTE: add
--no-cli-pager
to disable paging and store response in temporary local file for inspection
aws --no-cli-pager cloudfront create-distribution \
--distribution-config "file://$(pwd)/create-distribution.json"
> create-distribution.response.json
- response: a large JSON structure, mostly the config sent with some distribution meta info
Gotcha: CloudFront distribution takes a moment to deploy.
In the Distributions overview, there is a Last modified field that says Deploying for a while after every change; depending on screen and browser window width, this field might be hidden, so the UI might looks like the distribution is up and running while in fact, it is not.
test distribution
- get
DomainName
from response
jq -r '.Distribution.DomainName' create-distribution.response.json
abcdefghij1234.cloudfront.net
- test
http
http http://abcdefghij1234.cloudfront.net
HTTP/1.1 301 Moved Permanently
Connection: keep-alive
Content-Length: 183
Content-Type: text/html
Date: Mon, 02 Aug 2021 20:14:27 GMT
Location: https://abcdefghij1234.cloudfront.net/
Server: CloudFront
Via: 1.1 8640a37b586353bc916562c577770223.cloudfront.net (CloudFront)
X-Amz-Cf-Id: ooT0Y1QvDE7_yoRmb0p0Un2Db6O713rBvudtmz1xer7YwEU0GE8smw==
X-Amz-Cf-Pop: HAM50-C2
X-Cache: Redirect from cloudfront
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>CloudFront</center>
</body>
</html>
So the distribution redirects from http://abcdefghij1234.cloudfront.net
to https://abcdefghij1234.cloudfront.net
- as it should; that's what it was created for.
- test
https
HTTP/1.1 403 Forbidden
Connection: keep-alive
Content-Type: application/xml
Date: Mon, 02 Aug 2021 20:14:35 GMT
Server: AmazonS3
Transfer-Encoding: chunked
Via: 1.1 c3e656776c8a9f0e1ea24405ab1dcc85.cloudfront.net (CloudFront)
X-Amz-Cf-Id: or4SC8urWEv_8c3jDURv5IINwFU1TDVLSQ3_X7tya7Ncz8ujyz0-IQ==
X-Amz-Cf-Pop: HAM50-C2
X-Cache: Error from cloudfront
x-amz-bucket-region: us-east-1
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>EAST1CM5WJR8QM3S</RequestId>
<HostId>zF2dJm2vsuSM633NHuzcA5VqrCrNkfYGu31FRmKKIkebuI5+6l5DlVnr4kk9be262hcqktoiROw=</HostId>
</Error>
- (xml formatted for readability)
That does not look good. Not sure if that is to be expected ?!?
Update the AWS Route 53 records
- change from using the S3 bucket to using the CloudFront distribution
- as before, create a temporary local file
change-batch.apex.updatejson
bysed
ing the earlier filechange-batch.apex.json
- use
UPSERT
instead ofCREATE
: The record exists already and must be updated. HostedZoneId
: replace old valueZ3AQBSTGFYJSTF
(for S3) byZ2FDTNDATAQYW2
, some magic value taken fromchange-resource-record-sets
docsDNSName
: quote fromchange-resource-record-sets
docs
Specify the domain name that CloudFront assigned when you created your distribution.
Your CloudFront distribution must include an alternate domain name that matches the name of the resource record set. For example, if the name of the resource record set is acme.example.com, your CloudFront distribution must include acme.example.com as one of the alternate domain names.
--> replace s3-website-us-east-1.amazonaws.com
(for S3) by abcdefghij1234.cloudfront.net
:
sed -e 's|CREATE|UPSERT|g' \
-e 's|Z3AQBSTGFYJSTF|Z2FDTNDATAQYW2|g' \
-e 's|s3-website-us-east-1.amazonaws.com|abcdefghij1234.cloudfront.net|g' \
change-batch.apex.json > change-batch.apex.update.json
- file contents:
{
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "mydomain01.com.",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"DNSName": "abcdefghij1234.cloudfront.net",
"EvaluateTargetHealth": false
}
}
}
]
}
- shell command
aws route53 change-resource-record-sets \
--hosted-zone-id Z123456789EXAMPLE0SKX \
--change-batch "file://$(pwd)/change-batch.apex.update.json"
- response similar as when creating records above
test apex domain record
- test
http
http http://mydomain01.com
HTTP/1.1 301 Moved Permanently
Connection: keep-alive
Content-Length: 183
Content-Type: text/html
Date: Mon, 02 Aug 2021 19:08:27 GMT
Location: https://mydomain01.com/
Server: CloudFront
Via: 1.1 2408979685aa1bdb752824d292e63bf7.cloudfront.net (CloudFront)
X-Amz-Cf-Id: Ww60Ol_0fdR8SsgcHeRYUd_de1rVejX6w_wuK80aR21e3IHstB-irA==
X-Amz-Cf-Pop: HAM50-C2
X-Cache: Redirect from cloudfront
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>CloudFront</center>
</body>
</html>
- the response now comes from CloudFront and no longer from S3, so the updated DNS record seems to work :-)
- test
http
with a path
http http://mydomain01.com/some/path
... similar output as above ...
--> looks good
- test
https
http https://mydomain01.com
HTTP/1.1 403 Forbidden
Connection: keep-alive
Content-Type: application/xml
Date: Mon, 02 Aug 2021 18:53:51 GMT
Server: AmazonS3
Transfer-Encoding: chunked
Via: 1.1 ea89c67081222c8c680e7a37ad75f4f0.cloudfront.net (CloudFront)
X-Amz-Cf-Id: 5prv5_g5zXOX3aRBp2Gq64JJPuwC2o5dHIp9RCAHm6Ls8hK6EFghXw==
X-Amz-Cf-Pop: HAM50-C2
X-Cache: Error from cloudfront
x-amz-bucket-region: us-east-1
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>T78ASF3FA9QGV4T5</RequestId>
<HostId>xaEgwEtbeesL4XfxMdxVoPAt9Lpb1ZDM9Fs5W4htBbcWNbV9sMUTjVAPIuWwAQ3Xh1yRhh4b4Ts=</HostId>
</Error>
- (as before, xml formatted for readability)
NOTE: This response comes from AmazonS3
, not from CloudFront
as the previous one. The S3 bucket has no access restrictions whatsoever in place - so how can there be an access denied ?!?
double-check bucket permissions
aws s3api get-bucket-policy --bucket mydomain01.com
An error occurred (NoSuchBucketPolicy) when calling the GetBucketPolicy operation: The bucket policy does not exist
That matches the empty Bucket policy field in the AWS S3 Console - but is it really ok that there is no bucket policy at all ?!?
Now that look back at test distribution above, I see that the response to accessing abcdefghij1234.cloudfront.net
directly also come from S3, not from CloudFront, so the problem seems to be pretty clear:
My questions #2
- Why does the S3 bucket deny access ?
- Is it normal for an S3 bucket to have no access policy at all ? Don't usually have "public" buckets a policy that explicitly allows access to anyone ?
- Similar to one S3 bucket per apex / sub domain, do I also need one CloudFront distribution per apex / sub domain ?
- If so, I guess adding
*.mydomain01.com
as alternate domain to the certificate (and the distribution) does not really make any sense, does it ?!? I'd also need one certificate per distribution, dedicated to one domain, correct ?
You are on the right track in general. Just one comment: Route53 can be omitted if your domain uses some other DNS service provider already.
No, if you use CloudFront. The CNAME is configured separately in CloudFront.
No, you don't need one bucket per domain/subdomain.
You should use your
s3-website-us-east-1.amazonaws.com
domain as the CF origin.If you use the bucket just to redirect traffic, no access policy should be fine.
Yes, you need one CloudFront distribution per domain/subdomain because one distribution can attach at most one ACM certificate.
Adding the wildcard domain does make sense since the CF distribution needs to handle subdomain traffic as well.
If you have any further questions, please join the AWS Chat and @ me in the chat.