Skip to content

Commit a6aa9d2

Browse files
Improve / Fix S3 Bucket Usage (#2760)
* add `random_id` to bucket name * Update documentation * change default force_destroy_bucket * make bucket names configurable and prevent_destroy * remove specifies * remove `force_destroy` flag * add prevent_destroy * add note * update docs * update docs
1 parent e219f12 commit a6aa9d2

File tree

14 files changed

+115
-55
lines changed

14 files changed

+115
-55
lines changed

infrastructure/README.md

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ Follow these steps to set up the infrastructure:
2121
```bash
2222
cd infrastructure/backend/
2323
```
24-
*Note:* Optionally change the region: set `aws_region` in a `.tfvars` file.
24+
25+
**Note:** Optionally change the region: set `aws_region` in a `.tfvars` file.
2526

2627
- Initialize Terraform if needed:
2728
```bash
@@ -33,6 +34,10 @@ Follow these steps to set up the infrastructure:
3334
terraform apply
3435
```
3536

37+
**Note:** Copy the state bucket name from the output.
38+
39+
**Note:** It is recommended to not destroy the backend resources unless absolutely necessary.
40+
3641
2. **Setup Main Infrastructure (staging)**:
3742

3843
- Navigate to the main infrastructure directory. If you are in `infrastructure/backend`, you can use:
@@ -50,13 +55,23 @@ Follow these steps to set up the infrastructure:
5055
cat terraform.tfvars.example > terraform.tfvars
5156
```
5257

53-
- *Note:* Optionally change the region:
54-
- set `aws_region` in a `.tfvars` file.
55-
- set `region` in a `.tfbackend` file and provide it using `terraform init -backend-config=<file>`.
58+
- Create a local backend configuration file:
59+
```bash
60+
touch terraform.tfbackend
61+
```
62+
63+
- Copy the contents from the example file:
64+
```bash
65+
cat terraform.tfbackend.example > terraform.tfbackend
66+
```
67+
68+
*Note:* Update the state bucket name in `terraform.tfbackend` with the name of the state bucket created in the previous step.
69+
70+
*Note:* Update defaults (e.g. `region`) as needed.
5671

5772
- Initialize Terraform with the backend configuration:
5873
```bash
59-
terraform init
74+
terraform init -backend-config=terraform.tfbackend
6075
```
6176

6277
- Apply the changes to create the main infrastructure using the command:
@@ -114,13 +129,15 @@ The Django backend deployment is managed by Zappa. This includes the API Gateway
114129

115130
5. **Deploy**:
116131

117-
- *Note*: Make sure to populate all `DJANGO_*` secrets that are set as `to-be-set-in-aws-console`
132+
- **Note**: Make sure to populate all `DJANGO_*` secrets that are set as `to-be-set-in-aws-console`
118133
in the Parameter Store. The deployment might fail with no logs if secrets such as
119134
`DJANGO_SLACK_BOT_TOKEN` are invalid.
120135

121136
```bash
122137
zappa deploy staging
123138
```
139+
- **Note**: If the deployment is successful but returns a `5xx` error, resolve the issues
140+
and use `zappa undeploy staging` & `zappa deploy staging`. The command `zappa update staging` may not work.
124141

125142
Once deployed, use the URL provided by Zappa to test the API.
126143

@@ -163,7 +180,7 @@ Migrate and load data into the new database.
163180
- Upload the fixture present in `backend/data` to `nest-fixtures` bucket using the following command:
164181

165182
```bash
166-
aws s3 cp data/nest.json.gz s3://nest-fixtures/
183+
aws s3 cp data/nest.json.gz s3://owasp-nest-fixtures-<id>/
167184
```
168185

169186
3. **Run ECS Tasks**:
@@ -188,6 +205,9 @@ Migrate and load data into the new database.
188205
zappa undeploy staging
189206
```
190207

208+
- Ensure all buckets and ECR repositories are empty.
209+
210+
**Note:** Some resources have `prevent_destroy` set to `true`. Please set it to `false` before destruction.
191211
- To destroy Terraform infrastructure:
192212

193213
```bash

infrastructure/backend/.terraform.lock.hcl

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

infrastructure/backend/main.tf

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ terraform {
55
source = "hashicorp/aws"
66
version = "6.22.0"
77
}
8+
random = {
9+
source = "hashicorp/random"
10+
version = "3.7.2"
11+
}
812
}
913
}
1014

@@ -46,6 +50,10 @@ data "aws_iam_policy_document" "state_https_only" {
4650
}
4751
}
4852

53+
resource "random_id" "suffix" {
54+
byte_length = 4
55+
}
56+
4957
resource "aws_dynamodb_table" "state_lock" {
5058
name = "${var.project_name}-terraform-state-lock"
5159
billing_mode = "PAY_PER_REQUEST"
@@ -58,20 +66,32 @@ resource "aws_dynamodb_table" "state_lock" {
5866
name = "LockID"
5967
type = "S"
6068
}
69+
lifecycle {
70+
prevent_destroy = true
71+
}
6172
point_in_time_recovery {
6273
enabled = true
6374
}
6475
}
6576

6677
resource "aws_s3_bucket" "logs" { # NOSONAR
67-
bucket = "${var.project_name}-terraform-state-logs"
78+
bucket = "${var.project_name}-terraform-state-logs-${random_id.suffix.hex}"
79+
80+
lifecycle {
81+
prevent_destroy = true
82+
}
6883
tags = {
6984
Name = "${var.project_name}-terraform-state-logs"
7085
}
7186
}
7287

7388
resource "aws_s3_bucket" "state" { # NOSONAR
74-
bucket = "${var.project_name}-terraform-state"
89+
bucket = "${var.project_name}-terraform-state-${random_id.suffix.hex}"
90+
object_lock_enabled = true
91+
92+
lifecycle {
93+
prevent_destroy = true
94+
}
7595
tags = {
7696
Name = "${var.project_name}-terraform-state"
7797
}
@@ -115,6 +135,17 @@ resource "aws_s3_bucket_logging" "state" {
115135
target_prefix = "s3/"
116136
}
117137

138+
resource "aws_s3_bucket_object_lock_configuration" "state" {
139+
bucket = aws_s3_bucket.state.id
140+
141+
rule {
142+
default_retention {
143+
days = 30
144+
mode = "GOVERNANCE"
145+
}
146+
}
147+
}
148+
118149
resource "aws_s3_bucket_policy" "logs" {
119150
bucket = aws_s3_bucket.logs.id
120151
policy = data.aws_iam_policy_document.logs.json

infrastructure/modules/ecs/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ module "load_data_task" {
217217
set -e
218218
pip install --target=/tmp/awscli-packages awscli
219219
export PYTHONPATH="/tmp/awscli-packages:$PYTHONPATH"
220-
python /tmp/awscli-packages/bin/aws s3 cp s3://${var.fixtures_s3_bucket}/nest.json.gz /tmp/nest.json.gz
220+
python /tmp/awscli-packages/bin/aws s3 cp s3://${var.fixtures_bucket_name}/nest.json.gz /tmp/nest.json.gz
221221
python manage.py load_data --fixture-path /tmp/nest.json.gz
222222
EOT
223223
]

infrastructure/modules/ecs/variables.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ variable "fixtures_read_only_policy_arn" {
3030
type = string
3131
}
3232

33-
variable "fixtures_s3_bucket" {
33+
variable "fixtures_bucket_name" {
3434
description = "The name of the S3 bucket for fixtures"
3535
type = string
3636
}

infrastructure/modules/storage/main.tf

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ terraform {
55
source = "hashicorp/aws"
66
version = "6.22.0"
77
}
8+
random = {
9+
source = "hashicorp/random"
10+
version = "3.7.2"
11+
}
812
}
913
}
1014

@@ -15,16 +19,19 @@ data "aws_iam_policy_document" "fixtures_read_only" {
1519
]
1620
effect = "Allow"
1721
resources = [
18-
"arn:aws:s3:::${var.fixtures_s3_bucket}/*"
22+
"arn:aws:s3:::${var.fixtures_bucket_name}-${random_id.suffix.hex}/*"
1923
]
2024
}
2125
}
2226

27+
resource "random_id" "suffix" {
28+
byte_length = 4
29+
}
30+
2331
module "fixtures_bucket" {
2432
source = "./modules/s3-bucket"
2533

26-
bucket_name = var.fixtures_s3_bucket
27-
force_destroy = var.force_destroy_bucket
34+
bucket_name = "${var.fixtures_bucket_name}-${random_id.suffix.hex}"
2835
tags = merge(var.common_tags, {
2936
Name = "${var.project_name}-${var.environment}-fixtures"
3037
})
@@ -33,8 +40,7 @@ module "fixtures_bucket" {
3340
module "zappa_bucket" {
3441
source = "./modules/s3-bucket"
3542

36-
bucket_name = var.zappa_s3_bucket
37-
force_destroy = var.force_destroy_bucket
43+
bucket_name = "${var.zappa_bucket_name}-${random_id.suffix.hex}"
3844
tags = merge(var.common_tags, {
3945
Name = "${var.project_name}-${var.environment}-zappa-deployments"
4046
})

infrastructure/modules/storage/modules/s3-bucket/main.tf

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ data "aws_iam_policy_document" "this" {
3535
}
3636
}
3737

38-
resource "aws_s3_bucket" "this" { #NOSONAR
39-
bucket = var.bucket_name
40-
force_destroy = var.force_destroy
41-
tags = var.tags
38+
resource "aws_s3_bucket" "this" { # NOSONAR
39+
bucket = var.bucket_name
40+
tags = var.tags
41+
42+
lifecycle {
43+
prevent_destroy = true
44+
}
4245
}
4346

4447
resource "aws_s3_bucket_policy" "this" {

infrastructure/modules/storage/modules/s3-bucket/variables.tf

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
variable "abort_incomplete_multipart_upload_days" {
2-
description = "Specifies the number of days after which an incomplete multipart upload is aborted."
2+
description = "The number of days after which an incomplete multipart upload is aborted."
33
type = number
44
default = 7
55
}
@@ -9,14 +9,8 @@ variable "bucket_name" {
99
type = string
1010
}
1111

12-
variable "force_destroy" {
13-
description = "If true, deletes all objects from the bucket when the bucket is destroyed."
14-
type = bool
15-
default = false
16-
}
17-
1812
variable "noncurrent_version_expiration_days" {
19-
description = "Specifies the number of days an object is noncurrent before it is expired."
13+
description = "The number of days an object is noncurrent before it is expired."
2014
type = number
2115
default = 30
2216
}

infrastructure/modules/storage/variables.tf

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,17 @@ variable "environment" {
99
type = string
1010
}
1111

12-
variable "fixtures_s3_bucket" {
12+
variable "fixtures_bucket_name" {
1313
description = "The name of the S3 bucket for fixtures"
1414
type = string
1515
}
1616

17-
variable "force_destroy_bucket" {
18-
description = "If true, deletes all objects from the bucket when the bucket is destroyed."
19-
type = bool
20-
default = false
21-
}
22-
2317
variable "project_name" {
2418
description = "The name of the project"
2519
type = string
2620
}
2721

28-
variable "zappa_s3_bucket" {
22+
variable "zappa_bucket_name" {
2923
description = "The name of the S3 bucket for Zappa deployments"
3024
type = string
3125
}

infrastructure/staging/backend.tf

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
terraform {
22
backend "s3" {
3-
bucket = "owasp-nest-terraform-state"
4-
dynamodb_table = "owasp-nest-terraform-state-lock"
5-
encrypt = true
6-
key = "staging/terraform.tfstate"
7-
region = "us-east-2"
3+
encrypt = true
4+
key = "staging/terraform.tfstate"
85
}
96
}

0 commit comments

Comments
 (0)