Skip to content

Commit

Permalink
Implement S3 Bucket Suitable for Serving Static Websites on S3 (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
osterman authored and const-bon committed Sep 19, 2017
1 parent b0a4077 commit fb10238
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 1 deletion.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Compiled files
*.tfstate
*.tfstate.backup
*.terraform.tfstate*
# Module directory
.terraform/

.idea
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright {yyyy} {name of copyright owner}
Copyright 2017 Cloud Posse, LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,58 @@
# tf_s3_website

Terraform Module for Creating S3 backed Websites

## Further Reading

* http://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html

## Usage

module "website" {
source = "git::https://github.com/cloudposse/tf_s3_website.git?ref=master"
namespace = "${var.namespace}"
stage = "${var.stage}"
name = "${var.name}"
hostname = "${var.hostname}"
dns_zone_id = "${var.dns_zone_id}"
}

## Variables

| Name | Default | Description | Required |
|:------------------------------------|:--------------:|:----------------------------------------------------------------------------------------------------------------|:--------:|
| `namespace` | `` | Namespace (e.g. `cp` or `cloudposse`) | Yes |
| `stage` | `` | Stage (e.g. `prod`, `dev`, `staging`) | Yes |
| `name` | `` | Name (e.g. `bastion` or `db`) | Yes |
| `attributes` | `[]` | Additional attributes (e.g. `policy` or `role`) | No |
| `tags` | `{}` | Additional tags (e.g. `map("BusinessUnit","XYZ")` | No |
| `delimiter` | `-` | Delimiter to be used between `name`, `namespace`, `stage`, `arguments`, etc. | No |
| `hostname` | `[]` | Name of website bucket in `fqdn` format (e.g. `test.example.com`). IMPORTANT! Do not add trailing dot (`.`) | Yes |
| `dns_zone_id` | `` | ID of the hosted zone to contain the record | Yes |
| `error_document` | `404.html` | An absolute path to the document to return in case of a 4XX error | No |
| `index_document` | `index.html` | Amazon S3 returns this index document when requests are made to the root domain or any of the subfolders | No |
| `force_destroy` | `` | Delete all objects from the bucket so that the bucket can be destroyed without error (e.g. `true` or `false`) | No |
| `lifecycle_rule_enabled` | `` | Lifecycle rule status (e.g. `true` or `false`) | No |
| `noncurrent_version_transition_days`| `30` | Number of days to persist in the standard storage tier before moving to the glacier tier infrequent access tier | No |
| `noncurrent_version_expiration_days`| `90` | Specifies when noncurrent object versions expire | No |
| `cors_allowed_headers` | `["*"]` | List of allowed headers | No |
| `cors_allowed_methods` | `["GET"]` | List of allowed methods (e.g. ` GET, PUT, POST, DELETE, HEAD`) | No |
| `cors_allowed_origins` | `["*"]` | List of allowed origins (e.g. ` example.com, test.com`) | No |
| `cors_max_age_seconds` | `3600` | Time in seconds that browser can cache the response | No |
| `cors_expose_headers` | `["ETag"]` | List of expose header in the response | No |
| `prefix` | `` | Prefix identifying one or more objects to which the rule applies | No |
| `region` | `` | AWS region this bucket should reside in | No |
| `routing_rules` | `` | A json array containing routing rules describing redirect behavior and when redirects are applied | No |
| `versioning_enabled` | `` | State of versioning (e.g. `true` or `false`) | No |
| `logs_standard_transition_days` | `30` | Number of days to persist in the standard storage tier before moving to the glacier tier | No |
| `logs_glacier_transition_days` | `60` | Number of days after which to move the data to the glacier storage tier | No |
| `logs_expiration_days` | `90` | Number of days after which to expunge the objects | No |


## Outputs

| Name | Description |
|:------------------------------ |:------------------------------------------------------------|
| `hostname` | Assigned DNS-record to the DNS-record of website bucket |
| `s3_bucket_domain_name` | DNS-record of website bucket |
| `s3_bucket_name` | Name of of website bucket |
92 changes: 92 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
module "logs" {
source = "git::https://github.com/cloudposse/tf_log_storage.git?ref=tags/0.1.0"
name = "${var.name}"
stage = "${var.stage}"
namespace = "${var.namespace}"
standard_transition_days = "${var.logs_standard_transition_days}"
glacier_transition_days = "${var.logs_glacier_transition_days}"
expiration_days = "${var.logs_expiration_days}"
}

module "default_label" {
source = "git::https://github.com/cloudposse/tf_label.git?ref=tags/0.2.0"
namespace = "${var.namespace}"
stage = "${var.stage}"
name = "${var.name}"
delimiter = "${var.delimiter}"
attributes = ["origin"]
tags = "${var.tags}"
}

resource "aws_s3_bucket" "default" {
bucket = "${var.hostname}"
acl = "public-read"
tags = "${module.default_label.tags}"
region = "${var.region}"
force_destroy = "${var.force_destroy}"

logging {
target_bucket = "${module.logs.bucket_id}"
target_prefix = "${module.logs.prefix}"
}

website {
index_document = "${var.index_document}"
error_document = "${var.error_document}"
routing_rules = "${var.routing_rules}"
}

cors_rule {
allowed_headers = "${var.cors_allowed_headers}"
allowed_methods = "${var.cors_allowed_methods}"
allowed_origins = "${var.cors_allowed_origins}"
expose_headers = "${var.cors_expose_headers}"
max_age_seconds = "${var.cors_max_age_seconds}"
}

versioning {
enabled = "${var.versioning_enabled}"
}

lifecycle_rule {
id = "${module.default_label.id}"
enabled = "${var.lifecycle_rule_enabled}"
prefix = "${var.prefix}"
tags = "${module.default_label.tags}"

noncurrent_version_transition {
days = "${var.noncurrent_version_transition_days}"
storage_class = "GLACIER"
}

noncurrent_version_expiration {
days = "${var.noncurrent_version_expiration_days}"
}
}
}

resource "aws_s3_bucket_policy" "default" {
bucket = "${aws_s3_bucket.default.id}"
policy = "${data.aws_iam_policy_document.default.json}"
}

data "aws_iam_policy_document" "default" {
statement {
actions = ["s3:GetObject"]

resources = ["${aws_s3_bucket.default.arn}/*"]

principals {
type = "AWS"
identifiers = ["*"]
}
}
}

module "dns" {
source = "git::https://github.com/cloudposse/tf_vanity.git?ref=tags/0.2.0"
aliases = "${list(var.hostname)}"
parent_zone_id = "${var.dns_zone_id}"
target_dns_name = "${aws_s3_bucket.default.website_domain}"
target_zone_id = "${aws_s3_bucket.default.hosted_zone_id}"
}
11 changes: 11 additions & 0 deletions output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output "s3_bucket_name" {
value = "${aws_s3_bucket.default.id}"
}

output "s3_bucket_domain_name" {
value = "${aws_s3_bucket.default.bucket_domain_name}"
}

output "hostname" {
value = "${var.hostname}"
}
99 changes: 99 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
variable "name" {}

variable "namespace" {}

variable "stage" {}

variable "tags" {
default = {}
}

variable "delimiter" {
default = "-"
}

variable "hostname" {
}

variable "dns_zone_id" {
description = "ID of the hosted zone to contain the record"
}

variable "index_document" {
default = "index.html"
}

variable "error_document" {
default = "404.html"
}

variable "routing_rules" {
default = ""
}

variable "cors_allowed_headers" {
type = "list"
default = ["*"]
}

variable "cors_allowed_methods" {
type = "list"
default = ["GET"]
}

variable "cors_allowed_origins" {
type = "list"
default = ["*"]
}

variable "cors_expose_headers" {
type = "list"
default = ["ETag"]
}

variable "cors_max_age_seconds" {
default = "3600"
}

variable "logs_standard_transition_days" {
description = "Number of days to persist in the standard storage tier before moving to the glacier tier"
default = "30"
}

variable "logs_glacier_transition_days" {
description = "Number of days after which to move the data to the glacier storage tier"
default = "60"
}

variable "logs_expiration_days" {
description = "Number of days after which to expunge the objects"
default = "90"
}

variable "lifecycle_rule_enabled" {
default = ""
}

variable "prefix" {
default = ""
}

variable "noncurrent_version_transition_days" {
default = "30"
}

variable "noncurrent_version_expiration_days" {
default = "90"
}

variable "region" {
default = ""
}

variable "versioning_enabled" {
default = ""
}

variable "force_destroy" {
default = ""
}

0 comments on commit fb10238

Please sign in to comment.