DevOps

How to Manage Secrets in Web Applications?

March 14, 2023

If you build web applications, you will undoubtedly have passwords or secrets that need to be protected. In this article, we’ll break down the 5 levels of secret management, from terrible to industry best practices. By the end of this guide, you’ll be ready to properly manage the credentials for your next project.

Level 0: Hardcoding Secrets

Hardcoding secrets into your code is the worst option available. Although there are more extreme possibilities, such as turning off authentication completely, it’s still considered the worst practice for secret management. At this level, you place your password directly in the code where it’s needed.

For example, if you were building a Node.js app with a MongoDB database, you could put your password in the following line:

const dbClient = new MongoClient(process.env.MONGODB_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  auth: {
    user: 'admin',
    password: 'mypassword',
  },
});

However, this is a really bad idea. Some of the biggest drawbacks include:

  • Private information is scattered throughout the codebase, making it difficult to return to it later and modify.
  • Even if the Git repository is private, all of the developers working on the project will have to clone the repository and store a copy of their secret on their system.
  • It’s difficult to support multiple environments, such as having a separate development, staging or production environment.

Level 1: Extract Secrets into Separate Configuration Files

At this level, we create a config.env file containing the database password. We then use something like the dotenv package to load the secret as an environment variable. This is the preferred way to store secrets for development credentials. But, for production credentials, it’s not quite as secure.

// config.env
DATABASE_PASSWORD = mypassword
DATABASE_USER = admin

// app.js
const dbClient = new MongoClient(process.env.MONGODB_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  auth: { 
    user: process.env.DATABASE_USER, 
    password: process.env.DATABASE_PASSWORD 
  },
});

The benefits of extracting the secrets into a separate configuration file include:

  • Clearer code without secret strings floating around throughout the project.
  • Having separate configuration files for different environments is possible.
  • You’ll know where all the secrets are, and we can adjust our behavior accordingly.

Level 2: Encrypt before Checking them into the Repository

If it’s required to store secrets in the repository, then you can at least encrypt the secret files. For example, use OpenSSL to convert plain-text configuration files into encrypted files.

openssl aes-256-cbc -in mypassword.txt -out mypassword.txt.enc

Although this method is better than hardcoding secrets, the encryption key then becomes a sensitive secret itself. You’ll need to keep the encryption key secure.

Level 3: Use a Dedicated Secret Manager

The advantage of utilizing a dedicated secret manager, like the one provided by your cloud provider, is the ability to manage secrets in a single location. Secrets can be audited so you can track who has accessed each secret, and they can also have multiple versions.

Many cloud providers offer a key management system that managers encryption keys securely. For example, Google Cloud secret manager or AWS Secrets Manager.

The secrets are retrieved as follows:

gcloud secrets versions access latest --secret=my-secret

Level 4: Use Ephemeral Credentials with HashiCorp Vault

The best option for secure secret management is to use HashiCorp Vault with ephemeral credentials. This level ensures the secrets are only valid for a limited amount of time.

Vault generates new usernames and passwords for each requested resource. When the resource is no longer needed, then the username and password will be revoked automatically.

The process is automated with an API request, so the entire task is seamlessly managed by your applications automatically. To make this system work, you can use one of the HashiCorp Vault clients, such as the Node.js library.

Conclusion

Securing secrets is an essential task for web applications, and there are many different ways to do it. Different systems have various degrees of security and protection, so the level you choose depends on your specific needs.

We’ve covered the five levels of secret management, starting with the worst option to the best. Although, it’s not necessary or practical to use level 4 for all projects. Hopefully, you can find an appropriate level of security for your credentials that strikes the right balance between safety and convenience.

© All rights reserved — cs.fyi