Files

47 lines
2.9 KiB
Markdown

# secrets
Companion code for **Secrets in Spring Boot: Vault vs AWS Secrets Manager vs Kubernetes Secrets vs
Jasypt** on [ankurm.com](https://ankurm.com/spring-boot-secrets-management-vault-aws-kubernetes-jasypt/).
One small application that needs one database password, started nine different ways. Every
backend is exercised by a test, and each test writes the transcript the article quotes to `output/`.
There is no `docs/` folder: the explanations live in the article.
| Piece | Version | Checked against |
|---|---|---|
| Spring Boot | 4.1.2 | `maven-metadata.xml` for `spring-boot-starter-parent` |
| Spring Cloud | 2025.1.4 | `maven-metadata.xml` (2026.0.0 is RC only); 2025.1.2 added Boot 4.1 support per the release announcement |
| Spring Cloud Vault | 5.0.3 (pulls `spring-vault-core` 4.0.4) | `mvn dependency:tree` |
| Spring Cloud AWS | 4.2.1 (AWS SDK 2.57.0) | `maven-metadata.xml` |
| jasypt-spring-boot | 4.0.4 | `maven-metadata.xml` |
| Testcontainers | 2.0.5 | managed by Spring Boot 4.1.2 |
| Vault server | 2.2.1 (`hashicorp/vault:2.2.1`, dev mode) | `vault version` in the container |
| AWS emulator | moto 5.2.5 (`motoserver/moto:5.2.5`) | not AWS: no IAM, KMS or rotation Lambdas |
| JDK | 25 | Temurin 25.0.5 |
## Run it
```bash
export JAVA_HOME=/path/to/jdk-25
./scripts/run-all.sh # 9 tests (needs Docker), then the jar and /proc script
```
## What is where
| Transcript | Test or script | What it shows |
|---|---|---|
| `output/01-vault-import.txt` | `VaultImportTest` | `spring.config.import=vault://` binding a KV v2 secret, and the property source it creates |
| `output/02-vault-missing-and-denied.txt` | `VaultImportTest` | missing path, wrong token, unreachable Vault, `fail-fast`, `optional:` and the `strict` startup guard |
| `output/03-vault-rotation.txt` | `VaultRotationTest` | a rotated secret, `ContextRefresher`, record vs `@RefreshScope` |
| `output/04-vault-least-privilege.txt` | `VaultRotationTest`, `vault/app-read.hcl` | a token that can read two paths and nothing else |
| `output/05-aws-secrets-manager.txt` | `AwsSecretsManagerTest` | JSON secret import, version stages, polling reload, missing secret |
| `output/06-kubernetes-configtree.txt` | `KubernetesConfigtreeTest`, `k8s/*.yaml` | the kubelet's volume layout read by `configtree:`, and a swap |
| `output/07-jasypt.txt` | `JasyptTest` | `ENC(...)`, wrong and missing keys, decrypting outside Spring |
| `output/08-leaks.txt` | `LeaksTest` | record `toString`, actuator `env` and `configprops` |
| `output/09-dynamic-property-source-trap.txt` | `DynamicPropertyTrapTest` | why a Testcontainers `@DynamicPropertySource` does not reach the import |
| `output/10-exposure.txt` | `scripts/exposure.sh` | a secret in the jar, in `ps`, in `/proc/<pid>/environ` |
`k8s/secret.yaml` and `k8s/deployment-snippet.yaml` were **not applied to a cluster**; the volume
layout they produce is reproduced by hand in `KubernetesConfigtreeTest`. Timing figures and the AWS
polling result are indicative.