mirror of
https://gitlab.sarex.io/infra/terraform-contour-mirror.git
synced 2026-08-05 18:31:00 +03:00
++ strip comments
This commit is contained in:
parent
b54fc6f29b
commit
168f5d66ce
@ -15,30 +15,14 @@ locals {
|
|||||||
local.env_from_file != "" ? local.env_from_file : local.env_fallback
|
local.env_from_file != "" ? local.env_from_file : local.env_fallback
|
||||||
)
|
)
|
||||||
|
|
||||||
# Single declarative source: shape + data in one sops file. In CI it is
|
|
||||||
# decrypted ahead of time and the path is passed via INFRA_SECRET_VALUES_FILE;
|
|
||||||
# locally we fall back to direct sops decryption. Values reach the module only
|
|
||||||
# via inputs (ephemeral), never written to disk.
|
|
||||||
#
|
|
||||||
# No try(...,"")/try(...,{}) on decrypt/parse/env-lookup below on purpose:
|
|
||||||
# swallowing those failures used to collapse silently into secrets = [],
|
|
||||||
# and a terraform plan with 0 declared secrets looks like a normal, boring
|
|
||||||
# "destroy everything" diff - nothing marks it as "decrypt actually failed".
|
|
||||||
secret_values_env_file = get_env("INFRA_SECRET_VALUES_FILE", "")
|
secret_values_env_file = get_env("INFRA_SECRET_VALUES_FILE", "")
|
||||||
secret_values_raw = local.secret_values_env_file != "" ? file(local.secret_values_env_file) : sops_decrypt_file("${local.repo_root}/infrastructure-secrets.yaml")
|
secret_values_raw = local.secret_values_env_file != "" ? file(local.secret_values_env_file) : sops_decrypt_file("${local.repo_root}/infrastructure-secrets.yaml")
|
||||||
secret_values_config = yamldecode(local.secret_values_raw)
|
secret_values_config = yamldecode(local.secret_values_raw)
|
||||||
|
|
||||||
# file() as a poor man's error(): HCL has no native assert/error function,
|
|
||||||
# this is the standard trick - an intentionally-broken file() call surfaces
|
|
||||||
# the message text inside terraform's own "no such file" error.
|
|
||||||
_fail_on_missing_secret_env = !contains(keys(local.secret_values_config.environments), local.env_name) ? file("INFRA_ENV '${local.env_name}' not found in infrastructure-secrets.yaml environments: [${join(", ", keys(local.secret_values_config.environments))}]") : ""
|
_fail_on_missing_secret_env = !contains(keys(local.secret_values_config.environments), local.env_name) ? file("INFRA_ENV '${local.env_name}' not found in infrastructure-secrets.yaml environments: [${join(", ", keys(local.secret_values_config.environments))}]") : ""
|
||||||
|
|
||||||
secret_values_env = local.secret_values_config.environments[local.env_name]
|
secret_values_env = local.secret_values_config.environments[local.env_name]
|
||||||
|
|
||||||
# A typo in the "secrets" key itself (e.g. "secretz") opens the same hole
|
|
||||||
# as the per-entry typos below: try() on the secrets line below can't tell
|
|
||||||
# "key absent because 0 secrets declared" from "key renamed by a typo" -
|
|
||||||
# both yield []. Explicitly validate the env's allowed top-level keys.
|
|
||||||
allowed_secret_env_keys = toset(["secrets", "vault"])
|
allowed_secret_env_keys = toset(["secrets", "vault"])
|
||||||
secret_env_key_typos = [
|
secret_env_key_typos = [
|
||||||
for k in keys(local.secret_values_env) : "env '${local.env_name}': unknown top-level key '${k}'"
|
for k in keys(local.secret_values_env) : "env '${local.env_name}': unknown top-level key '${k}'"
|
||||||
@ -46,15 +30,8 @@ locals {
|
|||||||
]
|
]
|
||||||
_fail_on_secret_env_key_typos = length(local.secret_env_key_typos) > 0 ? file("Unknown/misspelled top-level key(s) in infrastructure-secrets.yaml: ${join(" | ", local.secret_env_key_typos)}") : ""
|
_fail_on_secret_env_key_typos = length(local.secret_env_key_typos) > 0 ? file("Unknown/misspelled top-level key(s) in infrastructure-secrets.yaml: ${join(" | ", local.secret_env_key_typos)}") : ""
|
||||||
|
|
||||||
# secrets key itself may legitimately be absent for an environment with 0
|
|
||||||
# secrets declared - that one stays a real default, not an error.
|
|
||||||
secrets = try(local.secret_values_env.secrets, [])
|
secrets = try(local.secret_values_env.secrets, [])
|
||||||
|
|
||||||
# Явная проверка top-level ключей каждой записи secrets: Terraform молча
|
|
||||||
# отбрасывает незнакомые ключи при приведении к типу (например custom_key
|
|
||||||
# вместо custom_keys, depends_ons вместо depends_on) - без этой проверки
|
|
||||||
# опечатка в infrastructure-secrets.yaml тихо теряется, без единой ошибки
|
|
||||||
# в плане, и нужное поле остаётся дефолтным/пустым.
|
|
||||||
allowed_secret_keys = toset([
|
allowed_secret_keys = toset([
|
||||||
"name", "namespace", "type", "registry_url", "data", "depends_on",
|
"name", "namespace", "type", "registry_url", "data", "depends_on",
|
||||||
"yc_sa_key_names", "custom_keys", "constant_keys", "random_keys",
|
"yc_sa_key_names", "custom_keys", "constant_keys", "random_keys",
|
||||||
@ -68,11 +45,6 @@ locals {
|
|||||||
])
|
])
|
||||||
_fail_on_secret_key_typos = length(local.secret_key_typos) > 0 ? file("Unknown/misspelled key(s) in infrastructure-secrets.yaml secrets: ${join(" | ", local.secret_key_typos)}") : ""
|
_fail_on_secret_key_typos = length(local.secret_key_typos) > 0 ? file("Unknown/misspelled key(s) in infrastructure-secrets.yaml secrets: ${join(" | ", local.secret_key_typos)}") : ""
|
||||||
|
|
||||||
# image-pull-secret (regcred) fan-out. Single source: vault.data.common.regcred.dockerconfigjson
|
|
||||||
# (secret values live under vault.data.* - see .sops.yaml encrypted_regex).
|
|
||||||
# Rolled as a kubernetes.io/dockerconfigjson secret named `regcred` into every
|
|
||||||
# namespace flagged `image_pull_secret: true` in infrastructure.yaml. Only created
|
|
||||||
# when the source is a real docker config (guards against the CHANGE_ME placeholder).
|
|
||||||
regcred_dockerconfigjson = try(local.secret_values_env.vault.data.common.regcred.dockerconfigjson, "")
|
regcred_dockerconfigjson = try(local.secret_values_env.vault.data.common.regcred.dockerconfigjson, "")
|
||||||
regcred_valid = can(jsondecode(local.regcred_dockerconfigjson))
|
regcred_valid = can(jsondecode(local.regcred_dockerconfigjson))
|
||||||
regcred_namespaces = [
|
regcred_namespaces = [
|
||||||
@ -116,7 +88,6 @@ locals {
|
|||||||
labels = try(secret.labels, {})
|
labels = try(secret.labels, {})
|
||||||
annotations = try(secret.annotations, {})
|
annotations = try(secret.annotations, {})
|
||||||
ignore_changes = try(secret.lifecycle.ignore_changes, false)
|
ignore_changes = try(secret.lifecycle.ignore_changes, false)
|
||||||
# Sink: k8s (default) or vault. vault_path is the KV name (default <prefix>/<name>).
|
|
||||||
sink = try(secret.sink, "k8s")
|
sink = try(secret.sink, "k8s")
|
||||||
vault_path = try(secret.vault_path, "")
|
vault_path = try(secret.vault_path, "")
|
||||||
}
|
}
|
||||||
@ -194,7 +165,6 @@ inputs = {
|
|||||||
kafka_outputs_map = try(dependency.kafka_topics.outputs.kafka_outputs_map, {})
|
kafka_outputs_map = try(dependency.kafka_topics.outputs.kafka_outputs_map, {})
|
||||||
valkey_outputs_map = {}
|
valkey_outputs_map = {}
|
||||||
|
|
||||||
# In-cluster constants (contour). No managed-YC CA; in-cluster pgbouncer/pg on 5432.
|
|
||||||
constants = {
|
constants = {
|
||||||
s3_endpoint = try(local.infra_config.environments[local.env_name].minio.endpoint, "http://minio.minio.svc.cluster.local:9000")
|
s3_endpoint = try(local.infra_config.environments[local.env_name].minio.endpoint, "http://minio.minio.svc.cluster.local:9000")
|
||||||
postgres_port = "5432"
|
postgres_port = "5432"
|
||||||
@ -203,7 +173,6 @@ inputs = {
|
|||||||
valkey_ca = ""
|
valkey_ca = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# Vault sink target (KV v2). Mount/prefix match the vault-secrets platform layout.
|
|
||||||
vault_kv_mount = try(local.secret_values_env.vault.kv_mount, "secrets")
|
vault_kv_mount = try(local.secret_values_env.vault.kv_mount, "secrets")
|
||||||
vault_path_prefix = try(local.secret_values_env.vault.path_prefix, "vault")
|
vault_path_prefix = try(local.secret_values_env.vault.path_prefix, "vault")
|
||||||
|
|
||||||
|
|||||||
@ -7,15 +7,6 @@ locals {
|
|||||||
infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml"))
|
infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml"))
|
||||||
secrets_file = "${local.repo_root}/infrastructure-secrets.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", "")
|
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_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)
|
secrets_config = yamldecode(local.secrets_config_raw)
|
||||||
@ -29,17 +20,10 @@ locals {
|
|||||||
local.env_from_file != "" ? local.env_from_file : local.env_fallback
|
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))}]") : ""
|
_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]
|
env_config = local.secrets_config.environments[local.env_name]
|
||||||
|
|
||||||
# Опечатка в самом ключе "vault" (например "vaultt") даёт ту же дыру, что
|
|
||||||
# и провалившийся decrypt: try() ниже не отличит "vault осознанно не задан"
|
|
||||||
# от "ключ переименован опечаткой" - в обоих случаях vault_config = {} и
|
|
||||||
# план "нечего менять в vault" выглядит легитимно.
|
|
||||||
allowed_env_config_keys = toset(["secrets", "vault"])
|
allowed_env_config_keys = toset(["secrets", "vault"])
|
||||||
env_config_key_typos = [
|
env_config_key_typos = [
|
||||||
for k in keys(local.env_config) : "env '${local.env_name}': unknown top-level key '${k}'"
|
for k in keys(local.env_config) : "env '${local.env_name}': unknown top-level key '${k}'"
|
||||||
@ -79,9 +63,6 @@ terraform {
|
|||||||
inputs = {
|
inputs = {
|
||||||
vault_kv_mount = try(local.vault_config.kv_mount, "secrets")
|
vault_kv_mount = try(local.vault_config.kv_mount, "secrets")
|
||||||
path_prefix = try(local.vault_config.path_prefix, "vault")
|
path_prefix = try(local.vault_config.path_prefix, "vault")
|
||||||
# Секретные значения обёрнуты под vault.data.* (см. .sops.yaml) - шифруется
|
|
||||||
# только этот поддерево, а не весь файл. applications ниже - конфиг policy/
|
|
||||||
# role, секретов не содержит, поэтому вне data.
|
|
||||||
common = try(local.vault_config.data.common, {})
|
common = try(local.vault_config.data.common, {})
|
||||||
infra = try(local.vault_config.data.infrastructure, {})
|
infra = try(local.vault_config.data.infrastructure, {})
|
||||||
applications = try(local.vault_config.applications, {})
|
applications = try(local.vault_config.applications, {})
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
# Маппинг наших типов на Kubernetes типы
|
|
||||||
k8s_secret_type_map = {
|
k8s_secret_type_map = {
|
||||||
"dockerconfigjson" = "kubernetes.io/dockerconfigjson"
|
"dockerconfigjson" = "kubernetes.io/dockerconfigjson"
|
||||||
"database" = "Opaque"
|
"database" = "Opaque"
|
||||||
@ -145,9 +144,6 @@ locals {
|
|||||||
if secret.type == "yc_sa"
|
if secret.type == "yc_sa"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Явные значения секрета (adopt 1:1 / статические). Приходят прямо из
|
|
||||||
# infrastructure-secrets.yaml в поле data как map(key => base64(raw_value)).
|
|
||||||
# k8s хранит .data уже в base64, поэтому base64decode даёт исходное значение байт-в-байт.
|
|
||||||
secrets_data_override = {
|
secrets_data_override = {
|
||||||
for name, secret in local.secrets_map : name => {
|
for name, secret in local.secrets_map : name => {
|
||||||
for key, b64 in try(secret.data, {}) : key => base64decode(b64)
|
for key, b64 in try(secret.data, {}) : key => base64decode(b64)
|
||||||
@ -168,7 +164,6 @@ locals {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
} : secret.type == "s3" ? {
|
} : secret.type == "s3" ? {
|
||||||
# Если указан конкретный bucket в depends_on - используем его, иначе fallback на s3_outputs
|
|
||||||
access_key = try(var.s3_buckets_map[secret.depends_on.bucket].access_key, var.s3_outputs.access_key)
|
access_key = try(var.s3_buckets_map[secret.depends_on.bucket].access_key, var.s3_outputs.access_key)
|
||||||
secret_key = try(var.s3_buckets_map[secret.depends_on.bucket].secret_key, var.s3_outputs.secret_key)
|
secret_key = try(var.s3_buckets_map[secret.depends_on.bucket].secret_key, var.s3_outputs.secret_key)
|
||||||
bucket = try(var.s3_buckets_map[secret.depends_on.bucket].bucket_name, var.s3_outputs.bucket_name)
|
bucket = try(var.s3_buckets_map[secret.depends_on.bucket].bucket_name, var.s3_outputs.bucket_name)
|
||||||
@ -185,7 +180,6 @@ locals {
|
|||||||
for key, constant_name in try(secret.constant_keys, {}) : key => try(var.constants[constant_name], "")
|
for key, constant_name in try(secret.constant_keys, {}) : key => try(var.constants[constant_name], "")
|
||||||
}
|
}
|
||||||
) : secret.type == "database" && local.database_outputs_by_secret[name] != null ? merge(
|
) : secret.type == "database" && local.database_outputs_by_secret[name] != null ? merge(
|
||||||
# Базовые поля из database outputs
|
|
||||||
{
|
{
|
||||||
host = local.database_outputs_by_secret[name].host
|
host = local.database_outputs_by_secret[name].host
|
||||||
port = try(var.constants.postgres_port, "6432")
|
port = try(var.constants.postgres_port, "6432")
|
||||||
@ -194,7 +188,6 @@ locals {
|
|||||||
password = local.database_outputs_by_secret[name].password
|
password = local.database_outputs_by_secret[name].password
|
||||||
"ca.crt" = try(var.constants.postgres_ca, "")
|
"ca.crt" = try(var.constants.postgres_ca, "")
|
||||||
},
|
},
|
||||||
# Кастомные статические поля
|
|
||||||
try(secret.custom_keys, {}),
|
try(secret.custom_keys, {}),
|
||||||
{
|
{
|
||||||
for key, constant_name in try(secret.constant_keys, {}) : key => try(var.constants[constant_name], "")
|
for key, constant_name in try(secret.constant_keys, {}) : key => try(var.constants[constant_name], "")
|
||||||
@ -247,15 +240,6 @@ locals {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Явный контракт для типов с обязательным depends_on. Раньше отсутствующее
|
|
||||||
# или неполное depends_on тихо резолвилось через try(..., "") в несуществующий
|
|
||||||
# ключ outputs-карты, outputs_by_secret[name] становился null, и секрет молча
|
|
||||||
# создавался ПУСТЫМ (без host/port/username/password) - без единой ошибки в
|
|
||||||
# плане. Для type=yc_sa такой защиты не было вообще: null-источник просто не
|
|
||||||
# проверялся, и итоговые access_key/secret_key/service_account_id молча
|
|
||||||
# оставались пустыми строками. Здесь это - явная ошибка плана. Секреты с
|
|
||||||
# готовым статическим data (adopt/1:1) под контракт не подпадают: они не
|
|
||||||
# резолвят depends_on вообще.
|
|
||||||
secrets_contract_errors = {
|
secrets_contract_errors = {
|
||||||
for name, secret in local.secrets_map : name => (
|
for name, secret in local.secrets_map : name => (
|
||||||
length(try(secret.data, {})) > 0 ? "" :
|
length(try(secret.data, {})) > 0 ? "" :
|
||||||
@ -284,12 +268,6 @@ locals {
|
|||||||
? "type=yc_sa requires depends_on.service_account"
|
? "type=yc_sa requires depends_on.service_account"
|
||||||
: ""
|
: ""
|
||||||
) :
|
) :
|
||||||
# dockerconfigjson не зависит от per-secret depends_on - источник это
|
|
||||||
# МОДУЛЬНЫЕ (общие для всех секретов) env_vars.DOCKER_REGISTRY_USERNAME/
|
|
||||||
# PASSWORD. Если они пустые, секрет молча создаётся с пустым логином/
|
|
||||||
# паролем внутри .dockerconfigjson - тот же класс тихой пустышки.
|
|
||||||
# ignore_changes=true - осознанно замороженный секрет (напр. известно
|
|
||||||
# пустые креды в CI) - контракт его не блокирует.
|
|
||||||
secret.type == "dockerconfigjson" && !try(secret.ignore_changes, false) ? (
|
secret.type == "dockerconfigjson" && !try(secret.ignore_changes, false) ? (
|
||||||
trimspace(try(var.env_vars.DOCKER_REGISTRY_USERNAME, "")) == "" || trimspace(try(var.env_vars.DOCKER_REGISTRY_PASSWORD, "")) == ""
|
trimspace(try(var.env_vars.DOCKER_REGISTRY_USERNAME, "")) == "" || trimspace(try(var.env_vars.DOCKER_REGISTRY_PASSWORD, "")) == ""
|
||||||
? "type=dockerconfigjson requires module-level env_vars.DOCKER_REGISTRY_USERNAME and env_vars.DOCKER_REGISTRY_PASSWORD to be non-empty"
|
? "type=dockerconfigjson requires module-level env_vars.DOCKER_REGISTRY_USERNAME and env_vars.DOCKER_REGISTRY_PASSWORD to be non-empty"
|
||||||
@ -299,8 +277,6 @@ locals {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Если для секрета заданы явные значения (data) - используем их 1:1,
|
|
||||||
# иначе собираем data из outputs/custom/constant/random как обычно.
|
|
||||||
secrets_data = {
|
secrets_data = {
|
||||||
for name, secret in local.secrets_map : name => (
|
for name, secret in local.secrets_map : name => (
|
||||||
contains(keys(local.secrets_data_override), name)
|
contains(keys(local.secrets_data_override), name)
|
||||||
@ -321,12 +297,10 @@ locals {
|
|||||||
sink = try(secret.sink, "k8s")
|
sink = try(secret.sink, "k8s")
|
||||||
vault_path = try(secret.vault_path, "") != "" ? secret.vault_path : "${var.vault_path_prefix}/${secret.name}"
|
vault_path = try(secret.vault_path, "") != "" ? secret.vault_path : "${var.vault_path_prefix}/${secret.name}"
|
||||||
data = try(local.secrets_data[name], {})
|
data = try(local.secrets_data[name], {})
|
||||||
# Явный data имеет приоритет над вычисляемыми, включая случайные ключи.
|
|
||||||
random_keys = contains(keys(local.secrets_data_override), name) ? {} : try(secret.random_keys, {})
|
random_keys = contains(keys(local.secrets_data_override), name) ? {} : try(secret.random_keys, {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# k8s-sink secrets, split by ignore_changes semantics.
|
|
||||||
secrets_with_ignore = {
|
secrets_with_ignore = {
|
||||||
for name, secret in local.secrets_with_data : name => secret
|
for name, secret in local.secrets_with_data : name => secret
|
||||||
if secret.sink == "k8s" && secret.ignore_changes
|
if secret.sink == "k8s" && secret.ignore_changes
|
||||||
@ -336,7 +310,6 @@ locals {
|
|||||||
if secret.sink == "k8s" && !secret.ignore_changes
|
if secret.sink == "k8s" && !secret.ignore_changes
|
||||||
}
|
}
|
||||||
|
|
||||||
# vault-sink secrets: same resolved data, written to Vault KV v2 instead.
|
|
||||||
secrets_vault = {
|
secrets_vault = {
|
||||||
for name, secret in local.secrets_with_data : name => secret
|
for name, secret in local.secrets_with_data : name => secret
|
||||||
if secret.sink == "vault"
|
if secret.sink == "vault"
|
||||||
@ -369,14 +342,11 @@ resource "kubernetes_secret" "with_ignore" {
|
|||||||
|
|
||||||
type = each.value.k8s_type
|
type = each.value.k8s_type
|
||||||
|
|
||||||
# Ссылка на random_password остаётся на уровне конкретного секрета. Поэтому
|
|
||||||
# новый случайный ключ не делает data неизвестным у всех остальных секретов.
|
|
||||||
data = merge(each.value.data, {
|
data = merge(each.value.data, {
|
||||||
for key, config in each.value.random_keys : key => random_password.secrets["${each.key}:${key}"].result
|
for key, config in each.value.random_keys : key => random_password.secrets["${each.key}:${key}"].result
|
||||||
})
|
})
|
||||||
|
|
||||||
lifecycle {
|
lifecycle {
|
||||||
# Игнорируем data, type и metadata чтобы не было phantom updates
|
|
||||||
ignore_changes = [data, type, metadata, wait_for_service_account_token]
|
ignore_changes = [data, type, metadata, wait_for_service_account_token]
|
||||||
precondition {
|
precondition {
|
||||||
condition = local.secrets_contract_errors[each.key] == ""
|
condition = local.secrets_contract_errors[each.key] == ""
|
||||||
@ -397,14 +367,11 @@ resource "kubernetes_secret" "without_ignore" {
|
|||||||
|
|
||||||
type = each.value.k8s_type
|
type = each.value.k8s_type
|
||||||
|
|
||||||
# Ссылка на random_password остаётся на уровне конкретного секрета. Поэтому
|
|
||||||
# новый случайный ключ не делает data неизвестным у всех остальных секретов.
|
|
||||||
data = merge(each.value.data, {
|
data = merge(each.value.data, {
|
||||||
for key, config in each.value.random_keys : key => random_password.secrets["${each.key}:${key}"].result
|
for key, config in each.value.random_keys : key => random_password.secrets["${each.key}:${key}"].result
|
||||||
})
|
})
|
||||||
|
|
||||||
lifecycle {
|
lifecycle {
|
||||||
# type и metadata игнорируем чтобы не было phantom updates
|
|
||||||
ignore_changes = [type, metadata, wait_for_service_account_token]
|
ignore_changes = [type, metadata, wait_for_service_account_token]
|
||||||
precondition {
|
precondition {
|
||||||
condition = local.secrets_contract_errors[each.key] == ""
|
condition = local.secrets_contract_errors[each.key] == ""
|
||||||
@ -413,8 +380,6 @@ resource "kubernetes_secret" "without_ignore" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Vault-sink: same resolved (plaintext) data map, written to Vault KV v2 instead
|
|
||||||
# of a Kubernetes Secret. Path = secret.vault_path (default <prefix>/<name>).
|
|
||||||
resource "vault_kv_secret_v2" "this" {
|
resource "vault_kv_secret_v2" "this" {
|
||||||
for_each = local.secrets_vault
|
for_each = local.secrets_vault
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user