Secure Spring Boot Secrets in OpenShift
Learn how to securely manage Spring Boot secrets in OpenShift using Secrets, Service Accounts, RBAC, External Secret Managers, Secret Rotation, and enterprise security best practices.
Introduction
Every enterprise Spring Boot application requires sensitive information to function.
Examples include:
- Database Passwords
- API Keys
- OAuth Client Secrets
- JWT Signing Keys
- Kafka Credentials
- Redis Passwords
- SSL Certificates
- Cloud Access Keys
One of the biggest mistakes developers make is storing these secrets inside:
application.propertiesapplication.yml- Git repositories
- Docker images
- Source code
This creates significant security risks.
OpenShift provides a secure mechanism using Secrets, enabling applications to consume sensitive data securely at runtime without exposing credentials.
Learning Objectives
By the end of this article, you will understand:
- Why secret management is important
- OpenShift Secrets architecture
- Spring Boot Secret injection
- Environment variables vs mounted files
- Secret rotation
- RBAC protection
- External Secret Managers
- Enterprise security best practices
Why Secure Secrets?
Never hardcode secrets.
❌ Bad Example
spring.datasource.password=Admin@123
jwt.secret=my-secret-key
aws.secretKey=AKIAxxxxxxxx
Problems:
- Visible in Git
- Stored inside Docker images
- Easy to leak
- Difficult to rotate
Enterprise Secret Architecture
flowchart TD
DEV["Developer"]
GIT["Git"]
OCP["OpenShift"]
SECRET["Secret"]
POD["Spring Boot Pod"]
DB["PostgreSQL"]
DEV --> GIT
GIT --> OCP
OCP --> SECRET
SECRET --> POD
POD --> DB
Secrets remain outside the application code.
Secret Management Flow
sequenceDiagram
participant Admin
participant OpenShift
participant Secret
participant SpringBoot
Admin->>OpenShift: Create Secret
OpenShift->>Secret: Store Securely
SpringBoot->>Secret: Read Secret
Secret-->>SpringBoot: Credentials
What Should Be Stored as Secrets?
Examples:
| Store as Secret | Store as ConfigMap |
|---|---|
| Passwords | Database Host |
| Tokens | Logging Level |
| Certificates | Feature Flags |
| API Keys | Kafka Topic |
| JWT Secret | Application Name |
Create Secret
apiVersion: v1
kind: Secret
metadata:
name: payment-secret
type: Opaque
stringData:
DATABASE_USERNAME: paymentuser
DATABASE_PASSWORD: StrongPassword@123
JWT_SECRET: my-super-secret-key
Deploy
oc apply -f payment-secret.yaml
Secret Architecture
flowchart LR
SECRET["Secret"]
ENV["Environment Variables"]
APP["Spring Boot"]
DB["Database"]
SECRET --> ENV
ENV --> APP
APP --> DB
Inject Secret as Environment Variable
Deployment YAML
env:
- name: DATABASE_USERNAME
valueFrom:
secretKeyRef:
name: payment-secret
key: DATABASE_USERNAME
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: payment-secret
key: DATABASE_PASSWORD
Spring Boot Configuration
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}
Spring Boot automatically resolves the environment variables.
Using @Value
@Value("${DATABASE_USERNAME}")
private String username;
@Value("${DATABASE_PASSWORD}")
private String password;
Using ConfigurationProperties
@ConfigurationProperties(prefix="database")
public class DatabaseProperties {
private String username;
private String password;
}
Preferred for enterprise applications.
Mount Secrets as Files
Some applications require certificates or license files.
flowchart LR
SECRET["Secret"]
VOLUME["Mounted Volume"]
APP["Spring Boot"]
SECRET --> VOLUME
VOLUME --> APP
Deployment
volumeMounts:
- name: payment-secret
mountPath: /etc/secrets
volumes:
- name: payment-secret
secret:
secretName: payment-secret
Secret Files
Inside the Pod
/etc/secrets
DATABASE_USERNAME
DATABASE_PASSWORD
JWT_SECRET
Read Secret File
String password =
Files.readString(
Path.of("/etc/secrets/DATABASE_PASSWORD"));
Database Connection
flowchart LR
APP["Spring Boot"]
SECRET["Secret"]
DB["PostgreSQL"]
APP --> SECRET
SECRET --> DB
Credentials never appear in source code.
JWT Secret
jwt.secret=${JWT_SECRET}
The signing key is securely injected.
TLS Certificates
Store certificates as Secrets.
flowchart TD
TLS["TLS Certificate"]
SECRET["Secret"]
ROUTE["OpenShift Route"]
BROWSER["Browser"]
TLS --> SECRET
SECRET --> ROUTE
ROUTE --> BROWSER
Verify Secrets
oc get secrets
Describe
oc describe secret payment-secret
View Secret
oc get secret payment-secret -o yaml
Data is Base64 encoded.
Decode Secret
echo "YWRtaW4=" | base64 --decode
Remember:
Base64 is encoding, not encryption.
RBAC Protection
Only authorized Service Accounts should access Secrets.
flowchart LR
APP["Spring Boot"]
SA["Service Account"]
RBAC["RBAC"]
SECRET["Secret"]
APP --> SA
SA --> RBAC
RBAC --> SECRET
Banking Example
flowchart TD
PAYMENT["Payment Service"]
PAY_SECRET["Payment Secret"]
JWT_SECRET["JWT Secret"]
KAFKA_SECRET["Kafka Secret"]
DB["Oracle Database"]
PAYMENT --> PAY_SECRET
PAY_SECRET --> DB
PAYMENT --> JWT_SECRET
PAYMENT --> KAFKA_SECRET
Each microservice has its own Secrets.
Secret Rotation
Passwords should be rotated regularly.
flowchart LR
OLD["Old Secret"]
NEW["New Secret"]
RESTART["Restart Pods"]
APP["Spring Boot"]
OLD --> NEW
NEW --> RESTART
RESTART --> APP
Benefits
- Better security
- Compliance
- Reduced credential exposure
External Secret Managers
Many enterprises don't store Secrets directly inside OpenShift.
Common solutions:
- HashiCorp Vault
- AWS Secrets Manager
- Azure Key Vault
- Google Secret Manager
- CyberArk
Enterprise Architecture
flowchart TD
APP["Spring Boot"]
SA["Service Account"]
ESO["External Secrets Operator"]
VAULT["HashiCorp Vault"]
DB["Database Password"]
API["API Keys"]
CERT["Certificates"]
APP --> SA
SA --> ESO
ESO --> VAULT
VAULT --> DB
VAULT --> API
VAULT --> CERT
Applications never directly store credentials.
AWS Secrets Manager Example
flowchart LR
APP["Spring Boot"]
ESO["External Secrets"]
ASM["AWS Secrets Manager"]
DB["PostgreSQL"]
APP --> ESO
ESO --> ASM
ASM --> DB
Secret Synchronization
flowchart LR
VAULT["HashiCorp Vault"]
ESO["External Secrets Operator"]
SECRET["OpenShift Secret"]
APP["Spring Boot"]
VAULT --> ESO
ESO --> SECRET
SECRET --> APP
Secrets stay synchronized automatically.
Verify Environment Variables
oc rsh payment-api
env
Verify:
DATABASE_USERNAME
DATABASE_PASSWORD
Common Problems
Secret Not Found
oc get secrets
Wrong Secret Name
Verify
secretKeyRef:
name: payment-secret
Permission Denied
Verify Service Account permissions.
oc auth can-i get secrets
Pod Cannot Start
Possible causes:
- Missing Secret
- Wrong key
- Incorrect mount path
Useful Commands
Create Secret
oc apply -f secret.yaml
List Secrets
oc get secrets
Describe Secret
oc describe secret payment-secret
Delete Secret
oc delete secret payment-secret
Production Best Practices
- Never hardcode secrets.
- Use one Secret per application.
- Protect Secrets with RBAC.
- Rotate passwords regularly.
- Use Service Accounts.
- Use TLS everywhere.
- Store certificates as Secrets.
- Audit Secret access.
- Integrate with enterprise secret managers.
- Never expose secrets in application logs.
Common Mistakes
❌ Storing passwords in Git.
❌ Hardcoding JWT keys.
❌ Sharing one Secret across multiple applications.
❌ Logging passwords.
❌ Giving all Pods permission to read Secrets.
❌ Assuming Base64 provides encryption.
Advantages
- Secure credential management
- Centralized secret storage
- Easy rotation
- Better compliance
- Cloud-native security
- Enterprise ready
- Spring Boot integration
- Zero hardcoded credentials
Summary
Secure secret management is a critical part of deploying Spring Boot applications on OpenShift.
Key takeaways:
- Store all sensitive information in OpenShift Secrets.
- Inject secrets using environment variables or mounted volumes.
- Protect access with Service Accounts and RBAC.
- Rotate credentials regularly.
- Integrate with external secret management solutions such as Vault for enterprise environments.
- Never hardcode credentials in source code, configuration files, or container images.
Interview Questions
- What is an OpenShift Secret?
- Why shouldn't passwords be stored in
application.properties? - What is the difference between ConfigMaps and Secrets?
- How do Spring Boot applications consume Secrets?
- How can Secrets be mounted as files?
- Why is Base64 encoding not considered encryption?
- What is Secret rotation?
- How do Service Accounts and RBAC secure Secret access?
- What are the benefits of using HashiCorp Vault or AWS Secrets Manager?
- What are the best practices for managing secrets in OpenShift?