4
votes

I'm trying to create a Azure DevOps pipeline for one of Java application using maven and in the unit test I have 2 secrets which needs to access the value from environment variables.

String key = System.getenv().get("MY_KEY");
String secret = System.getenv().get("MY_SECRET");

I have added 2 values under pipeline variables from the browser and mark them as "Keep this value secret" so that values will be kept as secret.

enter image description here

In the pipeline I have added required variables and substitute the value with configured variables.

variables:
  MY_KEY: $(MY_KEY_VAL)
  MY_SECRET: $(MY_SECRET_VAL)

However, when I run the build pipeline, it fails with unit test due to null values on both 'key' and 'secret' values.

How can I fix this? Am I doing anything wrong on the configurations?

UPDATE

As Ben mentioned below, it is not possible to set environment variable on hosted agents. In order to run all unit tests during the build pipeline and still keep the key & secret secure, I have modified the unit tests to read the key and secret from a file on the project root. Instead adding the file containing key & secret to git repo, it was added as a Secure File on the pipeline library and was given permission to access by pipeline.

On the Pipeline I was able to download the secure file using 'DownloadSecureFile' task.

- task: DownloadSecureFile@1
  displayName: Download API secrets
  name: configfile
  inputs:
    secureFile: 'service_api_keys'

Moved the file to project root using bash.

- bash: mv $(configfile.secureFilePath) ./

Run the build the process which will read the secrets on unit test execution.

2
Is your pipeline running on self-hosted agent? Windows or linux?Levi Lu-MSFT
@LeviLu-MSFT, I'm using shared Linux agentMelanga

2 Answers

2
votes

System.getenv() reads the system environment variables of the machine which runs the java code. And the variables defined in pipeline is in agent scope not machine scope.Maybe that is why the unit test cannot get the variables.

There is probably no direct way to achieve this. As Ben Smith mentioned, you can refactor your code to get the key/secret from a json files and add a Set Json Property task to update the json files with the variables you defined in the pipeline before maven task run the unit test. Check here for detailed usage of this task.

As another workaround,You can run your pipeline on a self-hosted linux agent, and try to add a bash script task to set the environment variables for the your linux agent(I tested and found set environment variables is not workable for shared-hosted agent). Check here for how to set environment variable for linux.

Check here to instructions to create a self-hosted linux agent.

Hope you will find above helpful!

1
votes

You need to substitute the values within your Java files. The variable substitution you have detailed above i.e.

variables:
  MY_KEY: $(MY_KEY_VAL)
  MY_SECRET: $(MY_SECRET_VAL)

will only replace the values in your pipeline YAML file.

You can substitute your variables in your Java files using the "Replace Tokens" task e.g.

- task: replacetokens@3
    inputs:
      targetFiles: "yourJavaFile.java"
      encoding: "auto"
      writeBOM: true
      verbosity: "detailed"
      actionOnMissing: "warn"
      keepToken: false
      tokenPrefix: "#{"
      tokenSuffix: "}#"
    displayName: Perform variable substitution in java file

And in your java file you would write the variables to be replaced as e.g.

String key = System.getenv().get("#{MY_KEY}#");
String secret = System.getenv().get("#{MY_SECRET}#");