Skip to content

Commit bb9767a

Browse files
Add backend.privileged attribute to the backend config in YAML stack config (#30)
* Add `backend.privileged` attribute to the `backend` config in YAML stack config * Add `backend.privileged` attribute to the `backend` config in YAML stack config * Auto Format * Add `backend.privileged` attribute to the `backend` config in YAML stack config * Auto Format * Add `backend.privileged` attribute to the `backend` config in YAML stack config Co-authored-by: cloudpossebot <11232728+cloudpossebot@users.noreply.github.com>
1 parent 02bdc65 commit bb9767a

9 files changed

Lines changed: 61 additions & 18 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,13 @@ Available targets:
347347
| <a name="requirement_external"></a> [external](#requirement\_external) | >= 2.0 |
348348
| <a name="requirement_local"></a> [local](#requirement\_local) | >= 1.3 |
349349
| <a name="requirement_template"></a> [template](#requirement\_template) | >= 2.2 |
350-
| <a name="requirement_utils"></a> [utils](#requirement\_utils) | >= 0.8.0 |
350+
| <a name="requirement_utils"></a> [utils](#requirement\_utils) | >= 0.11.0 |
351351

352352
## Providers
353353

354354
| Name | Version |
355355
|------|---------|
356-
| <a name="provider_utils"></a> [utils](#provider\_utils) | >= 0.8.0 |
356+
| <a name="provider_utils"></a> [utils](#provider\_utils) | >= 0.11.0 |
357357

358358
## Modules
359359

docs/terraform.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
| <a name="requirement_external"></a> [external](#requirement\_external) | >= 2.0 |
88
| <a name="requirement_local"></a> [local](#requirement\_local) | >= 1.3 |
99
| <a name="requirement_template"></a> [template](#requirement\_template) | >= 2.2 |
10-
| <a name="requirement_utils"></a> [utils](#requirement\_utils) | >= 0.8.0 |
10+
| <a name="requirement_utils"></a> [utils](#requirement\_utils) | >= 0.11.0 |
1111

1212
## Providers
1313

1414
| Name | Version |
1515
|------|---------|
16-
| <a name="provider_utils"></a> [utils](#provider\_utils) | >= 0.8.0 |
16+
| <a name="provider_utils"></a> [utils](#provider\_utils) | >= 0.11.0 |
1717

1818
## Modules
1919

examples/complete/versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ terraform {
1616
}
1717
utils = {
1818
source = "cloudposse/utils"
19-
version = ">= 0.8.0"
19+
version = ">= 0.11.0"
2020
}
2121
}
2222
}

examples/remote-state/versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ terraform {
1616
}
1717
utils = {
1818
source = "cloudposse/utils"
19-
version = ">= 0.8.0"
19+
version = ">= 0.11.0"
2020
}
2121
}
2222
}

examples/spacelift/versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ terraform {
1616
}
1717
utils = {
1818
source = "cloudposse/utils"
19-
version = ">= 0.8.0"
19+
version = ">= 0.11.0"
2020
}
2121
}
2222
}

examples/stacks/versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ terraform {
1616
}
1717
utils = {
1818
source = "cloudposse/utils"
19-
version = ">= 0.8.0"
19+
version = ">= 0.11.0"
2020
}
2121
}
2222
}

modules/remote-state/s3.tf

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,57 @@ data "terraform_remote_state" "s3" {
1414
workspace = local.s3_workspace
1515

1616
config = {
17-
encrypt = local.backend.encrypt
18-
bucket = local.backend.bucket
19-
key = local.backend.key
20-
dynamodb_table = local.backend.dynamodb_table
21-
region = local.backend.region
22-
role_arn = var.privileged || ! contains(keys(local.backend), "role_arn") ? null : local.backend.role_arn
23-
profile = var.privileged || ! contains(keys(local.backend), "profile") ? null : local.backend.profile
17+
encrypt = local.backend.encrypt
18+
bucket = local.backend.bucket
19+
key = local.backend.key
20+
dynamodb_table = local.backend.dynamodb_table
21+
region = local.backend.region
22+
23+
# NOTE: component types
24+
# Privileged components are those that require elevated (root-level) permissions to provision and access their remote state.
25+
# For example: `tfstate-backend`, `account`, `account-map`, `account-settings`, `iam-primary`.
26+
# Privileged components are usually provisioned during cold-start (when we don't have any IAM roles provisioned yet) by using an admin user credentials.
27+
# To access the remote state of privileged components, the caller needs to have permissions to access the backend and the remote state without assuming roles.
28+
# Regular components, on the other hand, don't require root-level permissions and are provisioned and their remote state is accessed by assuming IAM roles (or using profiles).
29+
# For example: `vpc`, `eks`, `rds`
30+
31+
# NOTE: global `backend` config
32+
# The global `backend` config should be declared in a global YAML stack config file (e.g. `globals.yaml`)
33+
# where all stacks can import it and have access to it (note that the global `backend` config is organization-wide and will not change after cold-start).
34+
# The global `backend` config in the global config file should always have the `role_arn` or `profile` specified (added after the cold-start).
35+
36+
# NOTE: components `backend` config
37+
# The `backend` portion for each individual component should be declared in a catalog file (e.g. `stacks/catalog/<component>.yaml`)
38+
# along with all the default values for a component.
39+
# The `privileged` attribute should always be declared in the `backend` portion for each individual component in the catalog.
40+
# Top-level stacks where a component is provisioned import the component's catalog (the default values and the component's backend config portion) and can override the default value.
41+
42+
# NOTE: `cold-start`
43+
# During cold-start we don't have any IAM roles provisioned yet, so we use an admin user credentials to provision the privileged components.
44+
# The `privileged` attribute for the privileged components should be set to `true` in the components' catalog,
45+
# and the privileged components should be provisioned using an admin user credentials.
46+
47+
# NOTE: after `cold-start`
48+
# After the privileged components (including the primary IAM roles) are provisioned, we update the global `backend` config in the global config file
49+
# to add the IAM role or profile to access the backend (after this, the global `backend` config should never change).
50+
# For some privileged components we can change the `privileged` attribute in the YAML config from `true` to `false`
51+
# to allow the regular components to access their remote state (e.g. we set the `privileged` attribute to `false` in the `account-map` component
52+
# since we use `account-map` in almost all regular components.
53+
# For each regular component, set the `privileged` attribute to `false` in the components' portion of `backend` config (in `stacks/catalog/<component>.yaml`)
54+
55+
# Advantages:
56+
# The global `backend` config is specified just once in the global config file, IAM role or profile is added to it after the cold start,
57+
# and after that the global `backend` config never changed.
58+
# We can make a component privileged or not any time by just updating its `privileged` attribute in the component's catalog file.
59+
# We can change a component's `backend` portion any time without touching/affection the backend configs of all other components (e.g. when we add a new
60+
# component, we don't touch the `globals.yaml` file at all, and we don't update the component's `role_arn` and `profile` settings).
61+
62+
# Use the role to access the remote state if the component is not privileged and `role_arn` is specified
63+
role_arn = ! coalesce(try(local.backend.privileged, null), var.privileged) && contains(keys(local.backend), "role_arn") ? local.backend.role_arn : null
64+
65+
# Use the profile to access the remote state if the component is not privileged and `profile` is specified
66+
profile = ! coalesce(try(local.backend.privileged, null), var.privileged) && contains(keys(local.backend), "profile") ? local.backend.profile : null
67+
2468
workspace_key_prefix = coalesce(local.base_component, var.component)
2569
}
2670

test/src/examples_spacelift_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,5 @@ func TestExamplesSpacelift(t *testing.T) {
6060
assert.Equal(t, "deps:stacks/uw2-dev.yaml", uw2DevAuroraPostgres2StackLabels[4])
6161
assert.Equal(t, "deps:stacks/uw2-globals.yaml", uw2DevAuroraPostgres2StackLabels[5])
6262
assert.Equal(t, "folder:component/aurora-postgres-2", uw2DevAuroraPostgres2StackLabels[6])
63-
assert.Equal(t, "folder:uw2", uw2DevAuroraPostgres2StackLabels[7])
64-
assert.Equal(t, "folder:uw2/dev", uw2DevAuroraPostgres2StackLabels[8])
63+
assert.Equal(t, "folder:uw2/dev", uw2DevAuroraPostgres2StackLabels[7])
6564
}

versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ terraform {
1616
}
1717
utils = {
1818
source = "cloudposse/utils"
19-
version = ">= 0.8.0"
19+
version = ">= 0.11.0"
2020
}
2121
}
2222
}

0 commit comments

Comments
 (0)