Where to securely store Google_Application_Credentials in Django project?

Question:

I have a Django project that uses the Google API. I created a docker-compose.yml which has my Django container and Nginx container. It builds successfully but when I run docker-compose up, I get following error:

google.auth.exceptions.DefaultCredentialsError: File /file/path/credentials.json was not found.

I have installed the Google SDK and ran ‘gcloud auth application-default login’ which creates the json file in my root directory. I then created an environment variable for it and configured my Django app.

settings.py:

GOOGLE_APPLICATION_CREDENTIALS = os.environ["GOOGLE_APPLICATION_CREDENTIALS"]

I can open the credentials json file in my finder so I know it’s there.

The Google API is being used for secret manager to retrive secret keys:

from google.cloud import secretmanager
import environ

env = environ.Env()
environ.Env.read_env()


def get_secret(secret_id, version_id="latest"):
    project_id = env("GOOGLE_PROJECT_ID")
    client = secretmanager.SecretManagerServiceClient()
    name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
    response = client.access_secret_version(name=name)
    return response.payload.data.decode("UTF-8")

Without running docker-compose up it works fine and I can retrieve keys but I want to test it out running my docker containers.

My docker-compose.yml:

version: '3'

services:
  backend:
    build:
      context: ./
      dockerfile: ./Dockerfile
    env_file:
      - ./backend/.env
    container_name: backend
    ports:
      - 8000:8000
  nginx:
    build:
      context: ./nginx
      dockerfile: ./Dockerfile
    container_name: nginx
    ports:
      - 80:80
    depends_on:
      - backend

I even tried downloading the service account key which places it in my downloads folder

When I move the file into the django project, it can ready it but from my understanding, you should’t have the credentials file in the source code. So where should I store the credentials for this to work securely?

Asked By: jdez

||

Answers:

There are two steps here you’re missing to use a local service account in the container without actually storing it there or adding it to your git repo:

I’ll speak in generalities and then you can add these to your docker-compose.yml:

Where Should The Google Services Look

The environment variable GOOGLE_APPLICATION_CREDENTIALS tells the Google services where it should look for a service account in the container. So in your service, set an environment variable with an absolute path in the container where these Google services should look:

services:
  backend:
    build:
      context: ./
      dockerfile: ./Dockerfile
    environment:
      GOOGLE_APPLICATION_CREDENTIALS: /tmp/keys/application_default_credentials.json
    env_file:
      - ./backend/.env

Mapping From Your Local Machine

Because you don’t want to store the service account in your repo, you need to set up a volume in your docker-compose.yml that maps the above GOOGLE_APPLICATION_CREDENTIALS to the service account on your local machine. If you have your service account at /jdez/Downloads/service-account.json, you’ll set up your volume like this:

services:
  backend:
    build:
      context: ./
      dockerfile: ./Dockerfile
    environment:
      GOOGLE_APPLICATION_CREDENTIALS: /tmp/keys/application_default_credentials.json
    env_file:
      - ./backend/.env
    volumes:
      - /jdez/Downloads/service-account.json:/tmp/keys/application_default_credentials.json

Now when the Google services look for the file at GOOGLE_APPLICATION_CREDENTIALS, they’ll read the one in your Downloads directory.

Because you’re using a service account, you don’t even need to run gcloud unless you need it for other things.

Answered By: I'm Joe Too