DEV Community

Vedant Phougat
Vedant Phougat

Posted on

Environment Variables: Naming Conventions and Runtime Access in C# .NET

Table of contents

1. Introduction

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'll cover simple ways to name environment variable keys for easy organization and show you how to load them into your 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 environment 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 configuration builders like .AddEnvironmentVariables("MyApp_") in .NET allows the application to load only variables prefixed with MyApp.

3. Mapping environment 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; }
}
Enter fullscreen mode Exit fullscreen mode

3.2. Naming Convention for Environment Variables

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
Enter fullscreen mode Exit fullscreen mode

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 environment 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>();
    }
}
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)