Contact Us
24/7
Python BlogDjango BlogSearch for Kubernetes Big DataSearch for Kubernetes AWS BlogCloud Services
<< ALL BLOG POSTS

Manage Your Secrets to Keep Your Code Secure

|
June 15, 2022

Cybersecurity is a growing concern across the globe, and with good reason. Securing the credentials, or secrets, used in your code is one of the most important things you can do to protect yourself.

Most applications need to access external resources such as databases, storage systems, or third-party web services to perform essential functions. In order to do that, the application needs to authenticate itself to the external resource using credentials, which could be in the form of secret keys or passwords.

Credentials are valuable targets for malicious hackers as they can then impersonate your company or your application to access your critical data. Therefore, it is crucial to protect these credentials and keep them secret as much as possible.

By removing the secrets from your source code and using a secrets manager, you can boost the security of your code secrets and protect your data from bad actors.

Remove secrets from source code

Consider this sample snippet for Django’s DATABASES setting.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

This can help programmers of all experience levels easily get started in running Django locally because it clearly illustrates what key/value pairs to use and what they are meant to contain. Hardcoding the values, however, only makes it easy to leak your database credentials to others. If your source code leaks, the credentials will leak as well.

Storing the credentials as environment variables is a common pattern to remove credentials from the source code. Instead of defining the credentials in the source code, they are instead defined in the environment the application is running in. The application then retrieves those values at runtime. This is a pattern recommended by the widely-known set of best practices called The Twelve-Factor App.

To set the environment variables on Linux/OS X, the following lines can be defined in .bashrc or .bash_profile (outside of the application source code):

export DB_NAME='mydatabase'
export DB_USER='mydatabaseuser'
export DB_PASSWORD='mypassword'
export DB_HOST='127.0.0.1'
export DB_PORT='5432'

In our example Django application, those credentials are retrieved from the environment at runtime.

import os

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.getenv('DB_NAME'),
        'USER': os.getenv('DB_USER'),
        'PASSWORD': os.getenv('DB_PASSWORD'),
        'HOST': os.getenv('DB_HOST'),
        'PORT': os.getenv('DB_PORT'),
    }
}

There you go. No more credentials in the source code. No more chance of your credentials leaking out together with your source code.

While this is a good first step, it can still be improved further. The credentials may not be in the source code but it is available in the runtime environment itself. Any process running in the same environment as your application can also easily access those credentials. To mitigate this, we can then use secret managers.

Use a secret manager

A secret manager is an application that serves as a secure storage system for credentials and other sensitive data. There are many options for secrets managers:

For our sample code, we will use AWS’ offering. We store our example credentials in a secret called DB_CREDENTIALS in AWS Secrets Manager.

Assuming boto3 has been installed as a dependency and configured correctly, our Django settings snippet can now be changed to this:

import boto3
import json

# Create a Secrets Manager client
client = boto3.client(
    service_name='secretsmanager',
    region_name='us-east-1'
)

db_credentials = json.loads(client.get_secret_value(SecretId='DB_CREDENTIALS')['SecretString'])

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': db_credentials['DB_NAME'],
        'USER': db_credentials['DB_USER'],
        'PASSWORD': db_credentials['DB_PASSWORD'],
        'HOST': db_credentials['DB_HOST'],
        'PORT': db_credentials['DB_PORT'],
    }
}

By doing it this way, the credentials are neither present in the source code nor in the environment. A malicious process in the same environment as the application would not be able to retrieve them from the environment variables.

Using secret managers to store credentials requires very minimal additional effort and cost but it greatly helps in improving the security of your application.

How can we assist you in reaching your objectives?
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.