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

Feature/s3 tag policies #193

Merged
merged 7 commits into from
Jun 22, 2021
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [6.9.0] - 2021-06-22
### Added
- Added apiary_consumer_iamroles variable to grant cross account access to IAM roles.
- Added apiary_customer_condition variable to restrict access using S3 object tags.

## [6.8.1] - 2021-06-17
### Added
- Add support for cross account access to s3 inventory.
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ module "apiary" {
}
]
apiary_customer_accounts = ["aws_account_no_1", "aws_account_no_2"]
apiary_customer_condition = <<EOF
"ForAnyValue:StringEquals": {"s3:ExistingObjectTag/security": [ "public"] } ,
"StringLike": {"s3:ExistingObjectTag/type": "image*" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have it as 'OBJECT_TYPE' in my code, but I'll change it to 'type'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

variable is generic, we can use OBJECT_TYPE internally, above is just a example to show usage

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this is in the README, didn't notice...

EOF
ingress_cidr = ["10.0.0.0/8"]
apiary_assume_roles = [
{
Expand Down
2 changes: 2 additions & 0 deletions VARIABLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
|------|-------------|:----:|:-----:|:-----:|
| apiary_assume_roles | List of maps - each map describes an IAM role that can be assumed in this account to write data into the configured list of schemas. See section [`apiary_assume_roles`](#apiary_assume_roles) for more info. | list(map) | - | no |
| apiary_customer_accounts | AWS account IDs for clients of this Metastore. | list | - | no |
| apiary_customer_condition | IAM policy condition applied to customer account s3 access. | string | `` | no |
| apiary_database_name | Database name to create in RDS for Apiary. | string | `apiary` | no |
| apiary_deny_roles | AWS IAM roles denied access to Apiary managed S3 buckets. | list | - | yes |
| apiary_domain_name | Apiary domain name for Route 53. | string | `` | no |
| apiary_log_bucket | Bucket for Apiary logs. | string | - | yes |
| apiary_log_prefix | Prefix for Apiary logs. | string | `` | no |
| apiary_managed_schemas | List of maps - each map entry describes an Apiary schema, along with S3 storage properties for the schema. See section [`apiary_managed_schemas`](#apiary_managed_schemas) for more info. | list(map) | - | no |
| apiary_consumer_iamroles | AWS IAM roles allowed read access to managed Apiary S3 buckets. | map | `<list>` | no |
| apiary_producer_iamroles | AWS IAM roles allowed write access to managed Apiary S3 buckets. | map | `<map>` | no |
| apiary_rds_additional_sg | Comma-separated string containing additional security groups to attach to RDS. | list | `<list>` | no |
| apiary_shared_schemas | Schema names which are accessible from read-only metastore, default is all schemas. | list | `<list>` | no |
Expand Down
2 changes: 2 additions & 0 deletions s3.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ data "template_file" "bucket_policy" {
vars = {
#if apiary_shared_schemas is empty or contains current schema, allow customer accounts to access this bucket.
customer_principal = (length(var.apiary_shared_schemas) == 0 || contains(var.apiary_shared_schemas, each.key)) && each.value["customer_accounts"] != "" ? join("\",\"", formatlist("arn:aws:iam::%s:root", split(",", each.value["customer_accounts"]))) : ""
customer_condition = var.apiary_customer_condition

bucket_name = each.value["data_bucket"]
encryption = each.value["encryption"]
kms_key_arn = each.value["encryption"] == "aws:kms" ? aws_kms_key.apiary_kms[each.key].arn : ""
consumer_iamroles = join("\",\"", var.apiary_consumer_iamroles)
producer_iamroles = replace(lookup(var.apiary_producer_iamroles, each.key, ""), ",", "\",\"")
deny_iamroles = join("\",\"", var.apiary_deny_iamroles)
client_roles = replace(lookup(each.value, "client_roles", ""), ",", "\",\"")
Expand Down
46 changes: 42 additions & 4 deletions templates/apiary-bucket-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,38 @@
"Statement": [
%{if customer_principal != ""}
{
"Sid": "Apiary customer account permissions",
"Sid": "Apiary customer account bucket permissions",
"Effect": "Allow",
"Principal": {
"AWS": [ "${customer_principal}" ]
},
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetBucketAcl",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::${bucket_name}",
"arn:aws:s3:::${bucket_name}"
]
},
%{endif}
%{if customer_principal != ""}
{
"Sid": "Apiary customer account object permissions",
"Effect": "Allow",
"Principal": {
"AWS": [ "${customer_principal}" ]
},
%{if customer_condition != ""}
"Condition": {
${customer_condition}
},
%{endif}
"Action": [
"s3:GetObject",
"s3:GetObjectAcl"
],
"Resource": [
"arn:aws:s3:::${bucket_name}/*"
]
},
Expand All @@ -36,6 +54,26 @@
}
},
%{endif}
%{if consumer_iamroles != ""}
{
"Sid": "Apiary consumer iamrole permissions",
"Effect": "Allow",
"Principal": {
"AWS": [ "${consumer_iamroles}" ]
},
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetBucketAcl",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::${bucket_name}",
"arn:aws:s3:::${bucket_name}/*"
]
},
%{endif}
%{if producer_iamroles != ""}
{
"Sid": "Apiary producer iamrole permissions",
Expand Down
12 changes: 12 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ variable "apiary_customer_accounts" {
default = []
}

variable "apiary_customer_condition" {
description = "IAM policy condition applied to customer account s3 object access."
type = string
default = ""
}

variable "apiary_deny_iamroles" {
description = "AWS IAM roles denied access to Apiary managed S3 buckets."
type = list(string)
Expand All @@ -144,6 +150,12 @@ variable "apiary_assume_roles" {
default = []
}

variable "apiary_consumer_iamroles" {
description = "AWS IAM roles allowed read access to managed Apiary S3 buckets."
type = list(string)
default = []
}

variable "apiary_producer_iamroles" {
description = "AWS IAM roles allowed write access to managed Apiary S3 buckets."
type = map(any)
Expand Down