Managing Secrets and Configuration in DevOps


In the world of DevOps, maintaining a secure and efficient workflow is crucial. One of the most important aspects of a DevOps pipeline is managing secrets and configurations. Whether it’s API keys, passwords, or database credentials, keeping sensitive data secure while ensuring it’s accessible to the appropriate systems is a challenge that every DevOps engineer faces.


What are Secrets and Configuration in DevOps?

Secrets in DevOps

In the context of DevOps, secrets refer to sensitive information such as:

  • API keys
  • Database credentials
  • SSH keys
  • Encryption keys
  • Access tokens

These secrets are required for accessing various services, systems, or APIs during deployment and runtime. Without secure management, secrets can become a major vulnerability in your infrastructure.

Configuration in DevOps

Configuration refers to the non-sensitive settings that control how an application or system behaves. These include:

  • Database connection strings (non-sensitive)
  • Environment variables (e.g., app settings)
  • Service URLs
  • Log levels

Configuration data is often environment-specific (development, staging, production) and needs to be stored in a way that is easily accessible and maintainable.


Why is Managing Secrets and Configuration Important?

Effective management of secrets and configuration is essential for the following reasons:

  • Security: Exposing secrets, such as database passwords or API keys, can lead to unauthorized access to critical services.
  • Compliance: Regulatory frameworks such as GDPR, HIPAA, and PCI-DSS mandate strict control over sensitive data.
  • Efficiency: Centralized management of configuration allows teams to quickly update and deploy new settings without requiring code changes.
  • Automation: In a CI/CD pipeline, secrets and configuration must be available to the right environments without manual intervention, ensuring automated workflows run smoothly.

Best Practices for Managing Secrets and Configuration

1. Use Secrets Management Tools

Instead of hardcoding secrets in your application or storing them in environment files, it’s best to use specialized tools designed to store and manage secrets securely. Some popular tools include:

  • HashiCorp Vault: A powerful and flexible secret management tool that can manage sensitive data and encrypt secrets at rest.
  • AWS Secrets Manager: A fully managed service from AWS that enables you to store, retrieve, and rotate secrets for your applications.
  • Azure Key Vault: A cloud-native service for managing and securing application secrets in Microsoft Azure.
  • Kubernetes Secrets: Kubernetes provides a native mechanism for storing and accessing sensitive information within a Kubernetes cluster.

Sample Code: Storing Secrets in HashiCorp Vault

Here’s a basic example of how to store and retrieve a secret in HashiCorp Vault:

# Authenticate with Vault
vault login <your-token>

# Store a secret
vault kv put secret/myapp/db-password value="mySuperSecretPassword"

# Retrieve the secret
vault kv get secret/myapp/db-password

In this example, a secret (the database password) is stored under the path secret/myapp/db-password, and Vault can securely retrieve it when needed.

2. Environment Variables for Configuration

For non-sensitive configurations (such as application settings), environment variables are a common approach. They allow you to inject configuration values directly into the application environment at runtime without having to hardcode them into the application code.

Sample Code: Using Environment Variables

Here’s how to use environment variables to manage configurations for a Node.js application:

// Load environment variables
require('dotenv').config();

// Access environment variables
const dbHost = process.env.DB_HOST;
const dbUser = process.env.DB_USER;
const dbPassword = process.env.DB_PASSWORD;

console.log(`Connecting to database ${dbHost} with user ${dbUser}`);

To load the environment variables, you could store them in a .env file (for development) or set them in the CI/CD pipeline during deployment.

Example .env file:

DB_HOST=localhost
DB_USER=myuser
DB_PASSWORD=mypassword

3. Encryption at Rest and in Transit

Secrets should be encrypted both at rest (when stored) and in transit (when transmitted across networks). This ensures that even if someone gains unauthorized access to your storage or network, the secrets are protected.

  • Use TLS/SSL to encrypt data in transit.
  • Use encryption algorithms (e.g., AES-256) to encrypt sensitive data stored in databases or files.

Many secrets management tools, such as HashiCorp Vault and AWS Secrets Manager, automatically handle encryption at rest.

4. Use Role-Based Access Control (RBAC)

Access to secrets and configuration data should be restricted based on roles and responsibilities. By implementing Role-Based Access Control (RBAC), you can ensure that only the appropriate services or team members have access to specific secrets or configurations.

For instance, you may want your database password to be accessible only by the database service, but not by other microservices. Similarly, sensitive configurations for production environments should only be accessible to deployment pipelines.

Sample Code: Using RBAC in Kubernetes

Here’s an example of a Kubernetes Role and RoleBinding to restrict access to a secret:

# Define a Role with access to the secret
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: secret-reader
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]

---
# Bind the Role to a specific service account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: secret-reader-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: my-app-service-account
    namespace: default
roleRef:
  kind: Role
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

This configuration ensures that only the service account my-app-service-account can access the secrets in the default namespace.

5. Automate Secret Rotation

Secrets should be rotated periodically to minimize the risk of leaks. Automation tools like HashiCorp Vault and AWS Secrets Manager allow you to configure automatic secret rotation to avoid manual intervention.

Sample Code: Automatic Secret Rotation in HashiCorp Vault

To configure automatic secret rotation, Vault can be set up to periodically update credentials for services such as databases. Here’s an example of setting up a dynamic secret engine for database credentials:

# Enable the database secret engine
vault secrets enable database

# Configure a MySQL connection (example)
vault write database/config/mysql connection_url="mysql://root:@localhost:3306/mydb"

# Create a role to generate dynamic database credentials
vault write database/roles/my-role \
    db_name=mysql \
    creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT ALL PRIVILEGES ON mydb.* TO '{{name}}'@'%';" \
    default_ttl="1h" \
    max_ttl="24h"

# Generate a new set of credentials
vault read database/creds/my-role

This setup ensures that Vault generates new database credentials dynamically, and the old ones are automatically rotated according to the TTL (Time-to-Live) setting.


Tools for Managing Secrets and Configuration

1. HashiCorp Vault

A powerful tool for managing secrets that supports multiple backends and integrates well with other infrastructure components.

2. AWS Secrets Manager

A fully managed service that provides secret storage, retrieval, and automatic rotation within the AWS ecosystem.

3. Azure Key Vault

Microsoft’s native secret management service, offering secure storage and access control in Azure.

4. Kubernetes Secrets

Native secret management in Kubernetes clusters, ideal for containerized applications.