From 0d0a773a673ec8603d0a99183f36a6535003d64a Mon Sep 17 00:00:00 2001 From: Maxim Mironenko Date: Wed, 27 Feb 2019 16:25:39 +0600 Subject: [PATCH] policy to allow only encrypted uploads (#5) * added policy to allow only encrypted uploads --- README.md | 2 +- docs/terraform.md | 2 +- main.tf | 47 +++++++++++++++++++++++++++++++++++++++++++++++ outputs.tf | 5 ----- variables.tf | 6 ++++++ 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index bf23ba35..6accb7a1 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ Available targets: | Name | Description | Type | Default | Required | |------|-------------|:----:|:-----:|:-----:| | acl | The canned ACL to apply. We recommend `private` to avoid exposing sensitive information | string | `private` | no | +| allow_encrypted_uploads_only | Set to `true` to prevent uploads of unencrypted objects to S3 bucket | string | `false` | no | | allowed_bucket_actions | List of actions the user is permitted to perform on the S3 bucket | list | `` | no | | attributes | Additional attributes (e.g. `1`) | list | `` | no | | delimiter | Delimiter to be used between `namespace`, `stage`, `name` and `attributes` | string | `-` | no | @@ -105,7 +106,6 @@ Available targets: | bucket_domain_name | FQDN of bucket | | bucket_id | Bucket Name (aka ID) | | enabled | Is module enabled | -| s3_bucket_arn | S3 bucket ARN | | secret_access_key | The secret access key. This will be written to the state file in plain-text | | user_arn | The ARN assigned by AWS for the user | | user_enabled | Is user creation enabled | diff --git a/docs/terraform.md b/docs/terraform.md index 3918b59b..3fe001b2 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -3,6 +3,7 @@ | Name | Description | Type | Default | Required | |------|-------------|:----:|:-----:|:-----:| | acl | The canned ACL to apply. We recommend `private` to avoid exposing sensitive information | string | `private` | no | +| allow_encrypted_uploads_only | Set to `true` to prevent uploads of unencrypted objects to S3 bucket | string | `false` | no | | allowed_bucket_actions | List of actions the user is permitted to perform on the S3 bucket | list | `` | no | | attributes | Additional attributes (e.g. `1`) | list | `` | no | | delimiter | Delimiter to be used between `namespace`, `stage`, `name` and `attributes` | string | `-` | no | @@ -28,7 +29,6 @@ | bucket_domain_name | FQDN of bucket | | bucket_id | Bucket Name (aka ID) | | enabled | Is module enabled | -| s3_bucket_arn | S3 bucket ARN | | secret_access_key | The secret access key. This will be written to the state file in plain-text | | user_arn | The ARN assigned by AWS for the user | | user_enabled | Is user creation enabled | diff --git a/main.tf b/main.tf index 48cdb879..74a2bac6 100644 --- a/main.tf +++ b/main.tf @@ -46,3 +46,50 @@ module "s3_user" { s3_actions = ["${var.allowed_bucket_actions}"] s3_resources = ["${join("", aws_s3_bucket.default.*.arn)}/*", "${join("", aws_s3_bucket.default.*.arn)}"] } + +data "aws_iam_policy_document" "bucket_policy" { + count = "${var.enabled == "true" && var.allow_encrypted_uploads_only == "true" ? 1 : 0}" + + statement { + sid = "DenyIncorrectEncryptionHeader" + effect = "Deny" + actions = ["s3:PutObject"] + resources = ["arn:aws:s3:::${aws_s3_bucket.default.id}/*"] + + principals { + identifiers = ["*"] + type = "*" + } + + condition { + test = "StringNotEquals" + values = ["${var.sse_algorithm}"] + variable = "s3:x-amz-server-side-encryption" + } + } + + statement { + sid = "DenyUnEncryptedObjectUploads" + effect = "Deny" + actions = ["s3:PutObject"] + resources = ["arn:aws:s3:::${aws_s3_bucket.default.id}/*"] + + principals { + identifiers = ["*"] + type = "*" + } + + condition { + test = "Null" + values = ["true"] + variable = "s3:x-amz-server-side-encryption" + } + } +} + +resource "aws_s3_bucket_policy" "default" { + count = "${var.enabled == "true" && var.allow_encrypted_uploads_only == "true" ? 1 : 0}" + bucket = "${join("", aws_s3_bucket.default.*.id)}" + + policy = "${join("", data.aws_iam_policy_document.bucket_policy.*.json)}" +} diff --git a/outputs.tf b/outputs.tf index 27154bdc..ef818c80 100644 --- a/outputs.tf +++ b/outputs.tf @@ -49,8 +49,3 @@ output "secret_access_key" { value = "${module.s3_user.secret_access_key}" description = "The secret access key. This will be written to the state file in plain-text" } - -output "s3_bucket_arn" { - value = "${join("", aws_s3_bucket.default.*.arn)}" - description = "S3 bucket ARN" -} diff --git a/variables.tf b/variables.tf index 254fff09..958b0f8e 100644 --- a/variables.tf +++ b/variables.tf @@ -90,3 +90,9 @@ variable "allowed_bucket_actions" { default = ["s3:PutObject", "s3:PutObjectAcl", "s3:GetObject", "s3:DeleteObject", "s3:ListBucket", "s3:ListBucketMultipartUploads", "s3:GetBucketLocation", "s3:AbortMultipartUpload"] description = "List of actions the user is permitted to perform on the S3 bucket" } + +variable "allow_encrypted_uploads_only" { + type = "string" + default = "false" + description = "Set to `true` to prevent uploads of unencrypted objects to S3 bucket" +}