Skip to content

Commit 7342c2e

Browse files
authored
Add deployers, general code cleanup (#160)
1 parent 2efb943 commit 7342c2e

File tree

12 files changed

+498
-154
lines changed

12 files changed

+498
-154
lines changed

README.md

Lines changed: 127 additions & 27 deletions
Large diffs are not rendered by default.

README.yaml

Lines changed: 107 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,26 @@ usage: |-
6363
6464
For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test).
6565
66-
This will create a new s3 bucket `eg-prod-app` for a cloudfront cdn.
66+
This will create a new s3 bucket `eg-prod-app` for a cloudfront cdn, and allow `principal1` to upload to
67+
`prefix1` and `prefix2`, while allowing `principal2` to manage the whole bucket.
6768
6869
```hcl
6970
module "cdn" {
7071
source = "cloudposse/cloudfront-s3-cdn/aws"
7172
# Cloud Posse recommends pinning every module to a specific version
72-
# version = "x.x.x"
73+
# version = "x.x.x"
7374
7475
namespace = "eg"
7576
stage = "prod"
7677
name = "app"
7778
aliases = ["assets.cloudposse.com"]
7879
dns_alias_enabled = true
7980
parent_zone_name = "cloudposse.com"
81+
82+
deployment_arns = {
83+
"arn:aws:s3:::principal1" = ["/prefix1", "/prefix2"]
84+
"arn:aws:s3:::principal2" = [""]
85+
}
8086
}
8187
```
8288
@@ -86,7 +92,7 @@ usage: |-
8692
module "cdn" {
8793
source = "cloudposse/cloudfront-s3-cdn/aws"
8894
# Cloud Posse recommends pinning every module to a specific version
89-
# version = "x.x.x"
95+
# version = "x.x.x"
9096
9197
origin_bucket = "eg-prod-app"
9298
aliases = ["assets.cloudposse.com"]
@@ -95,22 +101,110 @@ usage: |-
95101
}
96102
```
97103
98-
### Using an S3 Static Website Origin
99-
100-
When variable `website_enabled` is set to `true`, the S3 origin is configured
101-
as a static website. The S3 static website has the advantage of redirecting
102-
URL `subdir/` to `subdir/index.html` without requiring a
103-
[Lambda@Edge function to perform the redirection](https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/).
104-
The S3 static website responds only to CloudFront, preventing direct access to
105-
S3.
106-
104+
### Background on CDNs, "Origins", S3 Buckets, and Web Servers
105+
106+
#### CDNs and Origin Servers
107+
108+
There are some settings you need to be aware of when using this module. In order to understand the settings,
109+
you need to understand some of the basics of CDNs and web servers, so we are providing this _highly simplified_
110+
explanation of how they work in order for you to understand the implications of the settings you are providing.
111+
112+
A "**CDN**" ([Content Distribution Network](https://www.cloudflare.com/learning/cdn/what-is-a-cdn/)) is a collection of
113+
servers scattered around the internet with the aim of making it faster for people to retrieve content from a website.
114+
The details of why that is wanted/needed are beyond the scope of this document, as are most of the details of how
115+
a CDN is implemented. For this discussion, we will simply treat a CDN as a set of web servers all serving
116+
the same content to different users.
117+
118+
In a normal web server (again, greatly simplified), you place files on the server and the web server software receives
119+
requests from browsers and responds with the contents of the files.
120+
121+
For a variety of reasons, the web servers in a CDN do not work the way normal web servers work. Instead of getting
122+
their content from files on the local server, the CDN web servers get their content by acting like web browsers
123+
(proxies). When they get a request from a browser, they make the same request to what is called an "**Origin Server**".
124+
It is called an origin server because it _serves_ the original content of the web site, and thus is the _origin_
125+
of the content.
126+
127+
As a web site publisher, you put content on an Origin Server (which users usually should be prevented from accessing)
128+
and configure your CDN to use your Origin Server. Then you direct users to a URL hosted by your CDN provider, the
129+
users' browsers connect to the CDN, the CDN gets the content from your Origin Server, your Origin Server gets the
130+
content from a file on the server, and the data gets sent back hop by hop to the user. (The reason this ends up
131+
being a good idea is that the CDN can cache the content for a while, serving multiple users the same content while
132+
only contacting the origin server once.)
133+
134+
#### S3 Buckets: file storage and web server
135+
136+
S3 buckets were originally designed just to store files, and they are still most often used for that. The have a lot
137+
of access controls to make it possible to strictly limit who can read what files in the bucket, so that companies
138+
can store sensitive information there. You may have heard of a number of "data breaches" being caused by misconfigured
139+
permissions on S3 buckets, making them publicly accessible. As a result of that, Amazon has some extra settings on
140+
top of everything else to keep S3 buckets from being publicly accessible, which is usually a good thing.
141+
142+
However, at some point someone realized that since these files were in the cloud, and Amazon already had these web servers
143+
running to provide access to the files in the cloud, it was only a tiny leap to turn an S3 bucket into a web server.
144+
So now S3 buckets [can be published as web sites](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EnableWebsiteHosting.html)
145+
with a few configuration settings, including making the contents publicly accessible.
146+
147+
#### Web servers, files, and the different modes of S3 buckets
148+
149+
In the simplest web sites, the URL "path" (the part after the site name) corresponds directly to the path (under
150+
a special directory we will call `/webroot`) and name
151+
of a file on the web server. So if the web server gets a request for "http://example.com/foo/bar/baz.html" it will
152+
look for a file `/webroot/foo/bar/baz.html`. If it exists, the server will return its contents, and if it does not exist,
153+
the server will return a `Not Found` error. An S3 bucket, whether configured as a file store or a web site, will
154+
always do both of these things.
155+
156+
Web servers, however, do some helpful extra things. To name a few:
157+
- If the URL ends with a `/`, as in `http://example.com/foo/bar/`, the web server (depending on how it is configured)
158+
will either return a list of files in the directory or it will return the contents of a file in the directory with
159+
a special name (by default, `index.html`) if it exists.
160+
- If the URL does not end with a `/` but the last part, instead of being a file name, is a directory name, the web
161+
server will redirect the user to the URL with the `/` at the end instead of saying the file was `Not Found`. This
162+
redirect will get you to the `index.html` file we just talked about. Given the way people pass URLs around, this
163+
turns out to be quite helpful.
164+
- If the URL does not point to a directory or a file, instead of just sending back a cryptic `Not Found` error code,
165+
it can return the contents of a special file called an "error document".
166+
167+
#### Your Critical Decision: S3 bucket or website?
168+
169+
All of this background is to help you decide how to set `website_enabled` and `s3_website_password_enabled`.
170+
The default for `website_enabled` is `false` which is the easiest to configure and the most secure, and with
171+
this setting, `s3_website_password_enabled` is ignored.
172+
173+
S3 buckets, in file storage mode (`website_enabled = false`), do none of these extra things that web servers do.
174+
If the URL points to a file, it will return the file, and if it does not _exactly_ match a file, it will return
175+
`Not Found`. One big advantage, though, is that the S3 bucket can remain private (not publicly accessible). A second,
176+
related advantage is that you can limit the website to a portion of the S3 bucket (everything under a certain prefix)
177+
and keep the contents under the the other prefixes private.
178+
179+
S3 buckets configured as static websites (`website_enabled = true`), however, have these extra web server features like redirects, `index.html`,
180+
and error documents. The disadvantage is that you have to make the entire bucket public (although you can still
181+
restrict access to some portions of the bucket).
182+
183+
Another feature or drawback (depending on your point of view) of S3 buckets configured as static web sites is that
184+
they are directly accessible via their [website endpoint](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteEndpoints.html)
185+
as well as through Cloudfront. This module has a feature, `s3_website_password_enabled`, that requires a password
186+
be passed in the HTTP request header and configures the CDN to do that, which will make it much harder to access
187+
the S3 website directly. So set `s3_website_password_enabled = true` to limit direct access to the S3 website
188+
or set it to false if you want to be able to bypass Cloudfront when you want to.
189+
107190
In addition to setting `website_enabled=true`, you must also:
108191
109192
* Specify at least one `aliases`, like `["example.com"]` or
110193
`["example.com", "www.example.com"]`
111194
* Specify an ACM certificate
112195
113-
### Generating ACM Certificate
196+
### Custom Domain Names and Generating a TLS Certificate with ACM
197+
198+
When you set up Cloudfront, Amazon will generate a domain name for your website. You amost certainly will not
199+
want to publish that. Instead, you will want to use a custom domain name. This module refers to them as "aliases".
200+
201+
To use the custom domain names, you need to
202+
- Pass them in as `aliases` so that Cloudfront will respond to them with your content
203+
- Create CNAMEs for the aliases to point to the Cloudfront domain name. If your alias domains are hosted by
204+
Route53 and you have IAM permissions to modify them, this module will set that up for you if you set `dns_alias_enabled = true`.
205+
- Generate a TLS Certificate via ACM that includes the all the aliases and pass the ARN for the
206+
certificate in `acm_certificate_arn`. Note that for Cloudfront, the certificate has to be provisioned in the
207+
`us-east-1` region regardless of where any other resources are.
114208
115209
```hcl
116210
# For cloudfront, the acm has to be created in us-east-1 or it will not work

0 commit comments

Comments
 (0)