diff --git a/infrastructure/security-audit/README.md b/infrastructure/security-audit/README.md index 151e6e7..5bde1e4 100644 --- a/infrastructure/security-audit/README.md +++ b/infrastructure/security-audit/README.md @@ -104,16 +104,13 @@ DaemonSet `audit-collector-agent` на узлах `node-role.kubernetes.io/contr rm /tmp/admin.properties ``` -3. **Vault** (`secrets/` — KV v2): - - секрет `secrets/data/security-audit/kafka` с ключами `username`, `password`, `ca_crt`; - `ca_crt` — содержимое `ca.crt` из Secret `kafka/kafka-kafka-contour-tls` (CA генерирует чарт `kafka-contour`, - срок 365 дней; при перевыпуске обновить и здесь); - - политика `read` на `secrets/data/security-audit/kafka`; - - роль `security-audit` в `auth/kubernetes`: bound SA `audit-collector` **и** `access-collector`, namespace - `security-audit`, политика выше. - - Заводится в `infra/terraform`, ветка `contour`, модуль `vault-platform-secrets` (роли `vault_kubernetes_auth_backend_role`, - KV-секреты). +3. **Креды Kafka — статические Secret'ы** в namespace `security-audit` (роли в Vault не заведены, агент-инжектор + не используется): + - Secret `security-audit-kafka` с ключами `username`, `password` (SCRAM-пользователь `security-audit`); + - Secret `kafka-ca` с ключом `ca.crt` — содержимое `ca.crt` из Secret `kafka/kafka-kafka-contour-tls` + (CA генерирует чарт `kafka-contour`, срок 365 дней; при перевыпуске обновить и здесь). + Оба монтируются projected volume'ом в `/vault/secrets` под именами `kafka-username`, `kafka-password`, + `kafka-ca.crt` — конфиг коллекторов (`${file:...}`, `ca_file`) не меняется. 4. **Образ** `cr.yandex/crp3ccidau046kdj8g9q/opentelemetry-collector/opentelemetry-collector-contrib:0.121.0-amd64` доступен в registry контура (тот же, что дефолт чарта `opentelemetry-collector-prod` 0.117.1), `regcred` есть в namespace `security-audit`. @@ -126,7 +123,7 @@ DaemonSet `audit-collector-agent` на узлах `node-role.kubernetes.io/contr - ../../infrastructure/security-audit/uralkal ``` -`dependsOn` в оверлее ждёт HelmRelease `kafka/kafka` и `vault/vault`. +`dependsOn` в оверлее ждёт HelmRelease `kafka/kafka`. Порядок: сначала должен раскататься провайдер `audit-access` в istiod (`infrastructure/istio-pilot/uralkal/istio-pilot.yaml`, применяется сразу, как только попадёт в master: кластер его уже подключает). Telemetry из `mesh/` ссылается на этот провайдер по имени. Проверка: @@ -260,9 +257,8 @@ spec: Метка `istio-injection: disabled` отключила бы инъекцию совсем, даже по метке пода. - `PeerAuthentication` в репозитории нет, поэтому режим PERMISSIVE. Шлюз шлёт в коллектор по auto-mTLS (оба в mesh), коллектор в Kafka — тоже через mTLS (`kafka` в mesh), внутри остаётся `SASL_SSL`. -- Vault Agent (`agent-init-first`, pre-populate) + istio-proxy: по паттерну контура (`apps/bi`, `apps/bim`, `apps/cde`…) - `traffic.sidecar.istio.io/excludeOutboundPorts: "8200"`. Init-агент ходит в Vault мимо iptables-перехвата, - даже если `istio-init` отработал раньше. +- Креды Kafka — статические Secret'ы (projected volume в `/vault/secrets`), Vault Agent не используется: + роли `security-audit` в Vault контура нет. - `holdApplicationUntilProxyStarts`: kafka exporter подключается к брокерам на старте и без готового proxy падает. - `istio-init` требует `NET_ADMIN`/`NET_RAW`: enforce `privileged` это разрешает, профиль `warn: baseline` даст предупреждения при создании подов — ожидаемо. @@ -382,8 +378,8 @@ HTTP-probe на pilot-agent `:15020`, а тот ходит в приложени - **Mesh.** Job в mesh (`sidecar.istio.io/inject=true`, `holdApplicationUntilProxyStarts`). В конце скрипт вызывает `POST 127.0.0.1:15020/quitquitquit`, istio-proxy завершается, под — `Completed`. STRICT mTLS у Zitadel сейчас нет, но Job к нему готов. -- **Vault:** роль `security-audit-bootstrap`, `secrets/data/security-audit/zitadel-bootstrap` → `pat` → - `/vault/secrets/zitadel-pat`; `excludeOutboundPorts: 8200` — паттерн контура. +- **PAT:** статический Secret в namespace `security-audit` (роли в Vault нет), монтируется в + `/vault/secrets/zitadel-pat`; имя Secret'а и ключа — в `job.yaml`, сверить с созданным в контуре. - **Скрипт** (`files/idp-actions-bootstrap.sh`, POSIX sh) идемпотентен: 1. ждёт `/debug/ready` (10 попыток × 15 с); 2. печатает все типы событий инстанса (`known: …`, `POST /admin/v1/events/types/_search`); @@ -405,10 +401,8 @@ HTTP-probe на pilot-agent `:15020`, а тот ходит в приложени - Топик `security.idp-events`: 3 партиции, `retention.ms=259200000`, RF по контуру, тем же путём, что остальные топики. Пользователь `security-audit`, ACL не нужны. - Сервисный пользователь Zitadel `security-audit-bootstrap` (machine user) с ролью `IAM_OWNER` на инстансе. - Нужны `action.target.read/write/delete`, `action.execution.read/write`, `events.read`. Его PAT — во Vault - `secrets/data/security-audit/zitadel-bootstrap`, ключ `pat`. -- Роль Vault `security-audit-bootstrap` в `auth/kubernetes`: bound SA `idp-actions-bootstrap`, namespace `security-audit`, - политика `read` на `secrets/data/security-audit/zitadel-bootstrap`. + Нужны `action.target.read/write/delete`, `action.execution.read/write`, `events.read`. Его PAT — ключ + в статическом Secret'е namespace `security-audit` (см. `base/idp-actions-bootstrap/job.yaml`). - Feature flag не нужен: в v4.12.2 `actions` в `/v2/features/instance` удалён (reserved), Actions v2 включены всегда. Проверка API изнутри кластера (ожидается `"https://login.sarex.local.uralkali.com"`): diff --git a/infrastructure/security-audit/base/helmrelease-access-collector.yaml b/infrastructure/security-audit/base/helmrelease-access-collector.yaml index b4a5642..04178b4 100644 --- a/infrastructure/security-audit/base/helmrelease-access-collector.yaml +++ b/infrastructure/security-audit/base/helmrelease-access-collector.yaml @@ -118,31 +118,24 @@ spec: sidecar.istio.io/inject: "true" # Kafka exporter подключается к брокерам на старте: без готового istio-proxy коллектор упадёт. proxy.istio.io/config: '{"holdApplicationUntilProxyStarts": true}' - # Паттерн контура для Vault + sidecar (apps/*/base): трафик агента к Vault мимо istio-proxy. - traffic.sidecar.istio.io/excludeOutboundPorts: "8200" - vault.hashicorp.com/agent-inject: "true" - vault.hashicorp.com/agent-init-first: "true" - vault.hashicorp.com/agent-pre-populate-only: "true" - vault.hashicorp.com/agent-requests-cpu: "25m" - vault.hashicorp.com/agent-limits-cpu: "100m" - vault.hashicorp.com/auth-path: auth/kubernetes - vault.hashicorp.com/role: security-audit - # Многострочные шаблоны — см. helmrelease-collector.yaml (toYaml | tpl в чарте). - vault.hashicorp.com/agent-inject-secret-kafka-username: secrets/data/security-audit/kafka - vault.hashicorp.com/agent-inject-template-kafka-username: |- - {{ "{{- with secret \"secrets/data/security-audit/kafka\" -}}" }} - {{ "{{ .Data.data.username }}" }} - {{ "{{- end -}}" }} - vault.hashicorp.com/agent-inject-secret-kafka-password: secrets/data/security-audit/kafka - vault.hashicorp.com/agent-inject-template-kafka-password: |- - {{ "{{- with secret \"secrets/data/security-audit/kafka\" -}}" }} - {{ "{{ .Data.data.password }}" }} - {{ "{{- end -}}" }} - vault.hashicorp.com/agent-inject-secret-kafka-ca.crt: secrets/data/security-audit/kafka - vault.hashicorp.com/agent-inject-template-kafka-ca.crt: |- - {{ "{{- with secret \"secrets/data/security-audit/kafka\" -}}" }} - {{ "{{ .Data.data.ca_crt }}" }} - {{ "{{- end -}}" }} + + # Креды Kafka — статические Secret'ы namespace (роли security-audit в Vault нет). + # Те же пути /vault/secrets/..., что читает конфиг: ${file:...} и ca_file. + extraVolumes: + - name: kafka-secrets + projected: + sources: + - secret: + name: security-audit-kafka + items: + - {key: username, path: kafka-username} + - {key: password, path: kafka-password} + - secret: + name: kafka-ca + items: + - {key: ca.crt, path: kafka-ca.crt} + extraVolumeMounts: + - {name: kafka-secrets, mountPath: /vault/secrets, readOnly: true} # Контур-специфичное (CONTOUR, KAFKA_BROKERS) задаётся в оверлее через extraEnvs. alternateConfig: diff --git a/infrastructure/security-audit/base/helmrelease-collector.yaml b/infrastructure/security-audit/base/helmrelease-collector.yaml index 6298027..380d53b 100644 --- a/infrastructure/security-audit/base/helmrelease-collector.yaml +++ b/infrastructure/security-audit/base/helmrelease-collector.yaml @@ -51,7 +51,7 @@ spec: create: false serviceAccount: create: true - name: audit-collector # = роль Vault security-audit, bound SA + name: audit-collector # bound SA роли Vault security-audit — если вернёмся на Vault Agent presets: logsCollection: {enabled: false} hostMetrics: {enabled: false} @@ -96,39 +96,31 @@ spec: hostPath: {path: /var/log/audit, type: DirectoryOrCreate} - name: otelcol-storage hostPath: {path: /var/lib/otelcol-audit, type: DirectoryOrCreate} + # Креды Kafka — статические Secret'ы namespace (роли security-audit в Vault нет). + # Projected volume складывает оба Secret'а в /vault/secrets под теми же именами файлов, + # что читает конфиг: ${file:/vault/secrets/kafka-username|kafka-password}, ca_file=kafka-ca.crt. + - name: kafka-secrets + projected: + sources: + - secret: + name: security-audit-kafka + items: + - {key: username, path: kafka-username} + - {key: password, path: kafka-password} + - secret: + name: kafka-ca + items: + - {key: ca.crt, path: kafka-ca.crt} extraVolumeMounts: - {name: audit-log, mountPath: /var/log/audit, readOnly: true} - {name: otelcol-storage, mountPath: /var/lib/otelcol-audit} + - {name: kafka-secrets, mountPath: /vault/secrets, readOnly: true} # Метка исключает под из webhook'а инъекции Istio ещё до мутации (namespace без istio-injection). podLabels: sidecar.istio.io/inject: "false" podAnnotations: sidecar.istio.io/inject: "false" - vault.hashicorp.com/agent-inject: "true" - vault.hashicorp.com/agent-init-first: "true" - vault.hashicorp.com/agent-pre-populate-only: "true" - vault.hashicorp.com/agent-requests-cpu: "25m" - vault.hashicorp.com/agent-limits-cpu: "100m" - vault.hashicorp.com/auth-path: auth/kubernetes - vault.hashicorp.com/role: security-audit - # Чарт рендерит podAnnotations через toYaml | tpl: однострочный шаблон toYaml переносит, - # и литерал {{ "..." }} рвётся. Поэтому по строке на действие (block scalar не переносится). - vault.hashicorp.com/agent-inject-secret-kafka-username: secrets/data/security-audit/kafka - vault.hashicorp.com/agent-inject-template-kafka-username: |- - {{ "{{- with secret \"secrets/data/security-audit/kafka\" -}}" }} - {{ "{{ .Data.data.username }}" }} - {{ "{{- end -}}" }} - vault.hashicorp.com/agent-inject-secret-kafka-password: secrets/data/security-audit/kafka - vault.hashicorp.com/agent-inject-template-kafka-password: |- - {{ "{{- with secret \"secrets/data/security-audit/kafka\" -}}" }} - {{ "{{ .Data.data.password }}" }} - {{ "{{- end -}}" }} - vault.hashicorp.com/agent-inject-secret-kafka-ca.crt: secrets/data/security-audit/kafka - vault.hashicorp.com/agent-inject-template-kafka-ca.crt: |- - {{ "{{- with secret \"secrets/data/security-audit/kafka\" -}}" }} - {{ "{{ .Data.data.ca_crt }}" }} - {{ "{{- end -}}" }} # Контур-специфичное (CONTOUR, KAFKA_BROKERS) задаётся в оверлее через extraEnvs. # Полный конфиг вместо мержа с дефолтами чарта. diff --git a/infrastructure/security-audit/base/idp-actions-bootstrap/job.yaml b/infrastructure/security-audit/base/idp-actions-bootstrap/job.yaml index 0a93ded..464dc96 100644 --- a/infrastructure/security-audit/base/idp-actions-bootstrap/job.yaml +++ b/infrastructure/security-audit/base/idp-actions-bootstrap/job.yaml @@ -19,19 +19,6 @@ spec: annotations: sidecar.istio.io/inject: "true" proxy.istio.io/config: '{"holdApplicationUntilProxyStarts": true}' - traffic.sidecar.istio.io/excludeOutboundPorts: "8200" # Vault мимо istio-proxy (паттерн контура) - vault.hashicorp.com/agent-inject: "true" - vault.hashicorp.com/agent-init-first: "true" - vault.hashicorp.com/agent-pre-populate-only: "true" - vault.hashicorp.com/agent-requests-cpu: "25m" - vault.hashicorp.com/agent-limits-cpu: "100m" - vault.hashicorp.com/auth-path: auth/kubernetes - vault.hashicorp.com/role: security-audit-bootstrap - vault.hashicorp.com/agent-inject-secret-zitadel-pat: secrets/data/security-audit/zitadel-bootstrap - vault.hashicorp.com/agent-inject-template-zitadel-pat: |- - {{- with secret "secrets/data/security-audit/zitadel-bootstrap" -}} - {{ .Data.data.pat }} - {{- end -}} spec: serviceAccountName: idp-actions-bootstrap restartPolicy: Never @@ -82,6 +69,7 @@ spec: - {name: script, mountPath: /scripts, readOnly: true} - {name: events, mountPath: /config, readOnly: true} - {name: tmp, mountPath: /tmp} + - {name: zitadel-pat, mountPath: /vault/secrets, readOnly: true} volumes: - {name: tools, emptyDir: {sizeLimit: 16Mi}} - {name: tmp, emptyDir: {medium: Memory, sizeLimit: 16Mi}} # заголовки с PAT — только в памяти @@ -89,3 +77,10 @@ spec: configMap: {name: idp-actions-bootstrap-script} - name: events configMap: {name: idp-actions-bootstrap-events} + # PAT machine user'а security-audit-bootstrap — статический Secret (роли в Vault нет). + # TODO(verify): имя Secret'а и ключа сверить с созданным в контуре; скрипт читает PAT_FILE=/vault/secrets/zitadel-pat. + - name: zitadel-pat + secret: + secretName: security-audit-kafka + items: + - {key: zitadel_pat, path: zitadel-pat} diff --git a/infrastructure/security-audit/base/networkpolicy.yaml b/infrastructure/security-audit/base/networkpolicy.yaml index 53f0d64..6f90119 100644 --- a/infrastructure/security-audit/base/networkpolicy.yaml +++ b/infrastructure/security-audit/base/networkpolicy.yaml @@ -1,4 +1,5 @@ -# Коллектору нужны только DNS, Kafka и Vault (агент-инжектор). Входящие — только health-check kubelet'а. +# Коллектору нужны только DNS и Kafka. Входящие — только health-check kubelet'а. +# (Раньше был egress в Vault для агента-инжектора; креды — статические Secret'ы.) apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: @@ -25,8 +26,3 @@ spec: ports: # client-листенер SASL_SSL: bootstrap kafka-kafka-contour и advertised-адреса подов controller-headless - {port: 9092, protocol: TCP} - - to: - - namespaceSelector: - matchLabels: {kubernetes.io/metadata.name: vault} - ports: - - {port: 8200, protocol: TCP} # vault-vault-contour.vault.svc:8200 (AGENT_INJECT_VAULT_ADDR) diff --git a/infrastructure/security-audit/uralkal/access-collector.yaml b/infrastructure/security-audit/uralkal/access-collector.yaml index 647fa82..5302192 100644 --- a/infrastructure/security-audit/uralkal/access-collector.yaml +++ b/infrastructure/security-audit/uralkal/access-collector.yaml @@ -7,8 +7,6 @@ spec: dependsOn: - name: kafka namespace: kafka - - name: vault - namespace: vault values: extraEnvs: - name: CONTOUR diff --git a/infrastructure/security-audit/uralkal/audit-collector.yaml b/infrastructure/security-audit/uralkal/audit-collector.yaml index c475ca8..23c8079 100644 --- a/infrastructure/security-audit/uralkal/audit-collector.yaml +++ b/infrastructure/security-audit/uralkal/audit-collector.yaml @@ -7,8 +7,6 @@ spec: dependsOn: - name: kafka namespace: kafka - - name: vault - namespace: vault values: extraEnvs: - name: CONTOUR