Skip to content

Commit

Permalink
Merge pull request #20 from mineiros-io/mariux/add-oai-support
Browse files Browse the repository at this point in the history
Add support for Origin Aceess Identity Access from Cloudfront
  • Loading branch information
soerenmartius authored Feb 29, 2020
2 parents 65e7b5b + 5d5c5e7 commit 113a246
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 12 deletions.
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ of the bucket enforcing `bucket-owner-full-control` acl for objects created by o
Bucket Public Access Blocking

- **Additional Features**:
Cross-Account access policy with forced `bucket-owner-full-control` ACL for direct access
Cross-Account access policy with forced `bucket-owner-full-control` ACL for direct access,
Cloudfront Origin Access Identity (OAI) and policy

- *Features not yet implemented*:
Replication Configuration,
Expand All @@ -60,7 +61,7 @@ of the bucket enforcing `bucket-owner-full-control` acl for objects created by o
Bucket Metrics,
Bucket Inventory,
S3 Access Points (not yet supported by terraform aws provider),
Cloudfront Origin Access Identity (OAI) policy,
Origin Access Identity Access (OAI) for already existing OAIs,
Generate Cross-Account role for OAI enabled buckets if desired,
Generate KMS key to encrypt objects at rest if desired

Expand Down Expand Up @@ -192,6 +193,15 @@ Default is `["s3:PutObject", "s3:PutObjectAcl"]`.
Specifies ACLs to force on new objects for cross account access.
Default is `["bucket-owner-full-control"]`.

##### Cloudfront Origin Access Identity Access
- **`create_origin_access_identity`**: *(Optional `bool`)*
Specifies whether to create and origin access identity and grant it access to read
from the bucket. This can be used to grant a cloudfront distribution access to
bucket objects when specifying this bucket as an origin. **Attention:** Objects shared that way need
to be owned by the account the bucket belongs to and can not be owned be other accounts
(e.g. when uploaded through cross-account-access).
Default is `false` (disabled).

#### [`cors_rule`](#bucket-configuration) Object Attributes
- **`allowed_headers`**: *(Optional `list(string)`)*
Specifies which headers are allowed.
Expand Down Expand Up @@ -308,15 +318,22 @@ Can be `ONEZONE_IA`, `STANDARD_IA`, `INTELLIGENT_TIERING`, `GLACIER`, or `DEEP_A
The following attributes are exported by the module:

- **`bucket`**: All bucket attributes as returned by the
[`aws_s3_bucket` resource](https://www.terraform.io/docs/providers/aws/r/s3_bucket.html#attributes-reference)
[`aws_s3_bucket`](https://www.terraform.io/docs/providers/aws/r/s3_bucket.html#attributes-reference) resource
containing all arguments as specified above and the other attributes as specified below.
- **`id`**: The name of the bucket.
- **`arn`**: The ARN of the bucket. Will be of format `arn:aws:s3:::bucketname`.
- **`bucket_domain_name`**: The bucket domain name. Will be of format bucketname.s3.amazonaws.com.
- **`bucket_regional_domain_name`**: The bucket region-specific domain name. The bucket domain name including the region name, please refer here for format. Note: The AWS CloudFront allows specifying S3 region-specific endpoint when creating S3 origin, it will prevent redirect issues from CloudFront to S3 Origin URL.
- **`bucket_regional_domain_name`**: The bucket region-specific domain name.
The bucket domain name including the region name, please refer here for format.
Note: The AWS CloudFront allows specifying S3 region-specific endpoint when creating S3 origin,
it will prevent redirect issues from CloudFront to S3 Origin URL.
- **`bucket_policy`**: All bucket policy object attributes as returned by the
[`s3_bucket_policy`](https://www.terraform.io/docs/providers/aws/r/s3_bucket_policy.html#argument-reference) resource.
- **`hosted_zone_id`**: The Route 53 Hosted Zone ID for this bucket's region.
- **`region`**: The AWS region this bucket resides in.
- **`create`**: The `create` argument.
- **`origin_access_identity`**: All cloudfront origin access identity object attributes as returned by the
[`aws_cloudfront_origin_access_identity`](https://www.terraform.io/docs/providers/aws/r/cloudfront_origin_access_identity.html#attribute-reference) resource.

## Module Versioning
This Module follows the principles of [Semantic Versioning (SemVer)](https://semver.org/).
Expand Down
2 changes: 2 additions & 0 deletions examples/secure-s3-bucket/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ module "example-app-bucket" {
target_prefix = "log/"
}

create_origin_access_identity = true

cors_rule = {
allowed_headers = ["*"]
allowed_methods = ["PUT", "POST"]
Expand Down
45 changes: 37 additions & 8 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,17 @@ locals {
bucket_id = join("", aws_s3_bucket.bucket.*.id)
bucket_arn = join("", aws_s3_bucket.bucket.*.arn)

cross_account_bucket_actions_enabled = length(var.cross_account_bucket_actions) > 0
cross_account_object_actions_enabled = length(var.cross_account_object_actions) > 0
cross_account_object_actions_with_forced_acl_enabled = length(var.cross_account_object_actions_with_forced_acl) > 0
cross_account_enabled = length(var.cross_account_identifiers) > 0

cross_account_bucket_actions_enabled = local.cross_account_enabled && length(var.cross_account_bucket_actions) > 0
cross_account_object_actions_enabled = local.cross_account_enabled && length(var.cross_account_object_actions) > 0
cross_account_object_actions_with_forced_acl_enabled = local.cross_account_enabled && length(var.cross_account_object_actions_with_forced_acl) > 0

cross_account_actions_enabled = local.cross_account_bucket_actions_enabled || local.cross_account_object_actions_enabled || local.cross_account_object_actions_with_forced_acl_enabled

cross_account_enabled = length(var.cross_account_identifiers) > 0 && local.cross_account_actions_enabled
origin_access_identities_enabled = var.create && var.create_origin_access_identity

policy_enabled = var.create && (var.policy != null || local.cross_account_enabled)
policy_enabled = var.create && (var.policy != null || local.cross_account_actions_enabled || local.origin_access_identities_enabled)
}

# ---------------------------------------------------------------------------------------------------------------------
Expand All @@ -178,6 +180,7 @@ resource "aws_s3_bucket_public_access_block" "bucket" {
# Attach a Policy to the S3 Bucket to control:
# - Cross account bucket actions
# - Cross account object actions
# - Cloudfront origin access identity access
# ---------------------------------------------------------------------------------------------------------------------

resource "aws_s3_bucket_policy" "bucket" {
Expand All @@ -197,7 +200,7 @@ data "aws_iam_policy_document" "bucket" {
source_json = var.policy

dynamic "statement" {
for_each = length(var.cross_account_bucket_actions) == 0 ? [] : [1]
for_each = local.cross_account_bucket_actions_enabled ? [1] : []

content {
actions = var.cross_account_bucket_actions
Expand All @@ -211,7 +214,7 @@ data "aws_iam_policy_document" "bucket" {
}

dynamic "statement" {
for_each = length(var.cross_account_object_actions) == 0 ? [] : [1]
for_each = local.cross_account_object_actions_enabled ? [1] : []

content {
actions = var.cross_account_object_actions
Expand All @@ -225,7 +228,7 @@ data "aws_iam_policy_document" "bucket" {
}

dynamic "statement" {
for_each = length(var.cross_account_object_actions_with_forced_acl) == 0 ? [] : [1]
for_each = local.cross_account_object_actions_with_forced_acl_enabled ? [1] : []

content {
actions = var.cross_account_object_actions_with_forced_acl
Expand All @@ -247,4 +250,30 @@ data "aws_iam_policy_document" "bucket" {
}
}
}

dynamic "statement" {
for_each = local.origin_access_identities_enabled ? [{
actions = ["s3:GetObject"]
resources = ["${local.bucket_arn}/*"]
}, {
actions = ["s3:ListBucket"]
resources = [local.bucket_arn]

}] : []
content {
actions = statement.value.actions
resources = statement.value.resources

principals {
type = "AWS"
identifiers = aws_cloudfront_origin_access_identity.oai.*.iam_arn
}
}
}
}

resource "aws_cloudfront_origin_access_identity" "oai" {
count = local.origin_access_identities_enabled ? 1 : 0

comment = format("%s S3 buckets Origin Access Identity to be accessed from CloudFront", local.bucket_id)
}
10 changes: 10 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ output "bucket" {
value = try(aws_s3_bucket.bucket[0], {})
}

output "bucket_policy" {
description = "The full bucket object."
value = try(aws_s3_bucket_policy.bucket[0], {})
}

output "id" {
description = "The name of the bucket."
value = join("", aws_s3_bucket.bucket.*.id)
Expand Down Expand Up @@ -37,3 +42,8 @@ output "region" {
description = "The AWS region this bucket resides in."
value = join("", aws_s3_bucket.bucket.*.region)
}

output "origin_access_identity" {
description = "The AWS Cloudfront Origin Access Identity object."
value = try(aws_cloudfront_origin_access_identity.oai[0], {})
}
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,9 @@ variable "cross_account_forced_acls" {
"bucket-owner-full-control"
]
}

variable "create_origin_access_identity" {
type = bool
description = "Whether to create an origin access identity (OAI) and policy to be accessible from Cloudfront."
default = false
}

0 comments on commit 113a246

Please sign in to comment.