Secrets and Encryption

Encrypted Values in Git

Never put plain passwords or API keys in the config repo. Config Server can store them encrypted and decrypt them before sending to the service. Set a key on the server (from an environment variable):

# config-server application.yml
encrypt:
  key: ${CONFIG_ENCRYPT_KEY}     # long random string, kept outside Git

Example

Encrypt a value with the server's /encrypt endpoint and paste it with the {cipher} prefix:

curl -s localhost:8888/encrypt -d 'rzp_live_SecretKey123'

Example output

8f6c1a3e9b2d47e0c5a1f4b8d2e6c9a07b3f5e1d9c4a2b6e8f0d3c7a1b5e9f2c
# payment-service-prod.yml in the config repo
razorpay:
  key-id: rzp_live_AbCdEf123
  key-secret: '{cipher}8f6c1a3e9b2d47e0c5a1f4b8d2e6c9a07b3f5e1d9c4a2b6e8f0d3c7a1b5e9f2c'

Note: Quote the value: { has a special meaning in YAML. The service receives the decrypted value, so the Config Server itself must be protected.

Protect the Config Server

  • Run it on the private network only.
  • Add spring-boot-starter-security with a username/password, and give it to clients: spring.config.import: "configserver:http://config:${CONFIG_PASSWORD}@config-server:8888" (or spring.cloud.config.username / password).
  • For serious secret management use HashiCorp Vault (Config Server has a vault backend), AWS Secrets Manager or Kubernetes Secrets.
  • Disable /encrypt and /decrypt from outside, or anyone can decrypt your secrets.

Exercise

Exercise: payment-service must start ONLY if it gets its config (no silent fallback to local values) and should retry 6 times while the Config Server starts. Write its client config.

Show answer
spring:
  application:
    name: payment-service
  config:
    import: "configserver:http://config-server:8888"   # no "optional:"
  cloud:
    config:
      fail-fast: true
      retry:
        max-attempts: 6
        initial-interval: 1000
        multiplier: 1.5
# needs spring-retry + spring-boot-starter-aop on the classpath for retry