Skip to content

Commit

Permalink
feat: add policy for preventing unencrypted uploads, add new output, …
Browse files Browse the repository at this point in the history
…add possibility to create tfstate-backend by terraform (#17)

* feat: add policy for preventing unencrypted uploads, add new output, add possibility to create tfstate-backend by terraform

* docs: regenerate README.md
  • Loading branch information
SweetOps authored and osterman committed Mar 25, 2019
1 parent 647f942 commit 3c9b64f
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 4 deletions.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are
}
module "terraform_state_backend" {
source = "git::https://github.com/cloudposse/terraform- aws-tfstate-backend.git?ref=master"
source = "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master"
namespace = "cp"
stage = "prod"
name = "terraform"
Expand Down Expand Up @@ -136,12 +136,19 @@ Available targets:
| mfa_delete | A boolean that indicates that versions of S3 objects can only be deleted with MFA. ( Terraform cannot apply changes of this value; https://github.com/terraform-providers/terraform-provider-aws/issues/629 ) | string | `false` | no |
| name | Solution name, e.g. 'app' or 'jenkins' | string | `terraform` | no |
| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | string | `` | no |
| prevent_unencrypted_uploads | Prevent uploads of unencrypted objects to S3 | string | `true` | no |
| profile | AWS profile name as set in the shared credentials file | string | `` | no |
| read_capacity | DynamoDB read capacity units | string | `5` | no |
| regex_replace_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. By default only hyphens, letters and digits are allowed, all other chars are removed | string | `/[^a-zA-Z0-9-]/` | no |
| region | AWS Region the S3 bucket should reside in | string | - | yes |
| restrict_public_buckets | Whether Amazon S3 should restrict public bucket policies for this bucket. | string | `false` | no |
| role_arn | The role to be assumed | string | `` | no |
| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | string | `` | no |
| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | map | `<map>` | no |
| terraform_backend_config_file_name | Name of terraform backend config file | string | `terraform.tf` | no |
| terraform_backend_config_file_path | The path to terrafrom project directory | string | `` | no |
| terraform_state_file | The path to the state file inside the bucket | string | `terraform.tfstate` | no |
| terraform_version | The minimum required terraform version | string | `0.11.3` | no |
| write_capacity | DynamoDB write capacity units | string | `5` | no |

## Outputs
Expand All @@ -154,6 +161,7 @@ Available targets:
| s3_bucket_arn | S3 bucket ARN |
| s3_bucket_domain_name | S3 bucket domain name |
| s3_bucket_id | S3 bucket ID |
| terraform_backend_config | Rendered Terraform backend config file |



Expand Down Expand Up @@ -291,15 +299,17 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply

### Contributors

| [![Andriy Knysh][aknysh_avatar]][aknysh_homepage]<br/>[Andriy Knysh][aknysh_homepage] | [![Erik Osterman][osterman_avatar]][osterman_homepage]<br/>[Erik Osterman][osterman_homepage] | [![Maarten van der Hoef][maartenvanderhoef_avatar]][maartenvanderhoef_homepage]<br/>[Maarten van der Hoef][maartenvanderhoef_homepage] |
|---|---|---|
| [![Andriy Knysh][aknysh_avatar]][aknysh_homepage]<br/>[Andriy Knysh][aknysh_homepage] | [![Erik Osterman][osterman_avatar]][osterman_homepage]<br/>[Erik Osterman][osterman_homepage] | [![Maarten van der Hoef][maartenvanderhoef_avatar]][maartenvanderhoef_homepage]<br/>[Maarten van der Hoef][maartenvanderhoef_homepage] | [![Vladimir][SweetOps_avatar]][SweetOps_homepage]<br/>[Vladimir][SweetOps_homepage] |
|---|---|---|---|

[aknysh_homepage]: https://github.com/aknysh
[aknysh_avatar]: https://github.com/aknysh.png?size=150
[osterman_homepage]: https://github.com/osterman
[osterman_avatar]: https://github.com/osterman.png?size=150
[maartenvanderhoef_homepage]: https://github.com/maartenvanderhoef
[maartenvanderhoef_avatar]: https://github.com/maartenvanderhoef.png?size=150
[SweetOps_homepage]: https://github.com/SweetOps
[SweetOps_avatar]: https://github.com/SweetOps.png?size=150



Expand Down
4 changes: 3 additions & 1 deletion README.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ usage: |-
}
module "terraform_state_backend" {
source = "git::https://github.com/cloudposse/terraform- aws-tfstate-backend.git?ref=master"
source = "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master"
namespace = "cp"
stage = "prod"
name = "terraform"
Expand Down Expand Up @@ -115,3 +115,5 @@ contributors:
github: "osterman"
- name: "Maarten van der Hoef"
github: "maartenvanderhoef"
- name: "Vladimir"
github: "SweetOps"
8 changes: 8 additions & 0 deletions docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@
| mfa_delete | A boolean that indicates that versions of S3 objects can only be deleted with MFA. ( Terraform cannot apply changes of this value; https://github.com/terraform-providers/terraform-provider-aws/issues/629 ) | string | `false` | no |
| name | Solution name, e.g. 'app' or 'jenkins' | string | `terraform` | no |
| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | string | `` | no |
| prevent_unencrypted_uploads | Prevent uploads of unencrypted objects to S3 | string | `true` | no |
| profile | AWS profile name as set in the shared credentials file | string | `` | no |
| read_capacity | DynamoDB read capacity units | string | `5` | no |
| regex_replace_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. By default only hyphens, letters and digits are allowed, all other chars are removed | string | `/[^a-zA-Z0-9-]/` | no |
| region | AWS Region the S3 bucket should reside in | string | - | yes |
| restrict_public_buckets | Whether Amazon S3 should restrict public bucket policies for this bucket. | string | `false` | no |
| role_arn | The role to be assumed | string | `` | no |
| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | string | `` | no |
| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | map | `<map>` | no |
| terraform_backend_config_file_name | Name of terraform backend config file | string | `terraform.tf` | no |
| terraform_backend_config_file_path | The path to terrafrom project directory | string | `` | no |
| terraform_state_file | The path to the state file inside the bucket | string | `terraform.tfstate` | no |
| terraform_version | The minimum required terraform version | string | `0.11.3` | no |
| write_capacity | DynamoDB write capacity units | string | `5` | no |

## Outputs
Expand All @@ -35,4 +42,5 @@
| s3_bucket_arn | S3 bucket ARN |
| s3_bucket_domain_name | S3 bucket domain name |
| s3_bucket_id | S3 bucket ID |
| terraform_backend_config | Rendered Terraform backend config file |

88 changes: 88 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
locals {
prevent_unencrypted_uploads = "${var.prevent_unencrypted_uploads == "true" && var.enable_server_side_encryption == "true" ? 1 : 0}"
policy = "${local.prevent_unencrypted_uploads ? join("", data.aws_iam_policy_document.prevent_unencrypted_uploads.*.json) : ""}"
terraform_backend_config_file = "${format("%s/%s", var.terraform_backend_config_file_path, var.terraform_backend_config_file_name)}"
}

module "base_label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.6.3"
namespace = "${var.namespace}"
Expand All @@ -18,11 +24,72 @@ module "s3_bucket_label" {
context = "${module.base_label.context}"
}

data "aws_iam_policy_document" "prevent_unencrypted_uploads" {
count = "${local.prevent_unencrypted_uploads}"

statement = {
sid = "DenyIncorrectEncryptionHeader"

effect = "Deny"

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

actions = [
"s3:PutObject",
]

resources = [
"arn:aws:s3:::${module.s3_bucket_label.id}/*",
]

condition {
test = "StringNotEquals"
variable = "s3:x-amz-server-side-encryption"

values = [
"AES256",
]
}
}

statement = {
sid = "DenyUnEncryptedObjectUploads"

effect = "Deny"

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

actions = [
"s3:PutObject",
]

resources = [
"arn:aws:s3:::${module.s3_bucket_label.id}/*",
]

condition {
test = "Null"
variable = "s3:x-amz-server-side-encryption"

values = [
"true",
]
}
}
}

resource "aws_s3_bucket" "default" {
bucket = "${module.s3_bucket_label.id}"
acl = "${var.acl}"
region = "${var.region}"
force_destroy = "${var.force_destroy}"
policy = "${local.policy}"

versioning {
enabled = true
Expand Down Expand Up @@ -95,3 +162,24 @@ resource "aws_dynamodb_table" "without_server_side_encryption" {

tags = "${module.dynamodb_table_label.tags}"
}

data "template_file" "terraform_backend_config" {
template = "${file("${path.module}/templates/terraform.tf.tpl")}"

vars {
region = "${var.region}"
bucket = "${aws_s3_bucket.default.id}"
dynamodb_table = "${element(coalescelist(aws_dynamodb_table.with_server_side_encryption.*.name, aws_dynamodb_table.without_server_side_encryption.*.name), 0)}"
encrypt = "${var.enable_server_side_encryption == "true" ? "true" : "false"}"
role_arn = "${var.role_arn}"
profile = "${var.profile}"
terraform_version = "${var.terraform_version}"
terraform_state_file = "${var.terraform_state_file}"
}
}

resource "local_file" "terraform_backend_config" {
count = "${length(var.terraform_backend_config_file_path) > 0 ? 1 : 0}"
content = "${data.template_file.terraform_backend_config.rendered}"
filename = "${local.terraform_backend_config_file}"
}
5 changes: 5 additions & 0 deletions output.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ output "dynamodb_table_arn" {
value = "${element(coalescelist(aws_dynamodb_table.with_server_side_encryption.*.arn, aws_dynamodb_table.without_server_side_encryption.*.arn), 0)}"
description = "DynamoDB table ARN"
}

output "terraform_backend_config" {
value = "${data.template_file.terraform_backend_config.rendered}"
description = "Rendered Terraform backend config file"
}
13 changes: 13 additions & 0 deletions templates/terraform.tf.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
terraform {
required_version = ">= ${terraform_version}"
backend "s3" {
region = "${region}"
bucket = "${bucket}"
key = "${terraform_state_file}"
dynamodb_table = "${dynamodb_table}"
profile = "${profile}"
role_arn = "${role_arn}"
encrypt = "${encrypt}"
}
}
36 changes: 36 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,39 @@ variable "regex_replace_chars" {
default = "/[^a-zA-Z0-9-]/"
description = "Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. By default only hyphens, letters and digits are allowed, all other chars are removed"
}

variable "prevent_unencrypted_uploads" {
type = "string"
default = "true"
description = "Prevent uploads of unencrypted objects to S3"
}

variable "profile" {
default = ""
description = "AWS profile name as set in the shared credentials file"
}

variable "role_arn" {
default = ""
description = "The role to be assumed"
}

variable "terraform_backend_config_file_name" {
default = "terraform.tf"
description = "Name of terraform backend config file"
}

variable "terraform_backend_config_file_path" {
default = ""
description = "The path to terrafrom project directory"
}

variable "terraform_version" {
default = "0.11.3"
description = "The minimum required terraform version"
}

variable "terraform_state_file" {
default = "terraform.tfstate"
description = "The path to the state file inside the bucket"
}

0 comments on commit 3c9b64f

Please sign in to comment.