Skip to content

Commit

Permalink
Merge pull request #89 from Vermyndax/optional-content-sync-identity
Browse files Browse the repository at this point in the history
Create optional sync user
  • Loading branch information
Vermyndax authored Mar 27, 2021
2 parents 0d6948c + acd46d2 commit d8341db
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 23 deletions.
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ No modules.
| Name | Type |
|------|------|
| [aws_cloudfront_distribution.site_cloudfront_distribution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution) | resource |
| [aws_iam_access_key.content_sync_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_access_key) | resource |
| [aws_iam_user.content_sync](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user) | resource |
| [aws_iam_user_policy.content_sync_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy) | resource |
| [aws_route53_record.site_tld_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_route53_record.site_www_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_route53_zone.primary_site_tld](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource |
Expand All @@ -96,23 +99,27 @@ No modules.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_acm_site_certificate_arn"></a> [acm\_site\_certificate\_arn](#input\_acm\_site\_certificate\_arn) | ARN of an ACM certificate to use for https on the CloudFront distribution. | `any` | n/a | yes |
| <a name="input_acm_site_certificate_arn"></a> [acm\_site\_certificate\_arn](#input\_acm\_site\_certificate\_arn) | ARN of an ACM certificate to use for https on the CloudFront distribution. | `string` | n/a | yes |
| <a name="input_cloudfront_price_class"></a> [cloudfront\_price\_class](#input\_cloudfront\_price\_class) | Price class for Cloudfront. | `string` | `"PriceClass_100"` | no |
| <a name="input_content_bucket_versioning"></a> [content\_bucket\_versioning](#input\_content\_bucket\_versioning) | Defines whether or not to set versioning on the content bucket. | `bool` | `true` | no |
| <a name="input_create_cloudfront_distribution"></a> [create\_cloudfront\_distribution](#input\_create\_cloudfront\_distribution) | Defines whether or not to create a CloudFront distribution for the S3 bucket. | `bool` | `true` | no |
| <a name="input_create_public_dns_site_record"></a> [create\_public\_dns\_site\_record](#input\_create\_public\_dns\_site\_record) | If set to true, creates a public DNS record in your site\_tld hosted zone. If you do not already have a hosted zone for this TLD, you should set create\_public\_dns\_zone to true. Otherwise, this will try to create a record in an existing zone or fail. | `string` | `"true"` | no |
| <a name="input_create_content_sync_user"></a> [create\_content\_sync\_user](#input\_create\_content\_sync\_user) | Optionally create an IAM user and access keys to sync the content bucket. Note that this will store access information in your state file. Protect it accordingly. | `bool` | `false` | no |
| <a name="input_create_public_dns_site_record"></a> [create\_public\_dns\_site\_record](#input\_create\_public\_dns\_site\_record) | If set to true, creates a public DNS record in your site\_tld hosted zone. If you do not already have a hosted zone for this TLD, you should set create\_public\_dns\_zone to true. Otherwise, this will try to create a record in an existing zone or fail. | `bool` | `true` | no |
| <a name="input_create_public_dns_www_record"></a> [create\_public\_dns\_www\_record](#input\_create\_public\_dns\_www\_record) | Defines whether or not to create a WWW DNS record for the site. | `bool` | `false` | no |
| <a name="input_create_public_dns_zone"></a> [create\_public\_dns\_zone](#input\_create\_public\_dns\_zone) | If set to true, creates a public hosted zone in Route53 for your site. | `string` | `"false"` | no |
| <a name="input_create_sns_topic"></a> [create\_sns\_topic](#input\_create\_sns\_topic) | Defines whether or not to create an SNS topic for notifications about events. | `bool` | `false` | no |
| <a name="input_create_public_dns_zone"></a> [create\_public\_dns\_zone](#input\_create\_public\_dns\_zone) | If set to true, creates a public hosted zone in Route53 for your site. | `bool` | `false` | no |
| <a name="input_create_www_redirect_bucket"></a> [create\_www\_redirect\_bucket](#input\_create\_www\_redirect\_bucket) | Defines whether or not to create a www redirect S3 bucket. | `bool` | `true` | no |
| <a name="input_error_page_object"></a> [error\_page\_object](#input\_error\_page\_object) | The error page object for the Cloudfront/S3 distribution. | `string` | `"404.html"` | no |
| <a name="input_log_include_cookies"></a> [log\_include\_cookies](#input\_log\_include\_cookies) | Defines whether or not CloudFront should log cookies. | `bool` | `false` | no |
| <a name="input_root_page_object"></a> [root\_page\_object](#input\_root\_page\_object) | The root page object for the Cloudfront/S3 distribution. | `string` | `"index.html"` | no |
| <a name="input_site_region"></a> [site\_region](#input\_site\_region) | Region in which to provision the site. Default: us-east-1 | `string` | `"us-east-1"` | no |
| <a name="input_site_tld"></a> [site\_tld](#input\_site\_tld) | TLD of the website you want to create. A bucket will be created that is named this. Note that the module will error out if this bucket already exists in AWS. Example: example.com | `any` | n/a | yes |
| <a name="input_sns_topic_name"></a> [sns\_topic\_name](#input\_sns\_topic\_name) | Name for the SNS topic. | `string` | `"website-notifications"` | no |
| <a name="input_site_tld"></a> [site\_tld](#input\_site\_tld) | TLD of the website you want to create. A bucket will be created that is named this. Note that the module will error out if this bucket already exists in AWS. Example: example.com | `string` | n/a | yes |

## Outputs

No outputs.
| Name | Description |
|------|-------------|
| <a name="output_cloudfront_distribution_id"></a> [cloudfront\_distribution\_id](#output\_cloudfront\_distribution\_id) | CloudFront distribution ID. |
| <a name="output_content_sync_access_key"></a> [content\_sync\_access\_key](#output\_content\_sync\_access\_key) | Access key ID of the optional content sync user. |
| <a name="output_content_sync_access_secret"></a> [content\_sync\_access\_secret](#output\_content\_sync\_access\_secret) | Secret Access key of the optional content sync user. This is marked as sensitive and will not show in plan output, but be aware that it is stored in your state file. Encrypt accordingly. |
| <a name="output_content_sync_bucket_name"></a> [content\_sync\_bucket\_name](#output\_content\_sync\_bucket\_name) | Bucket name that contains the content for the site. |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
88 changes: 84 additions & 4 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ resource "aws_s3_bucket_public_access_block" "content_bucket_block" {

# S3 bucket for www redirect (optional)
resource "aws_s3_bucket" "site_www_redirect" {
count = var.create_www_redirect_bucket == "true" ? 1 : 0
count = var.create_www_redirect_bucket == true ? 1 : 0
bucket = "www.${random_uuid.random_bucket_name.result}"
# region = var.site_region
acl = "private"
Expand Down Expand Up @@ -190,7 +190,7 @@ resource "aws_cloudfront_distribution" "site_cloudfront_distribution" {
# DNS entry pointing to public site - optional

resource "aws_route53_zone" "primary_site_tld" {
count = var.create_public_dns_zone == "true" ? 1 : 0
count = var.create_public_dns_zone == true ? 1 : 0
name = var.site_tld
}

Expand All @@ -199,7 +199,7 @@ data "aws_route53_zone" "site_tld_selected" {
}

resource "aws_route53_record" "site_tld_record" {
count = var.create_public_dns_site_record == "true" ? 1 : 0
count = var.create_public_dns_site_record == true ? 1 : 0
zone_id = data.aws_route53_zone.site_tld_selected.zone_id
name = "${var.site_tld}."
type = "A"
Expand All @@ -212,7 +212,7 @@ resource "aws_route53_record" "site_tld_record" {
}

resource "aws_route53_record" "site_www_record" {
count = var.create_public_dns_www_record == "true" ? 1 : 0
count = var.create_public_dns_www_record == true ? 1 : 0
zone_id = data.aws_route53_zone.site_tld_selected.zone_id
name = "www"
type = "CNAME"
Expand All @@ -221,3 +221,83 @@ resource "aws_route53_record" "site_www_record" {
records = [var.site_tld]
}

# Optional content sync user

resource "aws_iam_user" "content_sync" {
count = var.create_content_sync_user == true ? 1 : 0
name = "${var.site_tld}-content-sync-user"

/* tags = {
tag-key = "tag-value"
} */
}

resource "aws_iam_access_key" "content_sync_key" {
count = var.create_content_sync_user == true ? 1 : 0
user = aws_iam_user.content_sync[count.index].name
}

resource "aws_iam_user_policy" "content_sync_policy" {
count = var.create_content_sync_user == true ? 1 : 0
name = "${var.site_tld}-content-sync-policy"
user = aws_iam_user.content_sync[count.index].name

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CloudFrontStuff",
"Effect": "Allow",
"Action": [
"acm:ListCertificates",
"cloudfront:GetDistribution",
"cloudfront:GetStreamingDistribution",
"cloudfront:GetDistributionConfig",
"cloudfront:ListDistributions",
"cloudfront:ListCloudFrontOriginAccessIdentities",
"cloudfront:CreateInvalidation",
"cloudfront:GetInvalidation",
"cloudfront:ListInvalidations",
"elasticloadbalancing:DescribeLoadBalancers",
"iam:ListServerCertificates",
"sns:ListSubscriptionsByTopic",
"sns:ListTopics",
"waf:GetWebACL",
"waf:ListWebACLs"
],
"Resource": "${aws_cloudfront_distribution.site_cloudfront_distribution.arn}"
},
{
"Sid": "BucketStuff",
"Effect": "Allow",
"Action": [
"s3:GetBucketTagging",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::${random_uuid.random_bucket_name.result}"
},
{
"Sid": "ObjectStuff",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::${random_uuid.random_bucket_name.result}/*",
"arn:aws:s3:::${random_uuid.random_bucket_name.result}"
]
},
{
"Sid": "HighLevelStuff",
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
}
]
}
EOF
}
20 changes: 20 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
output "content_sync_access_key" {
value = var.create_content_sync_user ? aws_iam_access_key.content_sync_key[0].id : ""
description = "Access key ID of the optional content sync user."
}

output "content_sync_access_secret" {
value = var.create_content_sync_user ? aws_iam_access_key.content_sync_key[0].secret : ""
sensitive = true
description = "Secret Access key of the optional content sync user. This is marked as sensitive and will not show in plan output, but be aware that it is stored in your state file. Encrypt accordingly."
}

output "content_sync_bucket_name" {
value = random_uuid.random_bucket_name.result
description = "Bucket name that contains the content for the site."
}

output "cloudfront_distribution_id" {
value = aws_cloudfront_distribution.site_cloudfront_distribution.id
description = "CloudFront distribution ID."
}
33 changes: 21 additions & 12 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -1,74 +1,83 @@
# Creation flags first

variable "site_region" {
type = string
description = "Region in which to provision the site. Default: us-east-1"
default = "us-east-1"
}

variable "create_www_redirect_bucket" {
type = bool
description = "Defines whether or not to create a www redirect S3 bucket."
default = true
}

variable "content_bucket_versioning" {
type = bool
description = "Defines whether or not to set versioning on the content bucket."
default = true
}

variable "create_cloudfront_distribution" {
type = bool
description = "Defines whether or not to create a CloudFront distribution for the S3 bucket."
default = true
}

variable "log_include_cookies" {
type = bool
description = "Defines whether or not CloudFront should log cookies."
default = false
}

variable "create_sns_topic" {
description = "Defines whether or not to create an SNS topic for notifications about events."
default = false
}

variable "sns_topic_name" {
description = "Name for the SNS topic."
default = "website-notifications"
}

variable "site_tld" {
type = string
description = "TLD of the website you want to create. A bucket will be created that is named this. Note that the module will error out if this bucket already exists in AWS. Example: example.com"
}

variable "create_public_dns_zone" {
type = bool
description = "If set to true, creates a public hosted zone in Route53 for your site."
default = "false"
default = false
}

variable "create_public_dns_site_record" {
type = bool
description = "If set to true, creates a public DNS record in your site_tld hosted zone. If you do not already have a hosted zone for this TLD, you should set create_public_dns_zone to true. Otherwise, this will try to create a record in an existing zone or fail."
default = "true"
default = true
}

variable "create_public_dns_www_record" {
type = bool
description = "Defines whether or not to create a WWW DNS record for the site."
default = false
}

variable "root_page_object" {
type = string
description = "The root page object for the Cloudfront/S3 distribution."
default = "index.html"
}

variable "error_page_object" {
type = string
description = "The error page object for the Cloudfront/S3 distribution."
default = "404.html"
}

variable "cloudfront_price_class" {
type = string
description = "Price class for Cloudfront."
default = "PriceClass_100"
}

variable "acm_site_certificate_arn" {
type = string
description = "ARN of an ACM certificate to use for https on the CloudFront distribution."
}

variable "create_content_sync_user" {
type = bool
description = "Optionally create an IAM user and access keys to sync the content bucket. Note that this will store access information in your state file. Protect it accordingly."
default = false
}

0 comments on commit d8341db

Please sign in to comment.