diff --git a/google_project/README.md b/google_project/README.md index e99323e7..71b0ff50 100644 --- a/google_project/README.md +++ b/google_project/README.md @@ -23,7 +23,8 @@ Sets up a single GCP project linked to a billing account plus management metadat | [project\_name](#input\_project\_name) | Name of project e.g., autopush | `string` | n/a | yes | | [project\_services](#input\_project\_services) | List of google\_project\_service APIs to enable. | `list(string)` | `[]` | no | | [realm](#input\_realm) | Realm is a grouping of environments being one of: global, nonprod, prod | `string` | `""` | no | -| [risk\_level](#input\_risk\_level) | Level of risk the project poses, usually obtained from an RRA | `string` | `""` | no | +| [risk\_level](#input\_risk\_level) | DEPRECATED - Level of risk the project poses, usually obtained from an RRA | `string` | `""` | no | +| [risk\_profile](#input\_risk\_profile) | Risk profile of the project, used by the Wiz security platform |
object({
has_authentication = string
has_exposed_api = string
is_actively_developed = string
is_customer_facing = string
is_internet_facing = string
is_regulated = string
regulatory_standards = list(string)
sensitive_data_types = list(string)
stores_data = string
})
|
{
"has_authentication": "UNKNOWN",
"has_exposed_api": "UNKNOWN",
"is_actively_developed": "UNKNOWN",
"is_customer_facing": "UNKNOWN",
"is_internet_facing": "UNKNOWN",
"is_regulated": "UNKNOWN",
"regulatory_standards": [],
"sensitive_data_types": [],
"stores_data": "UNKNOWN"
}
| no | ## Outputs diff --git a/google_project/locals.tf b/google_project/locals.tf index 21b69f48..8647616d 100644 --- a/google_project/locals.tf +++ b/google_project/locals.tf @@ -7,6 +7,22 @@ locals { app_code = coalesce(var.app_code, var.project_name) component_code = coalesce(var.component_code, "${local.app_code}-uncat") + # Helper locals for truncation of risk profile lists to 63 characters + regulatory_standards_joined = join(",", var.risk_profile.regulatory_standards) + sensitive_data_types_joined = join(",", var.risk_profile.sensitive_data_types) + + normalized_risk_profile = { + has_authentication = upper(var.risk_profile.has_authentication) + has_exposed_api = upper(var.risk_profile.has_exposed_api) + is_actively_developed = upper(var.risk_profile.is_actively_developed) + is_customer_facing = upper(var.risk_profile.is_customer_facing) + is_internet_facing = upper(var.risk_profile.is_internet_facing) + is_regulated = upper(var.risk_profile.is_regulated) + stores_data = upper(var.risk_profile.stores_data) + regulatory_standards = length(local.regulatory_standards_joined) > 63 ? substr(local.regulatory_standards_joined, 0, 63) : local.regulatory_standards_joined + sensitive_data_types = length(local.sensitive_data_types_joined) > 63 ? substr(local.sensitive_data_types_joined, 0, 63) : local.sensitive_data_types_joined + } + default_project_labels = { app = var.project_name app_code = local.app_code @@ -17,7 +33,7 @@ locals { realm = var.realm risk_level = var.risk_level } - all_project_labels = merge(local.default_project_labels, var.extra_project_labels) + all_project_labels = merge(local.default_project_labels, var.extra_project_labels, local.normalized_risk_profile) default_project_services = [ "cloudasset.googleapis.com", @@ -38,3 +54,18 @@ locals { default_data_access_logs = ["iam.googleapis.com", "secretmanager.googleapis.com", "sts.googleapis.com", "privilegedaccessmanager.googleapis.com"] data_access_logs_filter = join("\n", toset([for v in concat(local.default_data_access_logs, var.additional_data_access_logs) : "AND NOT protoPayload.serviceName=\"${v}\""])) } + +# we want to emit a warning when we truncate the lists in the risk profile +check "risk_profile_truncation" { + assert { + condition = length(local.regulatory_standards_joined) <= 63 + error_message = "Warning: regulatory_standards list '${local.regulatory_standards_joined}' exceeds 63 characters and will be truncated to '${substr(local.regulatory_standards_joined, 0, 63)}'" + } +} + +check "sensitive_data_truncation" { + assert { + condition = length(local.sensitive_data_types_joined) <= 63 + error_message = "Warning: sensitive_data_types list '${local.sensitive_data_types_joined}' exceeds 63 characters and will be truncated to '${substr(local.sensitive_data_types_joined, 0, 63)}'" + } +} \ No newline at end of file diff --git a/google_project/variables.tf b/google_project/variables.tf index 513f2666..907e7bb6 100644 --- a/google_project/variables.tf +++ b/google_project/variables.tf @@ -63,10 +63,49 @@ variable "extra_project_labels" { variable "risk_level" { default = "" - description = "Level of risk the project poses, usually obtained from an RRA" + description = "DEPRECATED - Level of risk the project poses, usually obtained from an RRA" type = string } +variable "risk_profile" { + description = "Risk profile of the project, used by the Wiz security platform" + type = object({ + has_authentication = string + has_exposed_api = string + is_actively_developed = string + is_customer_facing = string + is_internet_facing = string + is_regulated = string + regulatory_standards = list(string) + sensitive_data_types = list(string) + stores_data = string + }) + + default = { + has_authentication = "UNKNOWN" + has_exposed_api = "UNKNOWN" + is_actively_developed = "UNKNOWN" + is_customer_facing = "UNKNOWN" + is_internet_facing = "UNKNOWN" + is_regulated = "UNKNOWN" + regulatory_standards = [] + sensitive_data_types = [] + stores_data = "UNKNOWN" + } + + // need this so we use default values when not set or set to null + nullable = false + + validation { + condition = alltrue([ + for key, value in var.risk_profile : + key == "regulatory_standards" || key == "sensitive_data_types" ? true : + contains(["UNKNOWN", "YES", "NO"], upper(value)) + ]) + error_message = "String values must be one of: UNKNOWN, YES, NO. Lists (regulatory_standards, sensitive_data_types) can contain any strings." + } +} + # # Variables to possibly Archive? #