Files
panxiao81 5c2b575a4f
yaml / yaml (pull_request) Successful in 20s
ansible / collection-test (pull_request) Successful in 59s
ansible / lint (pull_request) Successful in 10m32s
feat(zot): 接入 SeaweedFS 与 SPIRE 并统一 S3 凭据来源
2026-09-14 13:26:54 +00:00

153 lines
5.1 KiB
YAML

# One ExternalSecret per Kubernetes Secret that was previously created by hand.
#
# These REPLACE the hand-applied secret.yaml files in ../../apps/authelia, ../../apps/gitea and
# ../../infrastructure/cloudflared. Those files stay gitignored as the break-glass copy — if OpenBao
# is down during a rebuild you can still `kubectl apply -f <svc>/secret.yaml` and
# carry on. ESO will reconcile back over it once bao returns.
#
# ⚠ ESO takes OWNERSHIP of the target Secret. The existing hand-created Secrets have
# the same names on purpose, so ESO adopts rather than duplicates them — but that
# also means a wrong key name here will OVERWRITE a working Secret with an empty or
# partial one. Check `kubectl get externalsecret -A` reports SecretSynced before
# trusting it, and remember Authelia and Gitea only read their secrets at startup.
#
# refreshInterval is deliberately long. Nothing here rotates on its own yet, and a
# short interval only adds load plus a wider window to notice a bad sync. When the
# OpenBao PostgreSQL secrets engine lands (see ../docs/cicd.md) the rotating
# credentials will want a shorter interval AND something to restart the consumer.
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: authelia-secrets
namespace: authelia
spec:
refreshInterval: 1h
secretStoreRef:
name: openbao
kind: ClusterSecretStore
target:
name: authelia-secrets
creationPolicy: Owner
# extract pulls EVERY key at the path, so the six key names live in OpenBao
# rather than being restated here. They must match the `path:` values in
# ../../apps/authelia/values.yaml exactly.
dataFrom:
- extract:
key: k8s/authelia
---
# Separate Secret, not a seventh key in authelia-secrets — the chart projects the
# existingSecret volume with an explicit items: list of only the six keys it
# generates, so an extra key would be stored but never mounted. That mistake took
# SSO down on 2026-07-28.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: authelia-oidc-jwks
namespace: authelia
spec:
refreshInterval: 1h
secretStoreRef:
name: openbao
kind: ClusterSecretStore
target:
name: authelia-oidc-jwks
creationPolicy: Owner
dataFrom:
- extract:
key: k8s/authelia-oidc-jwks
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: gitea-db
namespace: gitea
spec:
refreshInterval: 1h
secretStoreRef:
name: openbao
kind: ClusterSecretStore
target:
name: gitea-db
creationPolicy: Owner
dataFrom:
- extract:
key: k8s/gitea
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: cloudflared-tunnel
namespace: cloudflared
spec:
refreshInterval: 1h
secretStoreRef:
name: openbao
kind: ClusterSecretStore
target:
name: cloudflared-tunnel
creationPolicy: Owner
dataFrom:
- extract:
key: k8s/cloudflared
---
# SeaweedFS S3 identities, including the least-privilege `terraform` identity that
# holds Terraform remote state.
#
# ⚠ These credentials were previously INLINE in ../../apps/seaweedfs/values.yaml and went
# into git with the initial commit. Externalising stops the bleeding; the leaked
# anvAdmin key still needs rotating separately, since it is in history.
#
# The chart normally GENERATES seaweedfs-s3-secret from s3.credentials. We point
# filer.s3.existingConfigSecret at this one instead, so the chart stops rendering
# credentials from values entirely.
# zot 的 AK/SK 只保存在 k8s/zot-s3;在此组装服务端配置,不在基础配置中维护副本。
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: seaweedfs-s3-config
namespace: seaweedfs
spec:
refreshInterval: 1h
secretStoreRef:
name: openbao
kind: ClusterSecretStore
target:
name: seaweedfs-s3-config
creationPolicy: Owner
template:
engineVersion: v2
mergePolicy: Replace
data:
seaweedfs_s3_config: |-
{{- $config := mustFromJson .baseConfig -}}
{{- if not (kindIs "slice" $config.identities) -}}
{{- fail "base S3 configuration must contain an identities array" -}}
{{- end -}}
{{- if or (eq .zotAccessKey "") (eq .zotSecretKey "") -}}
{{- fail "zot S3 credentials must not be empty" -}}
{{- end -}}
{{- $identities := list -}}
{{- range $config.identities -}}
{{- if ne .name "zot" -}}
{{- $identities = append $identities . -}}
{{- end -}}
{{- end -}}
{{- $credential := dict "accessKey" .zotAccessKey "secretKey" .zotSecretKey -}}
{{- $zot := dict "name" "zot" "credentials" (list $credential) "actions" (list "Read:zot" "Write:zot" "List:zot" "Tagging:zot") -}}
{{- $_ := set $config "identities" (append $identities $zot) -}}
{{- mustToJson $config -}}
data:
- secretKey: baseConfig
remoteRef:
key: k8s/seaweedfs-s3
property: seaweedfs_s3_config
- secretKey: zotAccessKey
remoteRef:
key: k8s/zot-s3
property: access_key
- secretKey: zotSecretKey
remoteRef:
key: k8s/zot-s3
property: secret_key