Fix groups. Fix tests.
This commit is contained in:
parent
053d4151de
commit
840fc86b3e
|
@ -39,7 +39,7 @@ This separation into projects allows adhering to the least-privilege principle b
|
||||||
User groups provide a stable frame of reference that allows decoupling the final set of permissions from the stage where entities and resources are created, and their IAM bindings are defined.
|
User groups provide a stable frame of reference that allows decoupling the final set of permissions from the stage where entities and resources are created, and their IAM bindings are defined.
|
||||||
|
|
||||||
We use three groups to control access to resources:
|
We use three groups to control access to resources:
|
||||||
- `data-engineers`: They handle and run workloads on the `workload` subfolder. They have owner access to all resources in the `workload` folder in order to troubleshoot possible issues with pipelines. This team can also impersonate any service account.
|
- `data-engineers`: They handle and run workloads on the `workload` subfolder. They have editor access to all resources in the `workload` folder in order to troubleshoot possible issues within the workload. This team can also impersonate any service account in the workload folder.
|
||||||
- `data-security`: They handle security configurations for the shielded folder. They have owner access to the `audit-log` and `sec-core` projects.
|
- `data-security`: They handle security configurations for the shielded folder. They have owner access to the `audit-log` and `sec-core` projects.
|
||||||
|
|
||||||
## Encryption
|
## Encryption
|
||||||
|
@ -117,23 +117,23 @@ terraform apply
|
||||||
|
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---:|:---:|:---:|
|
|---|---|:---:|:---:|:---:|
|
||||||
| [organization](variables.tf#L130) | Organization details. | <code title="object({ domain = string id = string })">object({…})</code> | ✓ | |
|
| [organization](variables.tf#L129) | Organization details. | <code title="object({ domain = string id = string })">object({…})</code> | ✓ | |
|
||||||
| [prefix](variables.tf#L138) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | |
|
| [prefix](variables.tf#L137) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | |
|
||||||
| [access_policy](variables.tf#L17) | Access Policy name, set to null if creating one. | <code>string</code> | | <code>null</code> |
|
| [access_policy](variables.tf#L17) | Access Policy name, set to null if creating one. | <code>string</code> | | <code>null</code> |
|
||||||
| [access_policy_create](variables.tf#L23) | Access Policy configuration, fill in to create. Parent is in 'organizations/123456' format. | <code title="object({ parent = string title = string scopes = optional(list(string)) })">object({…})</code> | | <code>null</code> |
|
| [access_policy_create](variables.tf#L23) | Access Policy configuration, fill in to create. Parent is in 'organizations/123456' format. | <code title="object({ parent = string title = string scopes = optional(list(string)) })">object({…})</code> | | <code>null</code> |
|
||||||
| [data_dir](variables.tf#L33) | Relative path for the folder storing configuration data. | <code>string</code> | | <code>"data"</code> |
|
| [data_dir](variables.tf#L33) | Relative path for the folder storing configuration data. | <code>string</code> | | <code>"data"</code> |
|
||||||
| [enable_features](variables.tf#L39) | Flag to enable features on the solution. | <code title="object({ encryption = bool log_sink = bool vpc_sc = bool })">object({…})</code> | | <code title="{ encryption = false log_sink = true vpc_sc = true }">{…}</code> |
|
| [enable_features](variables.tf#L39) | Flag to enable features on the solution. | <code title="object({ encryption = bool log_sink = bool vpc_sc = bool })">object({…})</code> | | <code title="{ encryption = false log_sink = true vpc_sc = true }">{…}</code> |
|
||||||
| [folder_create](variables.tf#L52) | Provide values if folder creation is needed, uses existing folder if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object({ display_name = string parent = string })">object({…})</code> | | <code>null</code> |
|
| [folder_create](variables.tf#L52) | Provide values if folder creation is needed, uses existing folder if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object({ display_name = string parent = string })">object({…})</code> | | <code>null</code> |
|
||||||
| [folder_id](variables.tf#L61) | Folder ID in case you use folder_create=null. | <code>string</code> | | <code>null</code> |
|
| [folder_id](variables.tf#L61) | Folder ID in case you use folder_create=null. | <code>string</code> | | <code>null</code> |
|
||||||
| [groups](variables.tf#L67) | User groups. | <code>map(string)</code> | | <code title="{ data-engineers = "gcp-data-engineers" data-security = "gcp-data-security" }">{…}</code> |
|
| [groups](variables.tf#L67) | User groups. | <code>map(string)</code> | | <code title="{ workload-engineers = "gcp-data-engineers" workload-security = "gcp-data-security" }">{…}</code> |
|
||||||
| [kms_keys](variables.tf#L77) | KMS keys to create, keyed by name. | <code title="map(object({ iam = optional(map(list(string)), {}) labels = optional(map(string), {}) locations = optional(list(string), ["global", "europe", "europe-west1"]) rotation_period = optional(string, "7776000s") }))">map(object({…}))</code> | | <code>{}</code> |
|
| [kms_keys](variables.tf#L76) | KMS keys to create, keyed by name. | <code title="map(object({ iam = optional(map(list(string)), {}) labels = optional(map(string), {}) locations = optional(list(string), ["global", "europe", "europe-west1"]) rotation_period = optional(string, "7776000s") }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [log_locations](variables.tf#L88) | Optional locations for GCS, BigQuery, and logging buckets created here. | <code title="object({ bq = optional(string, "europe") storage = optional(string, "europe") logging = optional(string, "global") pubsub = optional(string, "global") })">object({…})</code> | | <code title="{ bq = "europe" storage = "europe" logging = "global" pubsub = null }">{…}</code> |
|
| [log_locations](variables.tf#L87) | Optional locations for GCS, BigQuery, and logging buckets created here. | <code title="object({ bq = optional(string, "europe") storage = optional(string, "europe") logging = optional(string, "global") pubsub = optional(string, "global") })">object({…})</code> | | <code title="{ bq = "europe" storage = "europe" logging = "global" pubsub = null }">{…}</code> |
|
||||||
| [log_sinks](variables.tf#L105) | Org-level log sinks, in name => {type, filter} format. | <code title="map(object({ filter = string type = string }))">map(object({…}))</code> | | <code title="{ audit-logs = { filter = "logName:\"/logs/cloudaudit.googleapis.com%2Factivity\" OR logName:\"/logs/cloudaudit.googleapis.com%2Fsystem_event\"" type = "bigquery" } vpc-sc = { filter = "protoPayload.metadata.@type=\"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata\"" type = "bigquery" } }">{…}</code> |
|
| [log_sinks](variables.tf#L104) | Org-level log sinks, in name => {type, filter} format. | <code title="map(object({ filter = string type = string }))">map(object({…}))</code> | | <code title="{ audit-logs = { filter = "logName:\"/logs/cloudaudit.googleapis.com%2Factivity\" OR logName:\"/logs/cloudaudit.googleapis.com%2Fsystem_event\"" type = "bigquery" } vpc-sc = { filter = "protoPayload.metadata.@type=\"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata\"" type = "bigquery" } }">{…}</code> |
|
||||||
| [projects_create](variables.tf#L148) | Provide values if projects creation is needed, uses existing project if null. Projects will be created in the shielded folder. | <code title="object({ billing_account_id = string })">object({…})</code> | | <code>null</code> |
|
| [projects_create](variables.tf#L147) | Provide values if projects creation is needed, uses existing project if null. Projects will be created in the shielded folder. | <code title="object({ billing_account_id = string })">object({…})</code> | | <code>null</code> |
|
||||||
| [projects_id](variables.tf#L156) | Project id, references existing projects if `projects_create` is null. Projects will be moved into the shielded folder. | <code title="object({ sec-core = string audit-logs = string })">object({…})</code> | | <code>null</code> |
|
| [projects_id](variables.tf#L155) | Project id, references existing projects if `projects_create` is null. Projects will be moved into the shielded folder. | <code title="object({ sec-core = string audit-logs = string })">object({…})</code> | | <code>null</code> |
|
||||||
| [vpc_sc_access_levels](variables.tf#L165) | VPC SC access level definitions. | <code title="map(object({ combining_function = optional(string) conditions = optional(list(object({ device_policy = optional(object({ allowed_device_management_levels = optional(list(string)) allowed_encryption_statuses = optional(list(string)) require_admin_approval = bool require_corp_owned = bool require_screen_lock = optional(bool) os_constraints = optional(list(object({ os_type = string minimum_version = optional(string) require_verified_chrome_os = optional(bool) }))) })) ip_subnetworks = optional(list(string), []) members = optional(list(string), []) negate = optional(bool) regions = optional(list(string), []) required_access_levels = optional(list(string), []) })), []) description = optional(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [vpc_sc_access_levels](variables.tf#L164) | VPC SC access level definitions. | <code title="map(object({ combining_function = optional(string) conditions = optional(list(object({ device_policy = optional(object({ allowed_device_management_levels = optional(list(string)) allowed_encryption_statuses = optional(list(string)) require_admin_approval = bool require_corp_owned = bool require_screen_lock = optional(bool) os_constraints = optional(list(object({ os_type = string minimum_version = optional(string) require_verified_chrome_os = optional(bool) }))) })) ip_subnetworks = optional(list(string), []) members = optional(list(string), []) negate = optional(bool) regions = optional(list(string), []) required_access_levels = optional(list(string), []) })), []) description = optional(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [vpc_sc_egress_policies](variables.tf#L194) | VPC SC egress policy defnitions. | <code title="map(object({ from = object({ identity_type = optional(string, "ANY_IDENTITY") identities = optional(list(string)) }) to = object({ operations = optional(list(object({ method_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) resource_type_external = optional(bool, false) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [vpc_sc_egress_policies](variables.tf#L193) | VPC SC egress policy defnitions. | <code title="map(object({ from = object({ identity_type = optional(string, "ANY_IDENTITY") identities = optional(list(string)) }) to = object({ operations = optional(list(object({ method_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) resource_type_external = optional(bool, false) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [vpc_sc_ingress_policies](variables.tf#L214) | VPC SC ingress policy defnitions. | <code title="map(object({ from = object({ access_levels = optional(list(string), []) identity_type = optional(string) identities = optional(list(string)) resources = optional(list(string), []) }) to = object({ operations = optional(list(object({ method_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [vpc_sc_ingress_policies](variables.tf#L213) | VPC SC ingress policy defnitions. | <code title="map(object({ from = object({ access_levels = optional(list(string), []) identity_type = optional(string) identities = optional(list(string)) resources = optional(list(string), []) }) to = object({ operations = optional(list(object({ method_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
|
|
|
@ -64,9 +64,8 @@ module "sec-project" {
|
||||||
project_create = var.projects_create != null && var.enable_features.encryption
|
project_create = var.projects_create != null && var.enable_features.encryption
|
||||||
prefix = var.projects_create == null ? null : var.prefix
|
prefix = var.projects_create == null ? null : var.prefix
|
||||||
group_iam = {
|
group_iam = {
|
||||||
(local.groups.data-engineers) = [
|
(local.groups.workload-security) = [
|
||||||
"roles/cloudkms.admin",
|
"roles/editor"
|
||||||
"roles/viewer",
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
services = [
|
services = [
|
||||||
|
|
|
@ -43,6 +43,11 @@ module "log-export-project" {
|
||||||
billing_account = try(var.projects_create.billing_account_id, null)
|
billing_account = try(var.projects_create.billing_account_id, null)
|
||||||
project_create = var.projects_create != null
|
project_create = var.projects_create != null
|
||||||
prefix = var.projects_create == null ? null : var.prefix
|
prefix = var.projects_create == null ? null : var.prefix
|
||||||
|
group_iam = {
|
||||||
|
(local.groups.workload-security) = [
|
||||||
|
"roles/editor"
|
||||||
|
]
|
||||||
|
}
|
||||||
iam = {
|
iam = {
|
||||||
# "roles/owner" = [module.automation-tf-bootstrap-sa.iam_email]
|
# "roles/owner" = [module.automation-tf-bootstrap-sa.iam_email]
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,9 @@ locals {
|
||||||
for k, v in local.groups : k => "group:${v}"
|
for k, v in local.groups : k => "group:${v}"
|
||||||
}
|
}
|
||||||
group_iam = {
|
group_iam = {
|
||||||
(local.groups.data-engineers) = [
|
(local.groups.workload-engineers) = [
|
||||||
"roles/editor",
|
"roles/editor",
|
||||||
|
"roles/iam.serviceAccountTokenCreator"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,9 +68,8 @@ variable "groups" {
|
||||||
description = "User groups."
|
description = "User groups."
|
||||||
type = map(string)
|
type = map(string)
|
||||||
default = {
|
default = {
|
||||||
#TODO data-analysts = "gcp-data-analysts"
|
workload-engineers = "gcp-data-engineers"
|
||||||
data-engineers = "gcp-data-engineers"
|
workload-security = "gcp-data-security"
|
||||||
data-security = "gcp-data-security"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue