Skip to content

Commit b6ad1d7

Browse files
authored
restrictive block on public access (#5)
* add release badges * test example, to get public block working * improve variable name, document how to customize it * guidance on max retention * more README and doc polish
1 parent bb33cbc commit b6ad1d7

File tree

8 files changed

+140
-17
lines changed

8 files changed

+140
-17
lines changed

.github/workflows/terraform_integration.yaml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323
EXAMPLE_TENANT_SA_ID: '104184075060961394622'
2424
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2525
AWS_REGION: 'us-west-2'
26+
AWS_ACCOUNT_ID: '626567183302'
2627
steps:
2728
- name: Get timestamp
2829
id: timestamp
@@ -58,7 +59,10 @@ jobs:
5859
working-directory: examples/basic
5960
run: |
6061
terraform init
61-
terraform apply -var="resource_name_prefix=tf_aws_w8s_export_ci_${{ env.timestamp}}" -var="worklytics_tenant_id=${{ env.EXAMPLE_TENANT_SA_ID }}" -auto-approve
62+
terraform apply -auto-approve \
63+
-var="aws_account_id=${{ env.AWS_ACCOUNT_ID }}" \
64+
-var="resource_name_prefix=tf_aws_w8s_export_ci_${{ env.timestamp}}" \
65+
-var="worklytics_tenant_id=${{ env.EXAMPLE_TENANT_SA_ID }}"
6266
echo "worklytics_export_bucket_id=$(terraform output -raw worklytics_export_bucket_id)" >> $GITHUB_OUTPUT
6367
echo "worklytics_tenant_aws_role_arn=$(terraform output -raw worklytics_tenant_aws_role_arn)" >> $GITHUB_OUTPUT
6468
@@ -71,4 +75,7 @@ jobs:
7175
working-directory: examples/basic
7276
run: |
7377
aws s3 rm s3://${{ steps.terraform_apply.outputs.worklytics_export_bucket_id }} --recursive
74-
terraform destroy -auto-approve -var="worklytics_tenant_id=${{ env.EXAMPLE_TENANT_SA_ID }}"
78+
terraform destroy -auto-approve \
79+
-var="aws_account_id=${{ env.AWS_ACCOUNT_ID }}" \
80+
-var="worklytics_tenant_id=${{ env.EXAMPLE_TENANT_SA_ID }}" \
81+
-var="resource_name_prefix=tf_aws_w8s_export_ci_${{ env.timestamp}}"

README.md

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
# Worklytics Export to AWS Terraform Module
22

3+
[![Latest Release](https://img.shields.io/github/v/release/Worklytics/terraform-aws-worklytics-export)](https://github.com/Worklytics/terraform-aws-worklytics-export/releases/latest)
4+
![tests](https://img.shields.io/github/actions/workflow/status/Worklytics/terraform-aws-worklytics-export/terraform_integration.yaml?label=tests)
5+
36
This module creates infra to support exporting data from Worklytics to AWS.
47

58
It is published in the Terraform Registry at:
69
https://registry.terraform.io/modules/Worklytics/worklytics-export/aws/latest
710

811
## Usage
912

10-
from Terraform registry: (pending release)
13+
from Terraform registry:
1114
```hcl
1215
module "worklytics-export" {
1316
source = "terraform-aws-worklytics-export"
14-
version = "~> 0.1.0"
17+
version = "~> 0.2.0"
1518
1619
# numeric ID of your Worklytics Tenant SA
1720
worklytics_tenant_id = "123123123123"
@@ -21,7 +24,7 @@ module "worklytics-export" {
2124
via GitHub:
2225
```hcl
2326
module "worklytics-export" {
24-
source = "git::https://github.com/worklytics/terraform-aws-worklytics-export/?ref=v0.1.0"
27+
source = "git::https://github.com/worklytics/terraform-aws-worklytics-export/?ref=v0.2.0"
2528
2629
# numeric ID of your Worklytics Tenant SA
2730
worklytics_tenant_id = "123123123123"
@@ -33,6 +36,10 @@ module "worklytics-export" {
3336
#### `worklytics_export_bucket`
3437
The Terraform resource created as the export bucket. See [`aws_s3_bucket`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) for details.
3538

39+
This is useful to compose with the other `aws_s3_bucket_*` resources to configure retention, encryption, etc. See:
40+
- [aws_s3_bucket_lifecycle_configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration)
41+
- [aws_s3_bucket_service_side_encryption_configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration)
42+
3643
#### `worklytics_tenant_aws_role`
3744
The IAM role that your Worklytics Tenant will assume before operating on your AWS infrastructure.
3845

@@ -46,11 +53,10 @@ for general idea; this is the reverse direction of that (GCP --> AWS, rather tha
4653
This value is useful for a few scenarios:
4754
- if you set a CMEK to encrypt the bucket rather than relying on AWS default, you may need to
4855
grant encrypt / data key creation permissions to this role.
49-
- if you additional IAM policies set on this account which would *deny* the permissions needed by
50-
this role for S3/etc, you'll have to use this role's ARN to add exceptions to those policies
56+
- if your AWS account has additional IAM policies which would *deny* the permissions needed by
57+
this role for S3/etc, use this role's ARN to add exceptions to those policies
5158
(in AWS IAM logic, explicit deny has precedence over explicit allow)
5259

53-
5460
## Compatibility
5561

5662
This module is meant for use with Terraform 1.0+. If you find incompatibilities using Terraform >=
@@ -66,11 +72,54 @@ If you wish to export Worklytics data to an existing bucket, use a Terraform imp
6672
terraform import module.worklytics_export.aws_s3_bucket.worklytics_export <bucket_name>
6773
```
6874

75+
### Customize Public Access Block
76+
By default, we set a restrictive public access block on the bucket. If you need something more
77+
permissive, you can disable the default block by setting the variable `enable_aws_s3_bucket_public_access_block=false`
78+
in your `terraform.tfvars` file and then add your own public access block as follows:
79+
80+
```tf
81+
resource "aws_s3_bucket_public_access_block" "worklytics_export" {
82+
bucket = module.worklytics_export.worklytics_export_bucket.id
83+
84+
block_public_acls = true
85+
block_public_policy = true
86+
ignore_public_acls = true
87+
restrict_public_buckets = true
88+
}
89+
```
90+
91+
### Add a Max Retention Policy
92+
93+
It's good practice to have a max retention policy on your bucket, even if it's really long. If you
94+
have a data pipeline regularly moving data from this bucket into your data warehouse, a value of 30
95+
or 60 days can likely lower your storage costs and reduce risk of having data in more places than it
96+
needs to be.
97+
98+
```tf
99+
resource "aws_s3_bucket_lifecycle_configuration" "worklytics_export" {
100+
bucket = module.worklytics_export.worklytics_export_bucket.id
101+
102+
rule {
103+
id = "max_retention_5_years"
104+
enabled = true
105+
106+
expiration {
107+
days = 5*365 # 5 years
108+
}
109+
}
110+
}
111+
112+
```
113+
69114
## Development
70115

71116
This module is written and maintained by [Worklytics, Co.](https://worklytics.co/) and intended to
72117
guide our customers in setting up their own infra to export data from Worklytics to AWS.
73118

74-
Our intent is that this will be [published as a Terraform module](https://developer.hashicorp.com/terraform/registry/modules/publish), so will follow [standard Terraform
75-
module structure](https://developer.hashicorp.com/terraform/language/modules/develop/structure).
119+
As this is [published as a Terraform module](https://developer.hashicorp.com/terraform/registry/modules/publish),
120+
we will strive to follow [standard Terraform module structure](https://developer.hashicorp.com/terraform/language/modules/develop/structure)
121+
and [style conventions](https://developer.hashicorp.com/terraform/language/syntax/style).
122+
123+
See [examples/basic/](examples/basic/) for a simple example of how to use this module.
124+
76125

examples/basic-remote/main.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ terraform {
66
}
77
}
88

9-
module "worklytics-export" {
9+
module "worklytics_export" {
1010
source = "terraform-aws-worklytics-export"
11-
version = "~> 0.1.0"
11+
version = "~> 0.2.0"
1212

1313
resource_name_prefix = var.resource_name_prefix
1414
worklytics_tenant_id = var.worklytics_tenant_id

examples/basic/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Basic Worklytics Export to S3 Example
2+
3+
We don't recommend *direct* use of this example, but rather use it as a reference for how to add
4+
the Worklytics Export module to your own Terraform configuration or as a working example when
5+
developing the module itself.
6+
7+
8+
## Usage for Development
9+
10+
Within `examples/basic/` (eg, here), create a `terraform.tfvars` file with the following content,
11+
customizing AWS account id and role name as needed.
12+
13+
```hcl
14+
worklytics_tenant_id = null # "123456712345671234567"
15+
aws_account_id = "626567183302" # our CI account!! use your own!
16+
aws_role_name = "Admin"
17+
```
18+
19+
Then test the example:
20+
21+
```shell
22+
terraform init
23+
terraform apply
24+
```

examples/basic/example_variables.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# variables needed by the example
2+
3+
variable "aws_account_id" {
4+
type = string
5+
description = "AWS account in which to provision. Required to be explicitly specified, to reduce chance of inadvertently provisioning in the wrong account."
6+
}
7+
8+
variable "aws_role_name" {
9+
type = string
10+
description = "The name of the role to assume within AWS account. `null` if already auth'd as desired role/user."
11+
default = null
12+
}

examples/basic/main.tf

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@ terraform {
88
}
99
}
1010

11+
# provider just for example purposes; in real use, you likely already have an AWS provider block
12+
# in your terraform configuration
13+
provider "aws" {
14+
15+
assume_role {
16+
role_arn = var.aws_role_name == null ? null : "arn:aws:iam::${var.aws_account_id}:role/${var.aws_role_name}"
17+
}
18+
19+
allowed_account_ids = [
20+
var.aws_account_id
21+
]
22+
}
23+
24+
1125

1226
module "worklytics_export" {
1327
source = "../../"
@@ -23,3 +37,5 @@ output "worklytics_export_bucket_id" {
2337
output "worklytics_tenant_aws_role_arn" {
2438
value = module.worklytics_export.worklytics_tenant_aws_role.arn
2539
}
40+
41+

main.tf

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ resource "aws_iam_role" "for_worklytics_tenant" {
4444
})
4545
}
4646

47-
4847
resource "aws_s3_bucket" "worklytics_export" {
48+
4949
bucket_prefix = replace(lower(var.resource_name_prefix), "_", "-")
5050

5151
lifecycle {
@@ -56,11 +56,20 @@ resource "aws_s3_bucket" "worklytics_export" {
5656
}
5757
}
5858

59-
resource "aws_s3_bucket_acl" "worklytics_export_private" {
59+
# you can use `aws_s3_bucket_public_access_block` to disable this, as these defaults are extreme.
60+
# if you do, we recommend setting something similar outside this module
61+
resource "aws_s3_bucket_public_access_block" "worklytics_export" {
62+
count = var.enable_aws_s3_bucket_public_access_block ? 1 : 0
63+
6064
bucket = aws_s3_bucket.worklytics_export.id
61-
acl = "private"
65+
66+
block_public_acls = true
67+
block_public_policy = true
68+
ignore_public_acls = true
69+
restrict_public_buckets = true
6270
}
6371

72+
6473
# TODO if key, need perm to "kms:GenerateDataKey" and "kms:Decrypt" ??
6574
# q - do we leave that to customer, or support it natively since pretty common case??
6675

variables.tf

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
21
variable "resource_name_prefix" {
32
type = string
4-
description = "Prefix to give to names of infra created by this module, where appicable."
3+
description = "Prefix to give to names of infra created by this module, where applicable."
54
default = "worklytics-export-"
65
}
76

@@ -14,3 +13,10 @@ variable "worklytics_tenant_id" {
1413
error_message = "`worklytics_tenant_id` must be a 21-digit numeric value. (or `null`, for pre-production use case where you don't want external entity to be allowed to assume the role)."
1514
}
1615
}
16+
17+
variable "enable_aws_s3_bucket_public_access_block" {
18+
type = bool
19+
description = "Whether to place restrictive `aws_s3_bucket_public_access_block` on S3 bucket. Set to `false` if you wish to configure something equivalent outside this module."
20+
default = true
21+
}
22+

0 commit comments

Comments
 (0)