Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix website support, remove awsutils depenencies #158

Merged
merged 4 commits into from
Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/auto-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ version-resolver:
- 'bugfix'
- 'bug'
- 'hotfix'
- 'no-release'
default: 'minor'

categories:
Expand Down
74 changes: 53 additions & 21 deletions README.md

Large diffs are not rendered by default.

46 changes: 34 additions & 12 deletions README.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,26 @@ description: |-

If `user_enabled` variable is set to `true`, the module will provision a basic IAM user with permissions to access the bucket.
This basic IAM system user is suitable for CI/CD systems (_e.g._ TravisCI, CircleCI) or systems which are *external* to AWS that cannot leverage
[AWS IAM Instance Profiles](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html) and
[AWS IAM Instance Profiles](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html)
or [AWS OIDC](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) to authenticate and
do not already have IAM credentials. Users or systems that have IAM credentials should either be granted access directly based on
their IAM identity or be allowed to assume an IAM role with access.
their IAM identity via `privileged_principal_arns` or be allowed to assume an IAM role with access.

We do not recommend creating IAM users this way for any other purpose.

This module blocks public access to the bucket by default. See `block_public_acls`, `block_public_policy`,
`ignore_public_acls`, and `restrict_public_buckets` to change the settings. See [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html)
for more details.

If an IAM user is created, the IAM user name is constructed using [terraform-null-label](https://github.com/cloudposse/terraform-null-label)
and some input is required. The simplest input is `name`. By default the name will be converted to lower case
and all non-alphanumeric characters except for hyphen will be removed. See the documentation for `terraform-null-label`
to learn how to override these defaults if desired.

If an AWS Access Key is created, it is stored either in SSM Parameter Store or is provided as a module output,
but not both. Using SSM Parameter Store is recommended because module outputs are stored in plaintext in
the Terraform state file.

# How to use this project
usage: |-
Using a [canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html).
Expand All @@ -90,14 +100,24 @@ usage: |-
source = "cloudposse/s3-bucket/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
acl = "private"
enabled = true
user_enabled = true
versioning_enabled = false
allowed_bucket_actions = ["s3:GetObject", "s3:ListBucket", "s3:GetBucketLocation"]
name = "app"
stage = "test"
namespace = "eg"

acl = "private"
enabled = true
user_enabled = false
versioning_enabled = false

privileged_principal_actions = ["s3:GetObject", "s3:ListBucket", "s3:GetBucketLocation"]
privileged_principal_arns = [
{
(local.deployment_iam_role_arn) = [""]
},
{
(local.additional_deployment_iam_role_arn) = ["prefix1/", "prefix2/"]
}
]
}
```

Expand Down Expand Up @@ -144,14 +164,14 @@ usage: |-
source = "cloudposse/s3-bucket/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
acl = ""
enabled = true
user_enabled = true
versioning_enabled = true
allowed_bucket_actions = ["s3:GetObject", "s3:ListBucket", "s3:GetBucketLocation"]
name = "app"
stage = "test"
namespace = "eg"

acl = ""
enabled = true
user_enabled = false
versioning_enabled = true

lifecycle_configuration_rules = local.lifecycle_configuration_rules

Expand Down Expand Up @@ -223,3 +243,5 @@ contributors:
github: "joshmyers"
- name: "Yonatan Koren"
github: "korenyoni"
- name: "Nuru"
github: "Nuru"
21 changes: 15 additions & 6 deletions docs/terraform.md

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions examples/complete/fixtures.us-east-2.tfvars
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
enabled = true

region = "us-east-2"

namespace = "eg"
Expand Down
8 changes: 8 additions & 0 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,13 @@ module "s3_bucket" {
transfer_acceleration_enabled = true
bucket_key_enabled = var.bucket_key_enabled

access_key_enabled = var.access_key_enabled
store_access_key_in_ssm = var.store_access_key_in_ssm
ssm_base_path = "/${module.this.id}"

website_configuration = var.website_configuration
cors_configuration = var.cors_configuration
website_redirect_all_requests_to = var.website_redirect_all_requests_to

context = module.this.context
}
35 changes: 35 additions & 0 deletions examples/complete/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ output "bucket_domain_name" {
description = "FQDN of bucket"
}

output "bucket_website_domain" {
value = module.s3_bucket.bucket_website_domain
description = "The bucket website domain, if website is enabled"
}

output "bucket_website_endpoint" {
value = module.s3_bucket.bucket_website_endpoint
description = "The bucket website endpoint, if website is enabled"
}

output "bucket_id" {
value = module.s3_bucket.bucket_id
description = "Bucket ID"
Expand Down Expand Up @@ -47,3 +57,28 @@ output "user_unique_id" {
value = module.s3_bucket.user_unique_id
description = "The user unique ID assigned by AWS"
}

// Terraform does not include null values in outputs, so to simplify testing,
// we replace the null value with an empty string. `coalesce` is used to
// test for null values, as it fails if all values are empty.
output "access_key_id" {
sensitive = true
value = try(coalesce(module.s3_bucket.access_key_id), "")
description = "Access Key ID"
}

output "secret_access_key" {
sensitive = true
value = try(coalesce(module.s3_bucket.secret_access_key), "")
description = "Secret Access Key. This will be written to the state file in plain-text"
}

output "access_key_id_ssm_path" {
value = try(coalesce(module.s3_bucket.access_key_id_ssm_path), "")
description = "The SSM Path under which the S3 User's access key ID is stored"
}

output "secret_access_key_ssm_path" {
value = try(coalesce(module.s3_bucket.secret_access_key_ssm_path), "")
description = "The SSM Path under which the S3 User's secret access key is stored"
}
63 changes: 61 additions & 2 deletions examples/complete/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ variable "lifecycle_rule_enabled" {
variable "prefix" {
type = string
default = ""
description = "Prefix identifying one or more objects to which the rule applies"
description = "Prefix identifying 1 or more objects to which the rule applies"
}

variable "noncurrent_version_transition_days" {
Expand All @@ -173,7 +173,48 @@ variable "noncurrent_version_expiration_days" {
description = "Specifies when noncurrent object versions expire"
}

variable "cors_rule_inputs" {
variable "website_redirect_all_requests_to" {
type = list(object({
host_name = string
protocol = string
}))
description = "If provided, all website requests will be redirected to the specified host name and protocol"
default = []

validation {
condition = length(var.website_redirect_all_requests_to) < 2
error_message = "Only 1 website_redirect_all_requests_to is allowed."
aknysh marked this conversation as resolved.
Show resolved Hide resolved
}
}

variable "website_configuration" {
type = list(object({
index_document = string
error_document = string
routing_rules = list(object({
condition = object({
http_error_code_returned_equals = string
key_prefix_equals = string
})
redirect = object({
host_name = string
http_redirect_code = string
protocol = string
replace_key_prefix_with = string
replace_key_with = string
})
}))
}))
description = "Specifies the static website hosting configuration object"
default = []

validation {
condition = length(var.website_configuration) < 2
error_message = "Only 1 website_configuration is allowed."
}
}

variable "cors_configuration" {
type = list(object({
allowed_headers = list(string)
allowed_methods = list(string)
Expand Down Expand Up @@ -283,3 +324,21 @@ variable "bucket_key_enabled" {
For more information, see: https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-key.html
EOT
}

variable "access_key_enabled" {
type = bool
default = true
description = "Set to `true` to create an IAM Access Key for the created IAM user"
}

variable "store_access_key_in_ssm" {
type = bool
default = false
description = <<-EOT
Set to `true` to store the created IAM user's access key in SSM Parameter Store,
`false` to store them in Terraform state as outputs.
Since Terraform state would contain the secrets in plaintext,
use of SSM Parameter Store is recommended.
EOT
}

24 changes: 24 additions & 0 deletions examples/complete/website-redirect.us-east-2.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
region = "us-east-2"

namespace = "eg"

stage = "test"

name = "s3-test-website"

acl = "private"

force_destroy = true

user_enabled = false

versioning_enabled = false

allow_encrypted_uploads_only = false

bucket_key_enabled = true

website_redirect_all_requests_to = [{
host_name = "www.example.com"
protocol = "https"
}]
71 changes: 71 additions & 0 deletions examples/complete/website.us-east-2.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
region = "us-east-2"

namespace = "eg"

stage = "test"

name = "s3-test-website"

acl = "private"

force_destroy = true

user_enabled = false

versioning_enabled = false

allow_encrypted_uploads_only = false

bucket_key_enabled = true

website_configuration = [
{
index_document = "index.html"
error_document = null
routing_rules = [
{
condition = {
http_error_code_returned_equals = "404"
key_prefix_equals = "docs/"
}
redirect = {
host_name = null
http_redirect_code = "301"
protocol = "https"
replace_key_prefix_with = "documents/"
replace_key_with = null
}
},
aknysh marked this conversation as resolved.
Show resolved Hide resolved
{
condition = {
http_error_code_returned_equals = null
key_prefix_equals = null
}
redirect = {
host_name = null
http_redirect_code = "302"
protocol = "https"
replace_key_prefix_with = "maintenance/"
replace_key_with = null
}
}
]
}
]

cors_configuration = [
{
allowed_headers = ["*"]
allowed_methods = ["PUT", "POST"]
allowed_origins = ["https://s3-website-test.testing.cloudposse.co"]
expose_headers = ["ETag"]
max_age_seconds = 3000
},
{
allowed_headers = null
allowed_methods = ["GET"]
allowed_origins = ["*"]
expose_headers = null
max_age_seconds = null
}
]
Loading