Skip to main content

Configuration

Overview

Purpose of this component is to build a configuration object based on current environment using the baseline config found in the configuration.ts file in the root of this component

The configuration system requires two environment variables in order to materialise the configuration with settings for the appropriate environment.

Please add this environment variable for development environments, you can get teh correct value from the Hectare Encryption secure note in LastPass in the Shared-Hectare Backend folder, please take the LOCAL environment variable from the secure note.

export HECTARE=""

For your local overides file you need to add this environment variable and ensure it points to the root of the repository to a file called overrides.json. This file will be ignored by Git

export HECTARE_OVERRIDES="/Users/nchampion/Dev/Repositories/Hectare/platform/overrides.json"

Create the overrides.json file in the root of the platform repo and add the following JSON to the file, this ensures your integration tests run against your personal test database

{
"developer": "[YOUR_NAME]",
"insights.enabled": false,
"insights.connection.database": "insights",
"whitelist.phones": "[YOUR_PHONE_NUMBER]",
"tests.aws.cognito.clientId": "5civehrtqe1shdtqurfei6dtm",
"tests.aws.cognito.userPoolId": "eu-west-2_iF043jIyZ"
}

Configuration is JSON, example as follows

export const configuration = {
production: {
default: false,
prod: true
},
dev: {
default: false,
dev: true
},
defaults: {
page_size: 25
},
node_path: '.:/opt/node_modules',
courier: {
api_key: {
encrypted: true,
default: 'CymtbB6Al/lD5z01Nfzp1SKzTj2F0A==',
uat: '0m1pNGQiDYn5YmrY1NHMZ/xPeIubJXF2J/sV+0irIw==',
sandbox: 'CymtbBAl/lD5z01NfzSKzTj2F0A==',
prod: '0m1pNGQiDY8Sn5YmrY1NHMZ/xPeIuiwbJXF2J/sV+0irIw=='
}
}
}

In the above example each configuration property can have a different value for each environment or can always have the same value (node_path in the above will be the same value for all environments).

You can have default values, so if all environments except prod for example have the same value, you can set the default key to this value and just add a prod key for the prod setting (see the dev key for an example of this approach above) which helps to minimise configuration.

All properties that need to specify different values for each environment must include the "default" key, this is used to indicate the property is a config property not a parent object such as the courier property in the above example.

Encryption

The configuration system supports encryption of properties if needed, to enable encryption you need to add the "encrypted" key as in the courier.api_key field above. The configuration is initialised once when the process starts and uses environment variables to determine which environment we're in and which encryption key and salt to use for decryption.

There is a unit test to encrypt values here components/configuration/builder.spec.ts you need to get the key and salt from the Hectare Backend shared folder in LastPass, there is a key and salt for dev / uat and one for sandbox / prod, use the dev key and salt for all environments except prod & sandbox and use the prod key and salt to encrypt production / sandbox values. Please ensure you revert the unit test before commiting so we dont commit secrets to git.

Configuration values from process.env

The configuration system supports reading configuration properties from process.env. In order to set the value of a configuration property to an environment variable use the following syntax in the configuration.ts file

{
"lambdaName": "env$AWS_LAMBDA_FUNCTION_NAME"
}

This will cause the configuration system to read the value from process.env['AWS_LAMBDA_FUNCTION_NAME']

AWS Secure Secrets Manager

The configuration system also supports storing secrets in AWS SSM. To leverage SSM, you need to create the secret in the correct account and include the arn to the secret in the configuration file.

Couple of points to note.

The ARN should be specified in config as such

{
"google": {
"mapsApiKey": {
"default": "arn:aws:secretsmanager:eu-west-2:527132486578:secret:hctr/google/maps-api-key-05BywU",
"prod": ""
}
}
}

This assumes we are using the "Other type of secret" key / value pairs secret type in AWS, if we need to support other secret types we will need to handle this in the SecretsManager class in configuration component.

It also assumes the key of the secret in AWS matches the name of the property type, mapsApiKey in this example. This allows us to support multiple secret values in the same secret and allows us to bind the correct value to the correct configuration property.

For this example the secret value in AWS is set up as follows

Secret key  Secret value
mapsApiKey google api key

When we compile the configuiration system we replace the google.mapsApiKey field with a function which will call the get method in SecretsManager class to retrieve the secret from AWS.

We have a local in-memory cache of the secrets

Key Prefixes

The configuration system also supports the ability to override settings only during test runs.

To do this prefix the key in overrides.json with tests. and this setting only will be applied during tests, for example

"tests.aws.cognito.clientId": "4v64tfg6935uvc4pf5c8vtrqf4",

Will set the aws.cognito.clientId field to the specified value only during test runs.

If you need to encrypt a local override, you can prefix the key with encrypted. for example

"encrypted.ravendb.backupCredentials": "e15CFEeh/FeSwVUVb"

will decrypt the value and set it to the ravendb.backupCredentials configuration setting