include "root" { path = find_in_parent_folders() } locals { repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../..") infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml")) secrets_file = "${local.repo_root}/infrastructure-secrets.yaml" # В CI файл расшифровывается заранее одним шагом, и путь передаётся через # INFRA_SECRET_VALUES_FILE (SOPS_AGE_KEY нужен только этому шагу, не всей # джобе). Локально - fallback на прямую расшифровку через sops_decrypt_file. # # Без try(...,"")/try(...,{}) на decrypt/parse ниже намеренно: раньше # провалившаяся расшифровка тихо схлопывалась в secrets_config = {}, дальше # в vault_config = {} и vault_enabled = false - план "ничего не менять в # vault" выглядел бы легитимно, без единой ошибки, хотя причина - сломанный # ключ/файл, а не осознанное отсутствие vault-конфига. secret_values_env_file = get_env("INFRA_SECRET_VALUES_FILE", "") secrets_config_raw = local.secret_values_env_file != "" ? file(local.secret_values_env_file) : sops_decrypt_file(local.secrets_file) secrets_config = yamldecode(local.secrets_config_raw) env_override = trimspace(get_env("INFRA_ENV", "")) env_from_file = try(trimspace(local.infra_config.current_environment), "") available_envs = sort(keys(local.secrets_config.environments)) env_fallback = try(local.available_envs[0], "") env_name = local.env_override != "" ? local.env_override : ( local.env_from_file != "" ? local.env_from_file : local.env_fallback ) # file() как самодельный error(): в HCL нет нативного assert/error, это # стандартный трюк - заведомо не существующий путь всплывает в тексте # ошибки terraform "no such file". _fail_on_missing_secret_env = !contains(keys(local.secrets_config.environments), local.env_name) ? file("INFRA_ENV '${local.env_name}' not found in infrastructure-secrets.yaml environments: [${join(", ", keys(local.secrets_config.environments))}]") : "" env_config = local.secrets_config.environments[local.env_name] # Опечатка в самом ключе "vault" (например "vaultt") даёт ту же дыру, что # и провалившийся decrypt: try() ниже не отличит "vault осознанно не задан" # от "ключ переименован опечаткой" - в обоих случаях vault_config = {} и # план "нечего менять в vault" выглядит легитимно. allowed_env_config_keys = toset(["secrets", "vault"]) env_config_key_typos = [ for k in keys(local.env_config) : "env '${local.env_name}': unknown top-level key '${k}'" if !contains(local.allowed_env_config_keys, k) ] _fail_on_env_config_key_typos = length(local.env_config_key_typos) > 0 ? file("Unknown/misspelled top-level key(s) in infrastructure-secrets.yaml: ${join(" | ", local.env_config_key_typos)}") : "" vault_config = try(local.env_config.vault, {}) vault_enabled = try(local.vault_config.enabled, false) } remote_state { backend = "s3" generate = { path = "backend.tf" if_exists = "overwrite_terragrunt" } config = { endpoint = get_env("TF_STATE_S3_ENDPOINT", "") bucket = get_env("TF_STATE_S3_BUCKET", "") key = "${local.env_name}/vault-secrets/terraform.tfstate" region = get_env("TF_STATE_S3_REGION", "ru-central1") access_key = get_env("S3_ACCESS_KEY", get_env("AWS_ACCESS_KEY_ID", "")) secret_key = get_env("S3_SECRET_KEY", get_env("AWS_SECRET_ACCESS_KEY", "")) skip_region_validation = true skip_credentials_validation = true skip_metadata_api_check = true skip_bucket_root_access = true force_path_style = true } } terraform { source = "${get_terragrunt_dir()}/../../modules//vault-platform-secrets" } inputs = { vault_kv_mount = try(local.vault_config.kv_mount, "secrets") path_prefix = try(local.vault_config.path_prefix, "vault") # Секретные значения обёрнуты под vault.data.* (см. .sops.yaml) - шифруется # только этот поддерево, а не весь файл. applications ниже - конфиг policy/ # role, секретов не содержит, поэтому вне data. common = try(local.vault_config.data.common, {}) infra = try(local.vault_config.data.infrastructure, {}) applications = try(local.vault_config.applications, {}) default_rsa_bits = try(local.vault_config.default_rsa_bits, 4096) kubernetes_auth_backend = try(local.vault_config.kubernetes_auth_backend, "kubernetes") create_regcred = local.vault_enabled && try(local.vault_config.features.create_regcred, true) create_smtp_auth = local.vault_enabled && try(local.vault_config.features.create_smtp_auth, true) create_django_auth = local.vault_enabled && try(local.vault_config.features.create_django_auth, true) create_rsa_keys = local.vault_enabled && try(local.vault_config.features.create_rsa_keys, true) create_infra_secrets = local.vault_enabled && try(local.vault_config.features.create_infra_secrets, true) create_infra_policies = local.vault_enabled && try(local.vault_config.features.create_infra_policies, true) create_infra_roles = local.vault_enabled && try(local.vault_config.features.create_infra_roles, true) create_app_policies = local.vault_enabled && try(local.vault_config.features.create_app_policies, true) create_app_roles = local.vault_enabled && try(local.vault_config.features.create_app_roles, true) }