Zwing Docs

Managing Environment Variables

How do we manage environment variables inside G1 CRM service.

Introduction

We use environment variables to make sure that none of the secret variables are not exposed to unauthorized party through codebase. We primarily follow two practices to manage environment variables, depending on the environment.

DisciplineEnvironmentApproach
Backendlocal.env file
Backendstaging,uat, prodAzure Key Vault (How to?)
Frontendlocal.env file
Frontendstaging, uat, or prod

Backend

Local Env

For local environment, you only need to set the variables inside the .env file.

After adding in .env, you can read the env variable by using the following approach.

Staging, UAT, or Production

On staging, uat or production environment, we follow the same approach of creating or updating the environment variable.

  1. If the env variable you are adding is sensitive, you will need to add a new secret in the Azure KeyVault service, through the infrastructure repository. You can read more about it here. Otherwise, you can simply define the variable in the .devops/helm/${env}.values.yaml
  2. Once the above step is done, update the helm charts to creating mapping of the newly created secret.

Now, to update the helm chart, you can make changes in the .devops/helm directory. It has the Deployment files for all of the services that we have in CRM.

First, update the .devops/helm/templates/secret-provider.yaml file. Below is a sample of the secret-provider.yaml file, only copy the relevant changes.

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: { { .Values.secretStore.name } }
  namespace: { { .Release.Namespace } }
spec:
  provider: azure
  secretObjects:
    - secretName: crm-app-secrets
      type: Opaque
      data:
        - objectName: key_vault_new_secret_name
          key: key_vault_new_secret_name
  parameters:
    usePodIdentity: "false"
    useVMManagedIdentity: "true" # Set to true for using managed identity
    userAssignedIdentityID: { { .Values.secretStore.userAssignedIdentityID } }
    keyvaultName: { { .Values.secretStore.keyvaultName } } # Set to the name of your key vault
    tenantId: { { .Values.secretStore.tenantId } } # The tenant ID of the key vault
    objects: |
      array:
        - | # add these lines to the bottom of your `secret-provider.yaml` file.
          objectName: key_vault_new_secret_name 
          objectType: secret

Once we have mapped the KeyVault secret to our local secret, we can now pass this secret to our Deployment definitions. Below is a sample file for Deployment file of cdp-service, .devops/helm/templates/cdp-service/deployment-api-service.yaml. Take a look at the highlighted section.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: crm-cdp-apis
  namespace: { { .Release.Namespace } }
  labels:
    app: crm-cdp-apis
spec:
  replicas: 2
  selector:
    matchLabels:
      app: crm-cdp-apis
  template:
    metadata:
      labels:
        app: crm-cdp-apis
    spec:
      containers:
        - name: crm-cdp-apis
          image: "{{ .Values.image.repository }}:{{ .Values.image.version }}"
          env:
            - name: NODE_ENV
              value: { { .Values.env } }
            - name: NEW_SECRET
              valueFrom: 
                secretKeyRef: 
                  name: crm-app-secrets
                  key: key_vault_new_secret_name
          volumeMounts:
            - name: secrets-store01-inline
              mountPath: "/mnt/secrets-store"
              readOnly: true
      volumes:
        - name: secrets-store01-inline
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: { { .Values.secretStore.name } }

Noice 🔥 Once done, you are good to raise a PR, and get a quick review.

Edit on GitHub