0
votes

Due to some new security requirments the api I'm developing now is required to store several urls, azure account names etc. in the azure key vault, rather than in the application.yml config file.

The issue is that I'm having trouble authenticating / accessing the key vault client in a Local environment. I have very limited access to the azure functions / key vault itself so testing the new code I'm writing is near impossible at current:

 public String getSecretFromKeyVault(String key) {

        /**
        * Breaks in the constructor call, as the system.env variables for MSI_ENDPOINT and MSI_SECRET are null.
        **/

        AppServiceMSICredentials credentials = new AppServiceMSICredentials(AzureEnvironment.AZURE);
        KeyVaultClient client = new KeyVaultClient(credentials);

        SecretBundle secret = client.getSecret("url-for-key-vault", key);
       return secret.value();

    }

I'm aware that the variables will be set in the cloud server, but my question is how can I best verify that the vault calls have been implemented properly(unit, integration, e2e local tests), and how would I manage to use key vault calls during local development / runtime?

The alternative to MSI would be to enter the client id and key manually, following authentication against the active directory. This could be a solution for local development, but Would still require the declaration of confidential information in the source code.

Ive also tried logging in to azure using az login before running the server but that didn't work either.

Does anyone have any suggestions on how I might resolve this issue, or what my best options are going forward?

Notes on application:

  • Java version: 8
  • Spring boot
  • Azure / vsts development and deployment environment
1
Unfortunately, this very limitation (also discussed here github.com/Azure/Azure-Functions/issues/638) forced us to move to a more portable solution (Hashicorp's Vault product).Not a JD
Ah thats what i thought, our hands are tied with azure annoyingly, most likely will have to use a separate function for local devJack Branch

1 Answers

1
votes

Since you're using spring-boot you may be better off using Microsoft's property source implementation that maps the keyvault properties into Spring properties and for local development and testing you set equivalent properties in property files.

Use Spring profiles. let's say you have azure and local profiles. In your application-azure.yml file configure your app to use keyvault:

# endpoint on the azure internal network for getting the identity access token

MSI_ENDPOINT: http://169.254.169.254/metadata/identity/oauth2/token
MSI_SECRET: unused

# this property triggers the use of keyvault for properties

azure.keyvault:
  uri: https://<your-keyvault-name>.vault.azure.net/

Now you can inject secret properties from the spring context into your variables and they will be read from keyvault:

  @Value("${superSecretValue}")
  String secretValue;

To make this work locally for testing, in your application-local.yml file you can set the secret property to something appropriate:

superSecretValue: dummy-for-testing-locally

The Azure dependency you need to add to build.gradle is:

implementation "com.microsoft.azure:azure-keyvault-secrets-spring-boot-starter:2.1.6"

Run your spring-boot jar with azure as the active profile when deployed, and local when testing and developing away from azure. This is tested and working with azure java containers.