# 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//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.