feat(security): External Secrets Operator + ClusterSecretStore на Vault #8

Merged
grachevko merged 1 commits from feat/external-secrets into main 2026-09-17 18:15:36 +00:00
7 changed files with 141 additions and 0 deletions
Showing only changes of commit b0678e5ccb - Show all commits
@@ -0,0 +1,26 @@
---
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: vault
spec:
provider:
vault:
# Внутрикластерный адрес, а не https://vault.<домен>: Vault слушает без TLS
# (tls_disable), а поход через шлюз потребовал бы ещё и доверия к internal-ca
# внутри ESO. Снаружи UI остаётся на https через envoy.
server: http://vault.security.svc:8200
path: kv
version: v2
auth:
kubernetes:
mountPath: kubernetes
role: eso
# Service account оператора: имя и namespace должны совпадать с
# bound_service_account_names/namespaces роли eso в Vault.
serviceAccountRef:
name: external-secrets
namespace: security
# Vault 1.21+ требует audience в роли, ESO по умолчанию просит "vault".
audiences:
- vault
@@ -0,0 +1,30 @@
---
# Проверочный ExternalSecret: доказывает всю цепочку ESO -> kubernetes-auth ->
# Vault -> Secret в кластере. Значение кладётся в Vault командой
# vault kv put kv/demo username=demo password=s3cr3t
# (key в ExternalSecret указывается без префикса path: demo -> kv/data/demo).
# Когда появятся настоящие потребители (токен вебхука Flux и приложения),
# этот объект можно удалить.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: vault-smoke
namespace: security
spec:
refreshInterval: 1h
secretStoreRef:
name: vault
kind: ClusterSecretStore
target:
name: vault-smoke
creationPolicy: Owner
deletionPolicy: Retain
data:
- secretKey: username
remoteRef:
key: demo
property: username
- secretKey: password
remoteRef:
key: demo
property: password
@@ -0,0 +1,36 @@
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: external-secrets
spec:
interval: 1h
chartRef:
kind: OCIRepository
name: external-secrets
install:
crds: CreateReplace
upgrade:
crds: CreateReplace
cleanupOnFail: true
remediation:
retries: 3
# Оператор без состояния: переустановка с нуля безопасна, поэтому при
# падении апгрейда релиз снимается и ставится заново, а не залипает.
strategy: uninstall
values:
replicaCount: 1
# CRD ставит и обновляет сам чарт.
installCRDs: true
# Валидирующий вебхук и его certController включены: сертификаты чарт
# выпускает и продлевает сам, cert-manager для этого не нужен.
webhook:
create: true
certController:
create: true
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
memory: 256Mi
@@ -0,0 +1,8 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./ocirepository.yaml
- ./helmrelease.yaml
- ./clustersecretstore.yaml
- ./externalsecret.yaml
@@ -0,0 +1,15 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: external-secrets
spec:
interval: 15m
layerSelector:
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
operation: copy
ref:
# Версия чарта external-secrets (равна appVersion). Релизы чарта тегируются
# как helm-chart-<version>, в ghcr публикуется тег без префикса.
tag: 2.10.0
url: oci://ghcr.io/external-secrets/charts/external-secrets
@@ -0,0 +1,25 @@
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: external-secrets
spec:
interval: 1h
path: ./kubernetes/apps/security/external-secrets/app
prune: true
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
targetNamespace: security
wait: true
healthChecks:
- apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
name: external-secrets
namespace: security
# Оператор ходит в Vault через kubernetes-auth, поэтому ждём готовности Vault.
# Обе Kustomization живут в ns security — dependsOn работает только внутри
# своего namespace, и здесь это выполняется.
dependsOn:
- name: vault
@@ -8,4 +8,5 @@ components:
resources:
- ./namespace.yaml
- ./external-secrets/ks.yaml
- ./vault/ks.yaml