How To Provide Secrets To A Java Or Node Application

Harith Sankalpa
5 min readOct 3, 2019

--

Have you ever made the mistake of committing your password or an api key to a public repository such as Github or Bitbucket? I am sure most of the developers have made this mistake in their early stages of their carrier once or twice before learning the lesson.

In this article, I explain how you can prevent accidentally making the above mistake by separating your sensitive information from your code which will prevent accidentally committing them to a version controlling system such as git and ending up in a public repository.

How can you separate code from data?

There are several ways you can exclude your sensitive information such as login details, application or api secrets from your code.

  1. Setting secrets as environment variables
  2. Setting secrets as command line arguments
  3. Including secrets in a separate configuration file

Now let’s see how each of these methods achieve our goal and how to do them in a Java or a Node application as examples.

1. Set secrets as environment variables

One of the best approaches to prevent accidentally publishing your application secrets to public repositories is to set them as environment variable in operating system instead of including them in your code. You can import these environment variables in runtime and use them as needed.

Environment variables are not specific to applications but to the operating system you are running your application on. Method of setting environment variable differs from operating system to operating system.

In Windows 10, you can find the option to set environment variables in Advanced System Settings in System Properties (Right click My Computer > Properties > Advanced System Settings > Select Advanced tab > Environment Variables) or in Control Panel.

In Linux based operating systems, to set an environment variable for all the processes globally, you can include your secrets as a key value pair in a file in the /etc/profile.d directory. You can name the file with a descriptive name with .sh extension at the end.

sudo cd /etc/profile.d
sudo touch <file_name>.sh
sudo gedit <file_name>.sh #You can use vim or any other text editor

Add the desired environment variable to the newly created file as follows. Make sure there are no unnecessary space between words and equal sign.

export <VARIABLE_KEY>=<VARIABLE_VALUE>#For exampleexport MY_SECRET=this_is_my_secret

You may have to restart your operating system for these global variables to be available in your development environment.

Now you can import these variables into your code at runtime. For example you can get the values of environment variables in Java with getenv() method.

String variable = System.getenv("VARIABLE_KEY")//To get the value of the above exampleString mySecret = System.getenv("MY_SECRET")

In Node.js you can use environment variables in your code as follows.

VARIABLE = process.env.VARIABLE_KEY//To get the value of the above examplemySecret = process.env.MY_SECRET

But you must keep in mind to implement methods such as try-catch blocks to handle errors which may occur in case of absence of those environment variables.

2. Set secrets as command line arguments

Command line arguments is another way to set variables that can be imported at runtime. In contrast to environment variables these arguments are set when application is launched as command line properties. Therefore, they must be specified each time you restart the program and they are specific to the process where as environment variables are available to all the processes running on the operating system. Method of setting and using these arguments differs from programming language to programming language.

In Java, these command line arguments are called as System Properties. These properties can be set using command line with -D option when application is launched as follows. You can specify multiple key value pairs separated by

java -DpropertyName=propertyValue MyAppLauncherClass#For examplejava -DmySecret=this_is_my_secret MySecretAppLauncherClass

Or you can set them dynamically in your code as follows. (Do not forget the quotation marks.)

System.setProperty("propertyName","propertyValue");

You can use the value of a system property set either way using getProperty() method.

String propertyValue = System.getProperty("propertyName");//For ExampleString mySecret = System.getProperty("mySecret");

Most modern Java IDEs provide a graphical interface to set these command line arguments/system properties so you do not have to specify them each time you run the code in development environment.

In node these command line arguments are treated as same as environment variables and they will override any environment variable with the same name.

$ propertyName=propertyValue node index.js

As treated as same as the environment variables they can read be accessed the same way we accessed environment variables in Node.js.

3. Set secrets in a configuration file

Instead of being hard coded inside your code, API keys and username/passwords can be included in a separate configuration file. They can be imported and used once needed. For example, when you are working on a Java project you can store your sensitive information in a “config.properties” and write a property file reader class to import and use data in that file.

Only including your secrets in a separate file will not solve the problem as if this configuration file gets uploaded to a public repository your sensitive information will be exposed once again. To prevent that, you can include this configuration file in the “.gitignore” which will prevent this file from being committed unless it’s added forcefully.

If another programmer wishes to work on your project he will have to either create a configuration file himself with necessary data or get a copy of the original configuration file. If you do not wish to provide the original configuration file, you should provide guidelines on how configuration data should be included in the configuration file by including either a template file such as “config_template.properties” with dummy data or a “readme” file with necessary information to re create the configuration file.

Conclusion

When you make your code public you must be cautious not to expose your sensitive information to others. There are three simple ways that can be followed to separate your secrets from code. They are setting your secrets as system wide environment variables, setting them as command line arguments or including all of them in a separate config file and setting it to be ignored by version controlling system.

When you follow any of the above method you must provide clear information on how to set required information in a “readme” file or within the code for the reference of other or future developers.

In a future article I will explain how you can use git hooks to prevent accidentally committing secrets to git.

--

--

Harith Sankalpa
Harith Sankalpa

Written by Harith Sankalpa

Software Engineer | Tech Enthusiast | Gamer | Photographer

Responses (1)