Skip to main content

Overview

Proper secret management is critical for maintaining the security of your infrastructure. The SGIVU Config Repository uses a combination of environment variable placeholders and external secret managers to keep sensitive data out of version control.
Never commit real secrets to YAML files. All sensitive values must be externalized using environment variables or secret management systems.

Core Principles

Externalize Secrets

Use environment variable placeholders for all sensitive data

Provide Defaults

Include safe defaults for development environments

Separate by Environment

Use different secrets for dev, staging, and production

Private Repository

Maintain strict access control on the config repository

Environment Variable Placeholders

Syntax

Spring Cloud Config supports the placeholder syntax ${VAR_NAME:default} where:
  • VAR_NAME is the environment variable to read
  • default is an optional fallback value (can be omitted for required secrets)

Examples from the Repository

Database Credentials

In sgivu-auth-dev.yml:
spring:
  datasource:
    url: jdbc:postgresql://${DEV_AUTH_DB_HOST:host.docker.internal}:${DEV_AUTH_DB_PORT:5432}/${DEV_AUTH_DB_NAME}
    username: ${DEV_AUTH_DB_USERNAME}
    password: ${DEV_AUTH_DB_PASSWORD}
Notice how DEV_AUTH_DB_HOST and DEV_AUTH_DB_PORT have defaults for local Docker development, while DEV_AUTH_DB_NAME, DEV_AUTH_DB_USERNAME, and DEV_AUTH_DB_PASSWORD are required and have no defaults.

OAuth2 Client Secrets

In sgivu-gateway.yml:
spring:
  security:
    oauth2:
      client:
        registration:
          sgivu-gateway:
            client-secret: ${SGIVU_GATEWAY_SECRET}

Internal Service Keys

In sgivu-auth.yml:
gateway-client:
  url: ${SGIVU_GATEWAY_URL:http://sgivu-gateway:8080}
  secret: ${SGIVU_GATEWAY_SECRET}

service:
  internal:
    secret-key: ${SERVICE_INTERNAL_SECRET_KEY}

JWT Keystore Configuration

In sgivu-auth.yml:
sgivu:
  jwt:
    keystore:
      location: ${JWT_KEYSTORE_LOCATION}
      password: ${JWT_KEYSTORE_PASSWORD}
    key:
      alias: ${JWT_KEY_ALIAS}
      password: ${JWT_KEY_PASSWORD}
Use descriptive variable names that indicate the environment and purpose, like DEV_AUTH_DB_PASSWORD instead of just DB_PASSWORD.

Local Development with .env Files

For local development, create a .env file in your sgivu-docker-compose directory:
# Database credentials
DEV_AUTH_DB_NAME=sgivu_auth_dev
DEV_AUTH_DB_USERNAME=sgivu_dev
DEV_AUTH_DB_PASSWORD=dev_password_123

# Service secrets
SGIVU_GATEWAY_SECRET=gateway_secret_dev
SERVICE_INTERNAL_SECRET_KEY=internal_key_dev

# Redis
REDIS_PASSWORD=redis_dev_password

# JWT Configuration
JWT_KEYSTORE_LOCATION=classpath:keystore.jks
JWT_KEYSTORE_PASSWORD=keystore_password
JWT_KEY_ALIAS=sgivu-jwt
JWT_KEY_PASSWORD=key_password
Add .env to your .gitignore to prevent accidentally committing local secrets.

Separating Secrets by Environment

Use environment-specific variable names to prevent cross-environment contamination:
1

Development

Use DEV_ prefix for all development secrets
username: ${DEV_AUTH_DB_USERNAME}
password: ${DEV_AUTH_DB_PASSWORD}
2

Production

Use PROD_ prefix for all production secrets
username: ${PROD_AUTH_DB_USERNAME}
password: ${PROD_AUTH_DB_PASSWORD}
3

Validate Separation

Ensure no service can accidentally use production credentials in development by keeping variable names distinct

External Secret Managers

For production environments, consider integrating with external secret management systems:

AWS Secrets Manager

Store secrets in AWS and reference them via Spring Cloud AWS

HashiCorp Vault

Centralized secret storage with dynamic credentials

Azure Key Vault

Azure-native secret management solution

Kubernetes Secrets

Built-in Kubernetes secret management for containerized deployments

Integration Pattern

  1. Store secrets in your secret manager
  2. Configure the Config Server to read from the secret manager
  3. Use the same placeholder syntax in YAML files
  4. Let Spring Cloud Config resolve secrets at runtime

Common Mistakes to Avoid

Hardcoded Secrets

Never do this:
spring:
  datasource:
    password: MyP@ssw0rd123  # ❌ Hardcoded secret
Always do this:
spring:
  datasource:
    password: ${PROD_AUTH_DB_PASSWORD}  # ✅ Externalized

Committing .env Files

Local .env files should never be committed to version control. Always add them to .gitignore.

Using Production Secrets in Development

Never reuse production credentials in development environments. Always maintain separate secrets with environment-specific prefixes.

Weak Default Values

If you must provide defaults, ensure they’re only suitable for local development:
# ❌ Bad - weak default that might be used in production
password: ${DB_PASSWORD:password}

# ✅ Good - no default, forces explicit configuration
password: ${PROD_DB_PASSWORD}

Security Checklist

Before committing configuration changes:
  • All sensitive values use ${VAR_NAME} placeholders
  • No hardcoded passwords, tokens, or API keys
  • Environment-specific variables use appropriate prefixes (DEV_, PROD_)
  • Default values (if any) are safe for local development only
  • .env files are in .gitignore
  • Repository has appropriate access controls
  • Secrets are documented in team password manager or secret system

Refreshing Secrets

When secrets change, services need to pick up new values:

Using Docker Compose

# Restart the Config Server to reload secrets
docker compose restart sgivu-config

# Restart affected microservices
docker compose restart sgivu-auth sgivu-gateway

Using Spring Boot Actuator

For services that support dynamic refresh:
curl -X POST http://localhost:9000/actuator/refresh
The /actuator/refresh endpoint must be enabled in the service configuration and typically requires authentication in production.

Best Practices Summary

  1. Never commit secrets - Use environment variables for all sensitive data
  2. Use descriptive names - Include environment and purpose in variable names
  3. Provide safe defaults - Only for local development, never for production
  4. Separate by environment - Use DEV_, PROD_ prefixes to prevent accidents
  5. Use secret managers - Integrate with AWS Secrets Manager, Vault, etc. for production
  6. Document secrets - Keep a secure inventory of what secrets exist and where
  7. Rotate regularly - Establish a process for rotating credentials periodically
  8. Audit access - Monitor who accesses the config repository and secret systems

Build docs developers (and LLMs) love