Secrets Management

Where Secrets Should (Not) Live

PlaceOK?Notes
application.yml committed to GitNeverGit history keeps it forever, even after you delete it
Environment variablesOKsimple; set by Docker/Kubernetes/systemd; visible to the process
Kubernetes SecretsOKenable encryption at rest; mount as env vars or files
Secret manager (Vault, AWS Secrets Manager, GCP Secret Manager)Bestaudit log, rotation, fine-grained access

application.yml

Reference secrets with placeholders; the real values come from the environment:

spring:
  datasource:
    url: ${DB_URL}
    username: ${DB_USER}
    password: ${DB_PASSWORD}
  config:
    import: optional:file:.env[.properties]   # local dev only; .env is in .gitignore
shopease:
  jwt:
    secret: ${JWT_SECRET}

Secret Manager with Spring Cloud

application-prod.yml

With spring-cloud-gcp-starter-secretmanager (or Spring Cloud Vault / AWS), a secret is just another property source:

spring:
  config:
    import: sm@        # Spring Cloud GCP 5.x+
  datasource:
    password: ${sm@shopease-db-password}

Catch Leaks Before They Ship

gitleaks

Run a secret scanner in CI and as a pre-commit hook:

gitleaks detect --source . --no-banner

Example output

Finding:     password: Sh0pEase@Prod2026
Secret:      Sh0pEase@Prod2026
RuleID:      generic-password
File:        src/main/resources/application-prod.yml
Line:        14
Commit:      9f1c2ab4e7d3
Author:      ravi

10:42AM WRN leaks found: 1

Tip: If a secret is ever pushed, rotate it immediately (change the password, issue a new key). Rewriting Git history is not enough: forks, clones and CI caches still have it.