|
| 1 | +locals { |
| 2 | + remote_workspace = var.workspace != null ? var.workspace : local.workspace |
| 3 | + ds_backend = contains(["remote", "s3"], local.backend_type) ? local.backend_type : "local" |
| 4 | + ds_workspace = local.ds_backend == "local" ? null : local.remote_workspace |
| 5 | + |
| 6 | + ds_configurations = { |
| 7 | + local = { |
| 8 | + path = "${path.module}/dummy-remote-state.json" |
| 9 | + } |
| 10 | + |
| 11 | + remote = local.ds_backend == "remote" ? { |
| 12 | + organization = local.backend.organization |
| 13 | + |
| 14 | + workspaces = { |
| 15 | + name = local.remote_workspace |
| 16 | + } |
| 17 | + } : null |
| 18 | + |
| 19 | + s3 = local.ds_backend == "s3" ? { |
| 20 | + encrypt = local.backend.encrypt |
| 21 | + bucket = local.backend.bucket |
| 22 | + key = local.backend.key |
| 23 | + dynamodb_table = local.backend.dynamodb_table |
| 24 | + region = local.backend.region |
| 25 | + |
| 26 | + # NOTE: component types |
| 27 | + # Privileged components are those that require elevated (root-level) permissions to provision and access their remote state. |
| 28 | + # For example: `tfstate-backend`, `account`, `account-map`, `account-settings`, `iam-primary`. |
| 29 | + # Privileged components are usually provisioned during cold-start (when we don't have any IAM roles provisioned yet) by using an admin user credentials. |
| 30 | + # 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. |
| 31 | + # 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). |
| 32 | + # For example: `vpc`, `eks`, `rds` |
| 33 | + |
| 34 | + # NOTE: global `backend` config |
| 35 | + # The global `backend` config should be declared in a global YAML stack config file (e.g. `globals.yaml`) |
| 36 | + # 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). |
| 37 | + # The global `backend` config in the global config file should always have the `role_arn` or `profile` specified (added after the cold-start). |
| 38 | + |
| 39 | + # NOTE: components `backend` config |
| 40 | + # The `backend` portion for each individual component should be declared in a catalog file (e.g. `stacks/catalog/<component>.yaml`) |
| 41 | + # along with all the default values for a component. |
| 42 | + # The `privileged` attribute should always be declared in the `backend` portion for each individual component in the catalog. |
| 43 | + # 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 values. |
| 44 | + |
| 45 | + # NOTE: `cold-start` |
| 46 | + # During cold-start we don't have any IAM roles provisioned yet, so we use an admin user credentials to provision the privileged components. |
| 47 | + # The `privileged` attribute for the privileged components should be set to `true` in the components' catalog, |
| 48 | + # and the privileged components should be provisioned using an admin user credentials. |
| 49 | + |
| 50 | + # NOTE: after `cold-start` |
| 51 | + # After the privileged components (including the primary IAM roles) are provisioned, we update the global `backend` config in the global config file |
| 52 | + # to add the IAM role or profile to access the backend (after this, the global `backend` config should never change). |
| 53 | + # For some privileged components we can change the `privileged` attribute in the YAML config from `true` to `false` |
| 54 | + # to allow the regular components to access their remote state (e.g. we set the `privileged` attribute to `false` in the `account-map` component |
| 55 | + # since we use `account-map` in almost all regular components. |
| 56 | + # For each regular component, set the `privileged` attribute to `false` in the components' portion of `backend` config (in `stacks/catalog/<component>.yaml`) |
| 57 | + |
| 58 | + # Advantages: |
| 59 | + # 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, |
| 60 | + # and after that the global `backend` config never changed. |
| 61 | + # We can make a component privileged or not any time by just updating its `privileged` attribute in the component's catalog file. |
| 62 | + # 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 |
| 63 | + # component, we don't touch the `globals.yaml` file at all, and we don't update the component's `role_arn` and `profile` settings). |
| 64 | + |
| 65 | + # Use the role to access the remote state if the component is not privileged and `role_arn` is specified |
| 66 | + role_arn = !coalesce(try(local.backend.privileged, null), var.privileged) && contains(keys(local.backend), "role_arn") ? local.backend.role_arn : null |
| 67 | + |
| 68 | + # Use the profile to access the remote state if the component is not privileged and `profile` is specified |
| 69 | + profile = !coalesce(try(local.backend.privileged, null), var.privileged) && contains(keys(local.backend), "profile") ? local.backend.profile : null |
| 70 | + |
| 71 | + workspace_key_prefix = local.workspace_key_prefix |
| 72 | + } : null |
| 73 | + } # ds_configurations |
| 74 | + |
| 75 | + |
| 76 | +} |
| 77 | + |
| 78 | +# Due to issues like |
| 79 | +# - https://github.com/hashicorp/terraform/issues/32023 |
| 80 | +# - https://github.com/hashicorp/terraform/issues/27849 |
| 81 | +# we want to avoid using `count` to enable or disable the data source, |
| 82 | +# so instead we use a dummy remote state (a local file) when otherwise |
| 83 | +# we would disable the data source via `count = 0`. |
| 84 | +data "terraform_remote_state" "data_source" { |
| 85 | + backend = local.ds_backend |
| 86 | + workspace = local.ds_workspace |
| 87 | + config = local.ds_configurations[local.ds_backend] |
| 88 | + defaults = var.defaults |
| 89 | +} |
0 commit comments