security-audit: add audit-processor — ship apiserver audit from Kafka to MinIO (Parquet)
base/processor-*.yaml: Deployment (1 replica, image k8s-audit-processor:394b6f9d), ConfigMap with config.yaml, ServiceAccount, NetworkPolicy (DNS, kafka:9092, external MinIO 10.133.0.245:9000). Contour-specific values for uralkal are set via env patch in the overlay (K8S_AUDIT_*), same pattern as the collectors. Credentials reuse the static Secrets (security-audit-kafka, kafka-ca, security-audit-minio) via a projected volume at /vault/secrets. app.env=stand: the contour's external MinIO has no TLS, so strict validation (minio.secure) would fail. log.s3_echo=true is temporary for flow verification (per security req. 20: disable after debugging).
This commit is contained in:
parent
9cb62ea9f0
commit
1960ef495c
@ -10,21 +10,24 @@
|
||||
| журнал аудита Vault | sidecar `audit-shipper` в подах Vault → `access-collector`, pipeline `logs/vault` | `security.vault-audit` |
|
||||
|
||||
Одно сообщение — одна запись в JSON (`encoding: raw`, без OTLP-обёртки), обогащённая полями `sarex_*`.
|
||||
Дальнейшие этапы (processor → MinIO/Parquet) — отдельными компонентами.
|
||||
Processor (`audit-processor`, образ `k8s-audit-processor` из `infra/k8s-audit`) читает топик
|
||||
`security.k8s-audit` и пишет события в MinIO (Parquet, `events/contour=<c>/dt=…/hour=…`). Его манифесты —
|
||||
`base/processor-*.yaml`, контур-специфика (CONTOUR, брокеры, endpoint MinIO, `log.s3_echo`) — env-патчем
|
||||
в оверлее. Секреты — те же статические Secret'ы, что у коллекторов, плюс `security-audit-minio`.
|
||||
|
||||
С observability-коллектором (`infrastructure/opentelemetry-collector`) не связан: отдельный релиз, namespace и конфиг.
|
||||
|
||||
| Каталог | Что | Namespace |
|
||||
|---|---|---|
|
||||
| `base/` | оба коллектора, NetworkPolicy, AuthorizationPolicy, Namespace | `security-audit` |
|
||||
| `base/` | оба коллектора, audit-processor, NetworkPolicy, AuthorizationPolicy, Namespace | `security-audit` |
|
||||
| `base/idp-actions-bootstrap/` | Job настройки Target/Execution'ов в Zitadel, скрипт и список событий (**сейчас отключён** в `base/kustomization.yaml` — отложено, нет PAT) | `security-audit` |
|
||||
| `mesh/` | EnvoyFilter и Telemetry шлюза; без `namespace` в kustomization, селектор шлюза — заглушка | `istio-system` |
|
||||
| `uralkal/` | оверлей: `base` + `mesh`, селектор шлюза, Kafka, `dependsOn` | — |
|
||||
| `uralkal/` | оверлей: `base` + `mesh`, селектор шлюза, Kafka, `dependsOn`, env audit-processor'а | — |
|
||||
| `../vault/uralkal-audit/` | Vault-часть журнала аудита Vault: оверлей поверх `vault/uralkal` (не подключён) | `vault` |
|
||||
|
||||
| Оверлей | Статус |
|
||||
|---|---|
|
||||
| `uralkal` | манифесты готовы, **в `clusters/uralkal` не подключён** |
|
||||
| `uralkal` | подключён в `clusters/uralkal` |
|
||||
|
||||
## Журнал аудита kube-apiserver
|
||||
|
||||
|
||||
@ -8,6 +8,10 @@ resources:
|
||||
- authorizationpolicy-access-collector.yaml
|
||||
- helmrelease-collector.yaml
|
||||
- helmrelease-access-collector.yaml
|
||||
- processor-serviceaccount.yaml
|
||||
- processor-configmap.yaml
|
||||
- processor-deployment.yaml
|
||||
- processor-networkpolicy.yaml
|
||||
# События Zitadel отложены: нет PAT machine user'а security-audit-bootstrap (роли в Vault нет,
|
||||
# статический Secret не заведён). Обратное включение: раскомментировать здесь и патч
|
||||
# idp-actions-bootstrap.yaml в оверлее uralkal, добавить ключ zitadel_pat в Secret.
|
||||
|
||||
62
infrastructure/security-audit/base/processor-configmap.yaml
Normal file
62
infrastructure/security-audit/base/processor-configmap.yaml
Normal file
@ -0,0 +1,62 @@
|
||||
# Конфиг audit-processor (образ k8s-audit-processor, CONFIG_PATH=/etc/k8s-audit/config.yaml).
|
||||
# Контур-специфичные значения (contour, kafka.brokers, minio.endpoint, app.env, log.s3_echo)
|
||||
# задаёт оверлей через env K8S_AUDIT_* — см. uralkal/kustomization.yaml.
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: audit-processor-config
|
||||
labels:
|
||||
app.kubernetes.io/name: audit-processor
|
||||
data:
|
||||
config.yaml: |
|
||||
contour: "" # K8S_AUDIT_CONTOUR
|
||||
|
||||
app:
|
||||
name: audit-processor
|
||||
env: dev # K8S_AUDIT_APP_ENV
|
||||
|
||||
log:
|
||||
level: info
|
||||
output: stdout
|
||||
add_source: false
|
||||
access_log: true
|
||||
audit_events: false # поток ИБ не идёт в прикладные логи (п.20)
|
||||
s3_echo: false # K8S_AUDIT_LOG_S3_ECHO; только отладка (п.20)
|
||||
|
||||
kafka:
|
||||
brokers: [] # K8S_AUDIT_KAFKA_BROKERS
|
||||
topic: security.k8s-audit
|
||||
group: security-audit-processor
|
||||
start_from: earliest # latest перескочил бы события после разрыва offset'ов
|
||||
session_timeout: 45s
|
||||
rebalance_timeout: 60s
|
||||
tls:
|
||||
enabled: true
|
||||
ca_file: /vault/secrets/kafka-ca.crt
|
||||
sasl:
|
||||
mechanism: SCRAM-SHA-512
|
||||
username_file: /vault/secrets/kafka-username
|
||||
password_file: /vault/secrets/kafka-password
|
||||
|
||||
minio:
|
||||
endpoint: "" # K8S_AUDIT_MINIO_ENDPOINT
|
||||
bucket: security-audit
|
||||
secure: false # внешний MinIO контура — plain HTTP (ServiceEntry minio.uralkal.external)
|
||||
access_key_file: /vault/secrets/minio-access-key
|
||||
secret_key_file: /vault/secrets/minio-secret-key
|
||||
|
||||
# Срок хранения обеспечивает ILM бакета; processor только проверяет правила при старте.
|
||||
retention:
|
||||
days: 90
|
||||
prefixes: [events/, changes/]
|
||||
check_on_start: true
|
||||
|
||||
http:
|
||||
host: 0.0.0.0
|
||||
port: 8000 # /healthz, /readyz, /metrics
|
||||
|
||||
stream:
|
||||
flush_interval: 5m
|
||||
flush_max_rows: 10000
|
||||
flush_timeout: 30s # меньше kafka.rebalance_timeout
|
||||
max_flush_failures: 30
|
||||
73
infrastructure/security-audit/base/processor-deployment.yaml
Normal file
73
infrastructure/security-audit/base/processor-deployment.yaml
Normal file
@ -0,0 +1,73 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: audit-processor
|
||||
labels:
|
||||
app.kubernetes.io/name: audit-processor
|
||||
spec:
|
||||
replicas: 1 # consumer group: партиция security.k8s-audit одна, вторая реплика была бы standby
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: audit-processor
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: audit-processor
|
||||
# Без sidecar: в Kafka процессор ходит напрямую SASL_SSL (как audit-collector),
|
||||
# во внешний MinIO — мимо mesh (ServiceEntry, HTTP).
|
||||
sidecar.istio.io/inject: "false"
|
||||
annotations:
|
||||
sidecar.istio.io/inject: "false"
|
||||
spec:
|
||||
serviceAccountName: audit-processor
|
||||
imagePullSecrets:
|
||||
- name: regcred
|
||||
securityContext:
|
||||
seccompProfile: {type: RuntimeDefault}
|
||||
containers:
|
||||
- name: audit-processor
|
||||
# Образ FROM scratch, USER 65534; CONFIG_PATH=/etc/k8s-audit/config.yaml — в ENTRYPOINT образа.
|
||||
image: cr.yandex/crp3ccidau046kdj8g9q/k8s-audit-processor:394b6f9d
|
||||
ports:
|
||||
- {name: http, containerPort: 8000}
|
||||
readinessProbe:
|
||||
httpGet: {path: /readyz, port: http}
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet: {path: /healthz, port: http}
|
||||
periodSeconds: 20
|
||||
resources:
|
||||
requests: {cpu: 50m, memory: 128Mi}
|
||||
limits: {cpu: 500m, memory: 512Mi}
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65534
|
||||
runAsGroup: 65534
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: [ALL]
|
||||
volumeMounts:
|
||||
- {name: config, mountPath: /etc/k8s-audit, readOnly: true}
|
||||
# Те же Secret'ы и имена файлов, что у коллекторов (плюс ключи MinIO).
|
||||
- {name: secrets, mountPath: /vault/secrets, readOnly: true}
|
||||
volumes:
|
||||
- name: config
|
||||
configMap: {name: audit-processor-config}
|
||||
- name: 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}
|
||||
- secret:
|
||||
name: security-audit-minio
|
||||
items:
|
||||
- {key: access_key, path: minio-access-key}
|
||||
- {key: secret_key, path: minio-secret-key}
|
||||
@ -0,0 +1,34 @@
|
||||
# Процессору нужны: Kafka (чтение топика), внешний MinIO (запись Parquet), DNS.
|
||||
# Входящие — только пробы и метрики (:8000). Складывается с общей политикой audit-collector
|
||||
# (podSelector {}): её правила DNS и Kafka дублировать не обязательно, но оставляем автономность.
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: audit-processor
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: audit-processor
|
||||
policyTypes: [Ingress, Egress]
|
||||
ingress:
|
||||
- ports:
|
||||
- {port: 8000, protocol: TCP} # /healthz, /readyz (kubelet), /metrics
|
||||
egress:
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels: {kubernetes.io/metadata.name: kube-system}
|
||||
podSelector:
|
||||
matchLabels: {k8s-app: kube-dns}
|
||||
- ipBlock: {cidr: 169.254.25.10/32} # nodelocaldns kubespray
|
||||
ports:
|
||||
- {port: 53, protocol: UDP}
|
||||
- {port: 53, protocol: TCP}
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels: {kubernetes.io/metadata.name: kafka}
|
||||
ports:
|
||||
- {port: 9092, protocol: TCP} # client-листенер SASL_SSL
|
||||
- to:
|
||||
- ipBlock: {cidr: 10.133.0.245/32} # внешний MinIO контура (minio.uralkal.external)
|
||||
ports:
|
||||
- {port: 9000, protocol: TCP}
|
||||
@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: audit-processor
|
||||
labels:
|
||||
app.kubernetes.io/name: audit-processor
|
||||
@ -31,3 +31,28 @@ patches:
|
||||
- op: replace
|
||||
path: /spec/ingress/0/from/0/podSelector/matchLabels
|
||||
value: {istio: ingressgateway}
|
||||
# Контур-специфика audit-processor (Kafka → MinIO/Parquet).
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: audit-processor
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/env
|
||||
value:
|
||||
- name: K8S_AUDIT_CONTOUR
|
||||
value: uralkal
|
||||
# MinIO контура — внешний, без TLS: strict-валидация (app.env ∉ dev/local/stand)
|
||||
# не пройдёт по minio.secure. Послабления стенда при этом используются только здесь:
|
||||
# Kafka по-прежнему TLS+SASL, start_from earliest.
|
||||
- name: K8S_AUDIT_APP_ENV
|
||||
value: stand
|
||||
# Отладочное эхо записанных в S3 событий в stdout. Только на время запуска (п.20):
|
||||
# после проверки потока выключить (false) и убрать комментарий.
|
||||
- name: K8S_AUDIT_LOG_S3_ECHO
|
||||
value: "true"
|
||||
# Service чарта kafka-contour; тот же адрес у коллекторов и приложений.
|
||||
- name: K8S_AUDIT_KAFKA_BROKERS
|
||||
value: kafka-kafka-contour.kafka.svc.cluster.local:9092
|
||||
# Внешний MinIO (ServiceEntry minio.uralkal.external в istio-config).
|
||||
- name: K8S_AUDIT_MINIO_ENDPOINT
|
||||
value: 10.133.0.245:9000
|
||||
|
||||
Loading…
Reference in New Issue
Block a user