++ contour: flat live/ (INFRA_ENV), port vault-platform-secrets module + namespace/vault-secrets units; drop product live/prod

This commit is contained in:
Kochetkov S 2026-07-16 16:18:00 +03:00
parent 128b7b4451
commit 98d9a29a6e
16 changed files with 1543 additions and 553 deletions

View File

@ -1,15 +0,0 @@
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
terraform {
backend "s3" {
access_key = ""
bucket = "tfstate-terragrunt-stage"
endpoint = "storage.yandexcloud.net"
force_path_style = true
key = "./terraform.tfstate"
region = "ru-central1"
secret_key = ""
skip_credentials_validation = true
skip_metadata_api_check = true
skip_region_validation = true
}
}

View File

@ -0,0 +1,50 @@
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"))
env_override = trimspace(get_env("INFRA_ENV", ""))
env_from_file = try(trimspace(local.infra_config.current_environment), "")
available_envs = sort(keys(try(local.infra_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
)
env_config = try(local.infra_config.environments[local.env_name], {})
}
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}/namespace/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//k8s-namespace"
}
inputs = {
namespaces = try(local.env_config.namespaces, [])
kubeconfig_path = get_env("KUBECONFIG", "")
kube_context = get_env("KUBE_CONTEXT", "")
}

View File

@ -1,31 +0,0 @@
include "root" {
path = find_in_parent_folders()
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "deep"
}
locals {
repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..")
infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml"))
env_name = basename(dirname(get_terragrunt_dir()))
env_config = local.infra_config.environments[local.env_name]
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules//yc-database"
}
inputs = {
databases = local.env_config.databases
yc_token = get_env("YC_TOKEN", "")
yc_service_account_key_file = get_env("YC_SERVICE_ACCOUNT_KEY_FILE", "")
yc_cloud_id = get_env("YC_CLOUD_ID", "")
yc_folder_id = get_env("YC_PROD_FOLDER_ID", get_env("YC_FOLDER_ID", ""))
kubeconfig_path = get_env("KUBECONFIG", "")
kube_context = get_env("KUBE_CONTEXT", "")
}

View File

@ -1,12 +0,0 @@
# Конфигурация для окружения prod
locals {
environment = "prod"
folder_id = get_env("YC_PROD_FOLDER_ID", "")
# Общие параметры для всех компонентов в prod
common_tags = {
Environment = "prod"
Project = "terraform"
ManagedBy = "terraform"
}
}

View File

@ -1,61 +0,0 @@
include "root" {
path = find_in_parent_folders()
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "deep"
}
locals {
repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..")
infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml"))
env_name = basename(dirname(get_terragrunt_dir()))
env_config = local.infra_config.environments[local.env_name]
kafka_topics = try(local.env_config.kafka.topics, [])
kafka_users = try(local.env_config.kafka.users, [])
kafka_cluster_refs = {
for ref, cfg in local.env_config.kafka_cluster_refs : ref => merge(cfg, {
cluster_id = startswith(tostring(cfg.cluster_id), "env:") ? get_env(trimprefix(tostring(cfg.cluster_id), "env:"), "") : tostring(cfg.cluster_id)
})
}
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules//kafka-topics-yc"
}
generate "import_existing" {
path = "import_existing.tf"
if_exists = "overwrite"
contents = join("\n\n", [
for user in local.kafka_users : <<-EOF
import {
to = yandex_mdb_kafka_user.this["${user.clusterRef}:${user.name}"]
id = "${local.kafka_cluster_refs[user.clusterRef].cluster_id}:${user.name}"
}
EOF
if try(user.adopt, false)
])
}
inputs = {
environment = local.env_name
topics = local.kafka_topics
users = local.kafka_users
kafka_cluster_refs = local.kafka_cluster_refs
kafka_policy = local.env_config.kafka_policy
create_users = true
default_user_roles = ["ACCESS_ROLE_PRODUCER", "ACCESS_ROLE_CONSUMER"]
user_password_length = 32
yc_token = get_env("YC_TOKEN", "")
yc_service_account_key_file = get_env("YC_SERVICE_ACCOUNT_KEY_FILE", "")
yc_cloud_id = get_env("YC_CLOUD_ID", "")
yc_folder_id = get_env("YC_PROD_FOLDER_ID", get_env("YC_FOLDER_ID", ""))
kubeconfig_path = get_env("KUBECONFIG", "")
kube_context = get_env("KUBE_CONTEXT", "")
}

View File

@ -1,31 +0,0 @@
include "root" {
path = find_in_parent_folders()
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "deep"
}
locals {
repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..")
infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml"))
env_name = basename(dirname(get_terragrunt_dir()))
env_config = local.infra_config.environments[local.env_name]
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules//k8s-namespace"
}
inputs = {
namespaces = local.env_config.namespaces
yc_token = get_env("YC_TOKEN", "")
yc_service_account_key_file = get_env("YC_SERVICE_ACCOUNT_KEY_FILE", "")
yc_cloud_id = get_env("YC_CLOUD_ID", "")
yc_folder_id = get_env("YC_PROD_FOLDER_ID", get_env("YC_FOLDER_ID", ""))
kubeconfig_path = get_env("KUBECONFIG", "")
kube_context = get_env("KUBE_CONTEXT", "")
}

View File

@ -1,52 +0,0 @@
include "root" {
path = find_in_parent_folders()
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "deep"
}
locals {
repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..")
infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml"))
env_name = basename(dirname(get_terragrunt_dir()))
env_var_prefix = upper(replace(local.env_name, "-", "_"))
env_config = local.infra_config.environments[local.env_name]
rabbitmq_config = try(local.env_config.rabbitmq, {})
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules//rabbitmq"
}
inputs = {
environment = local.env_name
management_endpoint = get_env("RABBITMQ_${local.env_var_prefix}_MANAGEMENT_ENDPOINT", try(local.rabbitmq_config.management_endpoint, ""))
management_username = get_env("RABBITMQ_${local.env_var_prefix}_MANAGEMENT_USERNAME", "")
management_password = get_env("RABBITMQ_${local.env_var_prefix}_MANAGEMENT_PASSWORD", "")
amqp_host = get_env("RABBITMQ_${local.env_var_prefix}_AMQP_HOST", try(local.rabbitmq_config.amqp_host, "rabbitmq.rabbitmq.svc.cluster.local"))
amqp_port = tonumber(get_env("RABBITMQ_${local.env_var_prefix}_AMQP_PORT", tostring(try(local.rabbitmq_config.amqp_port, 5672))))
rabbitmq_policy = try(local.rabbitmq_config.policy, {})
vhosts = try(local.rabbitmq_config.vhosts, [])
users = try(local.rabbitmq_config.users, [])
permissions = try(local.rabbitmq_config.permissions, [])
topic_permissions = try(local.rabbitmq_config.topic_permissions, [])
exchanges = try(local.rabbitmq_config.exchanges, [])
queues = try(local.rabbitmq_config.queues, [])
bindings = try(local.rabbitmq_config.bindings, [])
policies = try(local.rabbitmq_config.policies, [])
unmanaged_output_users = try(local.rabbitmq_config.unmanaged_output_users, [])
unmanaged_output_permissions = try(local.rabbitmq_config.unmanaged_output_permissions, [])
yc_token = get_env("YC_TOKEN", "")
yc_service_account_key_file = get_env("YC_SERVICE_ACCOUNT_KEY_FILE", "")
yc_cloud_id = get_env("YC_CLOUD_ID", "")
yc_folder_id = get_env("YC_PROD_FOLDER_ID", get_env("YC_FOLDER_ID", ""))
kubeconfig_path = get_env("KUBECONFIG", "")
kube_context = get_env("KUBE_CONTEXT", "")
}

View File

@ -1,33 +0,0 @@
include "root" {
path = find_in_parent_folders()
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "deep"
}
locals {
repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..")
infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml"))
env_name = basename(dirname(get_terragrunt_dir()))
env_config = local.infra_config.environments[local.env_name]
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules//yc-s3"
}
inputs = {
buckets = local.env_config.buckets
yc_service_accounts = try(local.env_config.yc_service_accounts, [])
folder_id = get_env("YC_PROD_FOLDER_ID", get_env("YC_FOLDER_ID", ""))
yc_token = get_env("YC_TOKEN", "")
yc_service_account_key_file = get_env("YC_SERVICE_ACCOUNT_KEY_FILE", "")
yc_cloud_id = get_env("YC_CLOUD_ID", "")
yc_folder_id = get_env("YC_PROD_FOLDER_ID", get_env("YC_FOLDER_ID", ""))
kubeconfig_path = get_env("KUBECONFIG", "")
kube_context = get_env("KUBE_CONTEXT", "")
}

View File

@ -1,224 +0,0 @@
include "root" {
path = find_in_parent_folders()
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "deep"
}
dependency "namespace" {
config_path = "../namespace"
mock_outputs = {
namespaces = {}
names = []
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
skip_outputs = get_env("TG_SKIP_DEPENDENCY_OUTPUTS", "false") == "true"
}
dependency "s3" {
config_path = "../s3"
mock_outputs = {
bucket_name = "mock-bucket"
access_key = "mock-access-key"
secret_key = "mock-secret-key"
buckets = {}
service_accounts = {}
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
skip_outputs = get_env("TG_SKIP_DEPENDENCY_OUTPUTS", "false") == "true"
}
dependency "database" {
config_path = "../database"
mock_outputs = {
database_outputs_map = {}
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
skip_outputs = get_env("TG_SKIP_DEPENDENCY_OUTPUTS", "false") == "true"
}
dependency "rabbitmq" {
config_path = "../rabbitmq"
mock_outputs = {
rabbitmq_outputs_map = {}
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
skip_outputs = get_env("TG_SKIP_DEPENDENCY_OUTPUTS", "false") == "true"
}
dependency "kafka_topics" {
config_path = "../kafka-topics"
mock_outputs = {
kafka_outputs_map = {}
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
skip_outputs = get_env("TG_SKIP_DEPENDENCY_OUTPUTS", "false") == "true"
}
dependency "valkey_users" {
config_path = "../valkey-users"
mock_outputs = {
valkey_outputs_map = {}
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
skip_outputs = get_env("TG_SKIP_DEPENDENCY_OUTPUTS", "false") == "true"
}
locals {
yc_postgresql_ca_cert = <<-EOT
-----BEGIN CERTIFICATE-----
MIIE3TCCAsWgAwIBAgIKPxb5sAAAAAAAFzANBgkqhkiG9w0BAQ0FADAfMR0wGwYD
VQQDExRZYW5kZXhJbnRlcm5hbFJvb3RDQTAeFw0xNzA2MjAxNjQ0MzdaFw0yNzA2
MjAxNjU0MzdaMFUxEjAQBgoJkiaJk/IsZAEZFgJydTEWMBQGCgmSJomT8ixkARkW
BnlhbmRleDESMBAGCgmSJomT8ixkARkWAmxkMRMwEQYDVQQDEwpZYW5kZXhDTENB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqgNnjk0JKPcbsk1+KG2t
eM1AfMnEe5RkAJuBBuwVV49snhcvO1jhKBx/pCnjr6biICc1/oAFDVgU8yVYYPwp
WZ2vH3ZtscjJ/RAT/NS9OKKG7kKknhFhVYxua5xhoIQmm6usBNYYiTcWoFm1eHC8
I9oddOLSscZYbh3unVRvt+3V+drVmUx9oSUKpqMgfysiv1MN6zB3vq9TFkbhz53E
k0tEcV+W2NnDaeFhLKy284FDKLvOdTDj1EDsSAihxl7sNEKpupNuhgyy2siOqUb+
d5mO/CRfaAKGg3E6hDM3pEi48E506dJdjPXWfHKSvuguMLRlb2RWdVocRZuyWxOh
0QIDAQABo4HkMIHhMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRMU5uItjx+
TOicX1+ovC1Xq2PSnzAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8E
BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSrucX/oe/mUx0zOSKE
0XbUN04tajBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vY3Jscy55YW5kZXgucnUv
WWFuZGV4SW50ZXJuYWxSb290Q0EvWWFuZGV4SW50ZXJuYWxSb290Q0EuY3JsMA0G
CSqGSIb3DQEBDQUAA4ICAQAsR5Lb4Pv2FD0Kk+4oc1GEOnehxKLsQtdV81nrU+IV
l9pr2oNMdi8lwIolvHZRllLM4Ba5AcRH6YJ5fe7AjKm+5EdSkhqVWo2UOllRCbtS
wmL50+erOAkxstSlRkO6b8x1L0MOBKv54E5YcQ/Wwt27ldSb6RkEmJBGvmxObAaf
5zc51pqSqao9tnldYaCblEQ/Zmy43FliIpa2eUJoh8DqK8bVo2gcI3wbQ32tWs9u
wvKk8fo4lAdhCwhv+QHuqau1VAY9hPU106bsFIDUmijTMxjAobKBi6CkIX6EbNHU
Jv4DzYVLlDd2y0CADdn2F6I70xpCBn5cquSGuvFbqZjQDmIHwb7WQSxadkiGRWfc
zVTnmiHjJONJJIpE2t+FOV3hc+8o98OzOtNaH2QQ9j6dnKvtIGKGFeNSDp0vXPOi
QhHiIyuB7eWx+g2whktQ74UCpGDSXYnEW3s8w5wezVWIEmouq7q4rCEkTNvJ7Ico
43AgUdPzAFS2zYktw1C+cbUALM8smvXbXrXOBzMmscjIhtXvLMrpPeh23VfdJfQB
0rN2BmRCLUE8JOV+o0k98XMm83oN+lGkL1l+hyoj3ok1uI3JrsWOcDyjOds3ptcN
KimJLm27ndjcxDNo/iA6gefMJuCxFRaqI+eF4P0jSkMgnnQqZkvLGFuHCw8eRDhm
bw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFGTCCAwGgAwIBAgIQJMM7ZIy2SYxCBgK7WcFwnjANBgkqhkiG9w0BAQ0FADAf
MR0wGwYDVQQDExRZYW5kZXhJbnRlcm5hbFJvb3RDQTAeFw0xMzAyMTExMzQxNDNa
Fw0zMzAyMTExMzUxNDJaMB8xHTAbBgNVBAMTFFlhbmRleEludGVybmFsUm9vdENB
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgb4xoQjBQ7oEFk8EHVGy
1pDEmPWw0Wgw5nX9RM7LL2xQWyUuEq+Lf9Dgh+O725aZ9+SO2oEs47DHHt81/fne
5N6xOftRrCpy8hGtUR/A3bvjnQgjs+zdXvcO9cTuuzzPTFSts/iZATZsAruiepMx
SGj9S1fGwvYws/yiXWNoNBz4Tu1Tlp0g+5fp/ADjnxc6DqNk6w01mJRDbx+6rlBO
aIH2tQmJXDVoFdrhmBK9qOfjxWlIYGy83TnrvdXwi5mKTMtpEREMgyNLX75UjpvO
NkZgBvEXPQq+g91wBGsWIE2sYlguXiBniQgAJOyRuSdTxcJoG8tZkLDPRi5RouWY
gxXr13edn1TRDGco2hkdtSUBlajBMSvAq+H0hkslzWD/R+BXkn9dh0/DFnxVt4XU
5JbFyd/sKV/rF4Vygfw9ssh1ZIWdqkfZ2QXOZ2gH4AEeoN/9vEfUPwqPVzL0XEZK
r4s2WjU9mE5tHrVsQOZ80wnvYHYi2JHbl0hr5ghs4RIyJwx6LEEnj2tzMFec4f7o
dQeSsZpgRJmpvpAfRTxhIRjZBrKxnMytedAkUPguBQwjVCn7+EaKiJfpu42JG8Mm
+/dHi+Q9Tc+0tX5pKOIpQMlMxMHw8MfPmUjC3AAd9lsmCtuybYoeN2IRdbzzchJ8
l1ZuoI3gH7pcIeElfVSqSBkCAwEAAaNRME8wCwYDVR0PBAQDAgGGMA8GA1UdEwEB
/wQFMAMBAf8wHQYDVR0OBBYEFKu5xf+h7+ZTHTM5IoTRdtQ3Ti1qMBAGCSsGAQQB
gjcVAQQDAgEAMA0GCSqGSIb3DQEBDQUAA4ICAQAVpyJ1qLjqRLC34F1UXkC3vxpO
nV6WgzpzA+DUNog4Y6RhTnh0Bsir+I+FTl0zFCm7JpT/3NP9VjfEitMkHehmHhQK
c7cIBZSF62K477OTvLz+9ku2O/bGTtYv9fAvR4BmzFfyPDoAKOjJSghD1p/7El+1
eSjvcUBzLnBUtxO/iYXRNo7B3+1qo4F5Hz7rPRLI0UWW/0UAfVCO2fFtyF6C1iEY
/q0Ldbf3YIaMkf2WgGhnX9yH/8OiIij2r0LVNHS811apyycjep8y/NkG4q1Z9jEi
VEX3P6NEL8dWtXQlvlNGMcfDT3lmB+tS32CPEUwce/Ble646rukbERRwFfxXojpf
C6ium+LtJc7qnK6ygnYF4D6mz4H+3WaxJd1S1hGQxOb/3WVw63tZFnN62F6/nc5g
6T44Yb7ND6y3nVcygLpbQsws6HsjX65CoSjrrPn0YhKxNBscF7M7tLTW/5LK9uhk
yjRCkJ0YagpeLxfV1l1ZJZaTPZvY9+ylHnWHhzlq0FzcrooSSsp4i44DB2K7O2ID
87leymZkKUY6PMDa4GkDJx0dG4UXDhRETMf+NkYgtLJ+UIzMNskwVDcxO4kVL+Hi
Pj78bnC5yCw8P5YylR45LdxLzLO68unoXOyFz1etGXzszw8lJI9LNubYxk77mK8H
LpuQKbSbIERsmR+QqQ==
-----END CERTIFICATE-----
EOT
repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..")
env_name = basename(dirname(get_terragrunt_dir()))
# Единый декларативный источник: форма + данные секретов в одном sops-файле
# infrastructure-secrets.yaml (шифруется только data). В CI файл расшифровывается
# заранее и путь передаётся через INFRA_SECRET_VALUES_FILE; локально - fallback
# на прямую расшифровку через sops_decrypt_file. Значения передаются в модуль
# только через inputs (эфемерно), чтобы расшифрованные данные не оседали на диске.
secret_values_env_file = get_env("INFRA_SECRET_VALUES_FILE", "")
secret_values_raw = local.secret_values_env_file != "" ? file(local.secret_values_env_file) : try(sops_decrypt_file("${local.repo_root}/infrastructure-secrets.yaml"), "")
secret_values_config = try(yamldecode(local.secret_values_raw), {})
secret_values_env = try(local.secret_values_config.environments[local.env_name], {})
secrets = try(local.secret_values_env.secrets, [])
# Нормализованный список для модуля. Ключ ресурса теперь namespace/name,
# resource_key больше не используется.
secrets_input = [
for secret in local.secrets : {
name = secret.name
namespace = secret.namespace
type = try(secret.type, "opaque")
registry_url = try(secret.registry_url, "")
data = try(secret.data, {})
depends_on = try(secret.depends_on, {})
yc_sa_key_names = try(secret.yc_sa_key_names, {})
custom_keys = try(secret.custom_keys, {})
constant_keys = try(secret.constant_keys, {})
random_keys = try(secret.random_keys, {})
credential_keys = try(secret.credential_keys, {})
labels = try(secret.labels, {})
annotations = try(secret.annotations, {})
ignore_changes = try(secret.lifecycle.ignore_changes, false)
}
]
}
generate "import_existing" {
path = "import_existing.tf"
if_exists = "overwrite"
contents = join("\n\n", [
for secret in local.secrets : <<-EOF
import {
to = kubernetes_secret.without_ignore["${secret.namespace}/${secret.name}"]
id = "${secret.namespace}/${secret.name}"
}
EOF
if try(secret.adopt, false) && try(secret.lifecycle.ignore_changes, false) == false
])
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules//k8s-secret"
}
inputs = {
secrets = local.secrets_input
s3_outputs = {
bucket_name = dependency.s3.outputs.bucket_name
access_key = dependency.s3.outputs.access_key
secret_key = dependency.s3.outputs.secret_key
}
s3_buckets_map = dependency.s3.outputs.buckets
yc_service_accounts_map = try(dependency.s3.outputs.service_accounts, {})
database_outputs_map = dependency.database.outputs.database_outputs_map
rabbitmq_outputs_map = try(dependency.rabbitmq.outputs.rabbitmq_outputs_map, {})
kafka_outputs_map = try(dependency.kafka_topics.outputs.kafka_outputs_map, {})
valkey_outputs_map = dependency.valkey_users.outputs.valkey_outputs_map
constants = {
s3_endpoint = "https://storage.yandexcloud.net"
postgres_port = "6432"
postgres_ca = local.yc_postgresql_ca_cert
valkey_port = "6380"
valkey_ca = local.yc_postgresql_ca_cert
}
env_vars = {
DOCKER_REGISTRY_USERNAME = get_env("DOCKER_REGISTRY_USERNAME", "")
DOCKER_REGISTRY_PASSWORD = get_env("DOCKER_REGISTRY_PASSWORD", "")
}
yc_token = get_env("YC_TOKEN", "")
yc_service_account_key_file = get_env("YC_SERVICE_ACCOUNT_KEY_FILE", "")
yc_cloud_id = get_env("YC_CLOUD_ID", "")
yc_folder_id = get_env("YC_PROD_FOLDER_ID", get_env("YC_FOLDER_ID", ""))
kubeconfig_path = get_env("KUBECONFIG", "")
kube_context = get_env("KUBE_CONTEXT", "")
}

View File

@ -1,31 +0,0 @@
include "root" {
path = find_in_parent_folders()
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "deep"
}
locals {
repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..")
infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml"))
env_name = basename(dirname(get_terragrunt_dir()))
env_config = local.infra_config.environments[local.env_name]
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules//yc-valkey-user"
}
inputs = {
valkey_users = try(local.env_config.valkey_users, [])
yc_token = get_env("YC_TOKEN", "")
yc_service_account_key_file = get_env("YC_SERVICE_ACCOUNT_KEY_FILE", "")
yc_cloud_id = get_env("YC_CLOUD_ID", "")
yc_folder_id = get_env("YC_PROD_FOLDER_ID", get_env("YC_FOLDER_ID", ""))
kubeconfig_path = get_env("KUBECONFIG", "")
kube_context = get_env("KUBE_CONTEXT", "")
}

View File

@ -1,63 +0,0 @@
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
terraform {
required_version = ">= 1.0"
required_providers {
yandex = {
source = "yandex-cloud/yandex"
version = "~> 0.100"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.23"
}
random = {
source = "hashicorp/random"
version = "~> 3.1"
}
}
}
provider "yandex" {
token = var.yc_token != "" ? var.yc_token : null
cloud_id = var.yc_cloud_id != "" ? var.yc_cloud_id : null
folder_id = var.yc_folder_id != "" ? var.yc_folder_id : null
zone = "ru-central1-a"
}
provider "kubernetes" {
# Если kubeconfig_path не указан, провайдер использует дефолтный путь ~/.kube/config
# Если указан, берем только первый путь (KUBECONFIG может содержать несколько путей через :)
config_path = var.kubeconfig_path != "" ? split(":", var.kubeconfig_path)[0] : null
config_context = var.kube_context != "" ? var.kube_context : null
}
variable "yc_token" {
type = string
default = ""
description = "Yandex Cloud token"
}
variable "yc_cloud_id" {
type = string
default = ""
description = "Yandex Cloud ID"
}
variable "yc_folder_id" {
type = string
default = ""
description = "Yandex Cloud folder ID"
}
variable "kubeconfig_path" {
type = string
default = ""
description = "Path to kubeconfig file"
}
variable "kube_context" {
type = string
default = ""
description = "Kubernetes context"
}

View File

@ -0,0 +1,69 @@
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"
secrets_config = try(yamldecode(sops_decrypt_file(local.secrets_file)), {})
env_override = trimspace(get_env("INFRA_ENV", ""))
env_from_file = try(trimspace(local.infra_config.current_environment), "")
available_envs = sort(keys(try(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
)
env_config = try(local.secrets_config.environments[local.env_name], {})
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")
common = try(local.vault_config.common, {})
infra = try(local.vault_config.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)
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
output "common_secret_paths" {
description = "Paths of created common Vault secrets"
value = compact([
try(vault_kv_secret_v2.common_regcred[0].name, ""),
try(vault_kv_secret_v2.common_smtp_auth[0].name, ""),
try(vault_kv_secret_v2.common_django_auth[0].name, ""),
try(vault_kv_secret_v2.common_rsa_keys[0].name, "")
])
}
output "infra_secret_paths" {
description = "Paths of created infrastructure Vault secrets"
value = concat(
compact([
try(vault_kv_secret_v2.postgresql_admin[0].name, ""),
try(vault_kv_secret_v2.postgresql_s3[0].name, ""),
try(vault_kv_secret_v2.postgresql_users[0].name, ""),
try(vault_kv_secret_v2.rabbitmq_auth[0].name, ""),
try(vault_kv_secret_v2.minio_admin[0].name, ""),
try(vault_kv_secret_v2.kafka_bootstrap[0].name, ""),
try(vault_kv_secret_v2.zitadel_postgresql[0].name, ""),
try(vault_kv_secret_v2.camunda_identity_components[0].name, ""),
try(vault_kv_secret_v2.camunda_identity_firstuser[0].name, ""),
try(vault_kv_secret_v2.camunda_keycloak_admin[0].name, ""),
try(vault_kv_secret_v2.camunda_postgresql[0].name, ""),
try(vault_kv_secret_v2.keycloak_admin[0].name, ""),
try(vault_kv_secret_v2.keycloak_postgresql[0].name, "")
]),
[for s in values(vault_kv_secret_v2.postgresql_apps) : s.name],
[for s in values(vault_kv_secret_v2.rabbitmq_apps) : s.name],
[for s in values(vault_kv_secret_v2.minio_apps) : s.name],
[for s in values(vault_kv_secret_v2.kafka_apps) : s.name]
)
}
output "infra_policy_names" {
description = "Created infrastructure Vault policy names"
value = keys(vault_policy.infra)
}
output "infra_role_names" {
description = "Created infrastructure Vault kubernetes auth role names"
value = [for r in values(vault_kubernetes_auth_backend_role.infra) : r.role_name]
}
output "app_policy_names" {
description = "Created application Vault policy names"
value = keys(vault_policy.app)
}
output "app_role_names" {
description = "Created application Vault kubernetes auth role names"
value = [for r in values(vault_kubernetes_auth_backend_role.app) : r.role_name]
}

View File

@ -0,0 +1,95 @@
variable "vault_kv_mount" {
description = "Vault KV v2 mount"
type = string
default = "secrets"
}
variable "path_prefix" {
description = "Path prefix inside Vault mount"
type = string
default = "platform"
}
variable "common" {
description = "Common platform secret configuration"
type = any
default = {}
}
variable "infra" {
description = "Infrastructure services secret/policy/role configuration"
type = any
default = {}
}
variable "applications" {
description = "Application Vault access roles/policies configuration"
type = any
default = {}
}
variable "create_regcred" {
description = "Create common dockerhub regcred secret"
type = bool
default = true
}
variable "create_smtp_auth" {
description = "Create common SMTP auth secret"
type = bool
default = true
}
variable "create_django_auth" {
description = "Create common django-auth secret"
type = bool
default = true
}
variable "create_rsa_keys" {
description = "Create common RSA key pair secret"
type = bool
default = true
}
variable "create_infra_secrets" {
description = "Create infrastructure service secrets"
type = bool
default = true
}
variable "create_infra_policies" {
description = "Create infrastructure Vault policies"
type = bool
default = true
}
variable "create_infra_roles" {
description = "Create infrastructure Vault kubernetes auth roles"
type = bool
default = true
}
variable "create_app_policies" {
description = "Create application Vault policies"
type = bool
default = true
}
variable "create_app_roles" {
description = "Create application Vault kubernetes auth roles"
type = bool
default = true
}
variable "kubernetes_auth_backend" {
description = "Vault kubernetes auth backend path"
type = string
default = "kubernetes"
}
variable "default_rsa_bits" {
description = "Default RSA key size"
type = number
default = 4096
}

View File

@ -0,0 +1,3 @@
terraform {
required_version = ">= 1.5.0"
}