How does Spring Cloud Kubernetes expose Kubernetes Secrets to the Environment, and what security defaults matter?
answer
- Secret = base64 (encoding, not encryption)
- SecretsPropertySource decodes into Environment
- enableApi=false by default -> prefer mounted paths
- API path needs RBAC get/watch on secrets
- env-injected secrets don't hot-update; volume does
basics
~10 sIt contributes a Secrets PropertySource so Secret keys become Spring properties. Secret values are base64-decoded automatically. Reading Secrets via the Kubernetes API is opt-in (enableApi); by default it reads Secrets from mounted file paths.
solid answer
~40 sA Kubernetes `Secret` is like a ConfigMap but for sensitive data, stored base64-encoded. Spring Cloud Kubernetes adds a `SecretsPropertySource` (`spring.cloud.kubernetes.secrets.*`) that decodes values and merges them into the `Environment`, so a DB password lands in `spring.datasource.password` like any property. Security nuance: consuming Secrets over the Kubernetes API is disabled by default (`enableApi=false`) because it requires broad RBAC and pulls secrets over the wire; the recommended path is to mount the Secret as a volume and point `spring.cloud.kubernetes.secrets.paths` at it, or use env vars. Names default to `spring.application.name`; `sources`, `namespace`, and label selectors let you target specific Secrets. Reload works for Secrets too when enabled.
code
yaml · 19 linesspring:
cloud:
kubernetes:
secrets:
enabled: true
enableApi: false # default; read from mounts, not the API
paths:
- /etc/secrets # where the Secret volume is mounted
# sources:
# - name: db-credentials
# namespace: prod
---
apiVersion: v1
kind: Secret
metadata:
name: orders-service
type: Opaque
data:
spring.datasource.password: c3VwZXItc2VjcmV0 # base64('super-secret')go deeper
Know Secrets become Spring properties and values are base64, not encrypted.
Explain enableApi default-off, mounted paths vs API mode, and RBAC implications.
Discuss precedence vs ConfigMaps, label selectors, reload behavior, and env-vs-volume update semantics.
Weigh Kubernetes Secrets vs external secret stores, /env actuator leakage, and RBAC blast radius in the threat model.
**What a Secret is.** A Kubernetes `Secret` mirrors a ConfigMap but is intended for sensitive values (passwords, tokens, keys). Its `data:` values are base64-encoded (encoding, NOT encryption — etcd encryption-at-rest is a separate cluster setting). **The Secrets property source.** Spring Cloud Kubernetes provides `SecretsPropertySource` / `KubernetesClientSecretsPropertySource`, configured under `spring.cloud.kubernetes.secrets.*`. It base64-decodes each value and contributes it to the `Environment`. So a Secret key `spring.datasource.password` becomes usable by `@Value("${spring.datasource.password}")` with no manual decoding. **Two consumption modes — the key security default:** 1. **Mounted volume / env (default, recommended).** Kubernetes projects the Secret into the pod filesystem (or env vars). Spring Cloud Kubernetes reads from `spring.cloud.kubernetes.secrets.paths` (a list of mount directories). No API call, no extra RBAC, secret never traverses the app's API connection. 2. **Kubernetes API (`spring.cloud.kubernetes.secrets.enableApi=true`, off by default).** The app calls the API to fetch the Secret. Convenient, but requires `get`/`list`/`watch` RBAC on `secrets` — a broad, high-value permission — so it is intentionally opt-in. **Targeting which Secret.** Like config: `name` (defaults to app name), `namespace`, `sources` (explicit list), and `labels` (a selector to pick Secrets by label). `enabled` defaults to `true`, but that only controls the property source; `enableApi` separately gates the API path. **Precedence.** Secret properties are contributed alongside ConfigMap properties. When the same key exists in both, ordering determines the winner; be deliberate — don't accidentally let a ConfigMap override a Secret. **Reload.** If `spring.cloud.kubernetes.reload.enabled=true` and Secrets monitoring is on, changing a Secret can fire a refresh just like a ConfigMap (event/watch mode needs `watch` RBAC on `secrets`; polling re-reads periodically). Note: a Secret mounted as a volume is eventually updated by the kubelet, but env-var-injected Secrets are NOT updated in a running container. **Gotchas.** - base64 is not security; protect via RBAC + etcd encryption + not logging values. - Enabling the API path widens RBAC — prefer mounted paths in production. - `@ConfigurationProperties` holding a password must be inside a `@RefreshScope`-managed bean (or be a `@ConfigurationProperties` bean, which is rebound) for reload to take effect. - Logging the whole `Environment` or a `/env` actuator endpoint can leak decoded secrets — sanitize. **When to use.** You keep secrets in Kubernetes and want them as first-class Spring properties. For stronger secret management many teams instead use an external store (Vault) — but that's a different integration.
- Why is reading Secrets via the Kubernetes API disabled by default?Because it requires granting the pod's service account `get`/`list`/`watch` on `secrets` — a powerful permission — and pulls secret material over the API connection. Mounting the Secret as a volume avoids both, so it's the safer default.
- Does Spring Cloud Kubernetes decrypt Secret values?It base64-decodes them (Kubernetes stores Secrets base64-encoded, not encrypted). Actual encryption at rest is a cluster-level etcd feature, independent of Spring.
saying these in an interview costs you the question
- Claiming base64 encoding is encryption / provides confidentiality
- Assuming API-mode secret reading is on by default
- Expecting env-var-injected secrets to hot-reload in a running container