Table of contents
- 1. Introduction
- 2. Why use prefixes for variables?
- 3. Mapping variables to configuration classes
- 4. Accessing the variables
- 5. Conclusion
- 6. See also
- 7. Feedback
1. Introduction
In modern application development, managing configurations—especially sensitive data—is crucial. Hardcoding secrets in your codebase can lead to accidental exposures, so what's the alternative? Environment variables help keep secret configurations out of your code, reducing the risk of accidental exposure. This way you can also change the value of your secrets, without the need to redeploy the application. But for them to be effective, you need a clear approach to naming and accessing these variables.
In this post we will dive into
- naming of environment variable keys for:
- Simple properties,
- Complex properties,
- Collection properties, and
- Dictionary properties
- adding prefix to environment variables for easy organization
- loading them into the application at runtime.
⚠️ Caution
While environment variables help prevent accidental exposure of sensitive data, by separating the secrets from you codebase, they do not provide any additional "security" as explained in this Stackoverflow question.
Storing secrets as plain text has risks like CWE-256. To improve security, consider using services similar to Azure Key-Vault and AWS Secrets Manager to securely retrieve sensitive information at runtime. Read this MSDN post for more details.
2. Why use prefixes for variables?
-
To avoid naming conflicts: Two applications might use a variable name
ConnectionString
. By prefixing it with application name/key, ensures that a specific application's variables are unique. - For ease of readability and maintenance: By grouping all the configuration keys related to a specific application together.
-
Avoid accidentally picking up of variables intended for other applications: By using
.AddEnvironmentVariables("MyApp_")
in .NET allows the application to load only variables prefixed withMyApp
.
3. Mapping variables to configuration classes
3.1. Define configuration classes
Here is a class which will be used to hold the configurations read from the environment variables:
public class AwsConfiguration
{
private const String SectionKey = "AwsConfiguration";
public String AccessKey { get; set; }
public String SecretKey { get; set; }
public EndpointConfiguration Endpoint { get; set; }
public List<String> Regions { get; set; }
public Dictionary<String, String> DetailTypes { get; set; }
}
public class EndpointConfiguration
{
public String Url { get; set; }
public Int32 Port { get; set; }
}
3.2. Naming convention
The naming convention for naming the keys in environment variables:
## Simple Properties
MyAwsApp_AwsConfiguration__AccessKey
MyAwsApp_AwsConfiguration__SecretKey
## Nested Properties
MyAwsApp_AwsConfiguration__Enpoint__Url
MyAwsApp_AwsConfiguration__Enpoint__Port
## Collection/Array Properties
MyAwsApp_AwsConfiguration__Region__0
MyAwsApp_AwsConfiguration__Region__1
MyAwsApp_AwsConfiguration__Region__2
## Dictionary Properties
# DetailTypes dictionary will have 2 keys - InProgress & Completed
# after successful binding of these key-value pairs
# to the object of class - AwsConfiguration
MyAwsApp_AwsConfiguration__DetailTypes__InProgress
MyAwsApp_AwsConfiguration__DetailTypes__Completed
## These properties will not be picked by the `.AddEnvironmentVariables("MyAwsApp_")
NOTMyAwsApp_AwsConfiguration__AccessKey
NOTMyAwsApp_AwsConfiguration__SecretKey
3.3. Understanding the Use of Delimiters
The single-underscore (_
) is used with the main prefix only, while double-underscore(__
) is used for complex properties of the configuration class (described in section 3.1.).
Why not use :
as the separator? Because as per MSDN:
The
:
separator doesn't work with environment variable hierarchical keys on all platforms. For example, the:
separator is not supported by Bash. The double-underscore,__
, is:
- Supported by all platforms.
- Automatically replaced by a colon,
:
.
4. Accessing the variables
One can access the environment variables in Main
method of Program
class as follows:
public class Program
{
public static void Main(String[] args)
{
var builder = new ConfigurationBuilder()
//the prefix - "MyAwsApp_" will be removed from the environment variable names
.AddEnvironmentVariables("MyAwsApp_");
var configuration = builder.Build();
var awsConfiguration = configuration
.GetSection(AwsConfiguration.SectionKey)
.Get<AwsConfiguration>();
}
}
The code AddEnvironmentVariables("MyAwsApp_");
will fetch all the variables that are marked with prefix MyAwsApp_
, strip this prefix from the variables name and then load them in the application. Consider the following variable MyAwsApp_ConnectionString
, it will be loaded into application as ConnectionString
.
5. Conclusion
Using clear naming, organized prefixes, and structured mapping for environment variables simplifies application setup. Here are a few advantages:
- Better organization: Prefixes group related settings, making them easier to locate.
- Avoid naming conflicts: Unique key names created by combining application and configuration name.
- Avoid accidental exposure of secret configurations: By keeping the sensitive data separate from the codebase.
6. See also
7. Feedback
Thank you for reading this post! Please leave any feedback in the comments about what could make this post better or topics you’d like to see next. Your suggestions help improve future posts and bring more helpful content.
Top comments (0)