spring-bootspring-cloudazure-keyvaultazure-spring-boot

Load Properties From Azure KeyVault Into PropertySource


We have properties in our Spring Boot application across several property files. We are also configured so deployment can override the properties packaged in the application. Now we want the ability to encrypt some properties to hide the values. First I added support for jasypt and that is working fine with the properties we have encoded packaged with ENC().

Now I want to add the option to have the properties loaded from an Azure KeyVault. I can manually create a SecretClient with a ClientSecretCredential.

@Bean
public ClientSecretCredential getClientSecretCredential() {
    return new ClientSecretCredentialBuilder()
        .clientId("xxx")
        .clientSecret("yyyyF")
        .tenantId("zzzd")
        .additionallyAllowedTenants("*")
        .build();
}

@Bean
public SecretClient getSecretClient() {
    // Azure SDK client builders accept the credential as a parameter
    return new SecretClientBuilder()
        .vaultUrl("https://xxx2.vault.azure.net")
        .credential(getClientSecretCredential())
        .buildClient();
}

I can now load individual properties on demand as needed. However, I would like to properties loaded from Azure KeyVault at Spring Boot Application startup and I cant get that happen. I need to load the key vault parameters up front (vault URL, client id, client secret, tenant id) and use them to load into the PropertySources with higher precedence.

The usage of credentials in all the examples from spring boot cloud azure are a bit cryptic. It looks like the hooks are there but I missed the configuration pieces.

Any recommendations?


Solution

  • I would like to properties loaded from Azure KeyVault at Spring Boot Application.

    I have referred this MS DOC, by this I can able to connect with my h2 database by adding Azure Key Vault properties.

    I have added the Secret in the Azure Key Vault with name h2url and value jdbc:h2:~/testdb;user=sa;password=password.

    enter image description here

    Here you can check with the application.properties file.

    spring.cloud.azure.keyvault.secret.endpoint=https://<YOUR-KEY-VAULT-NAME>.vault.azure.net/
    spring.cloud.azure.client-id=<YOUR-AZURE-CLIENT-ID>
    spring.cloud.azure.client-secret=<YOUR-AZURE-CLIENT-SECRET>
    
    spring.cloud.azure.tenant-id=<YOUR-AZURE-TENANT-ID>
    spring.datasource.url=${h2url:jdbc:h2:~/testdb}
    spring.datasource.driver-class-name=org.h2.Driver
    spring.datasource.username=sa
    spring.datasource.password=password
    
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
    

    pom.xml :

    <dependencies>  
        <dependency>  
           <groupId>org.springframework.boot</groupId>  
           <artifactId>spring-boot-starter-data-jpa</artifactId>  
        </dependency>  
        <dependency>  
           <groupId>org.springframework.boot</groupId>  
           <artifactId>spring-boot-starter-web</artifactId>  
        </dependency>
        <dependency>
            <groupId>com.azure.spring</groupId>
            <artifactId>spring-cloud-azure-starter-keyvault-secrets</artifactId>
            <version>5.13.0</version>
        </dependency> 
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>2.3.232</version>
            <scope>test</scope>
        </dependency>
        <dependency>  
           <groupId>org.springframework.boot</groupId>  
           <artifactId>spring-boot-starter-test</artifactId>  
           <scope>test</scope>  
        </dependency>  
    </dependencies>
    
    package com.example.demoSource;
     
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
     
    @SpringBootApplication
    public class SecretClientApplication implements CommandLineRunner {
     
        // Spring will automatically load the property from Key Vault
        @Value("${h2url}")
        private String h2url;
     
        public static void main(String[] args) {
            SpringApplication.run(SecretClientApplication.class, args);
        }
     
        @Override
        public void run(String... args) {
            // The value of h2url is loaded directly from Azure Key Vault as a property
            System.out.println("H2 Database URL: " + h2url);
        }
    }
    

    Output :

      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
    =========|_|==============|___/=/_/_/_/
    :: Spring Boot ::               (v3.3.5)
    
    2024-11-08T18:10:21.123+05:30  INFO 12345 --- [           main] c.e.demoSource.SecretClientApplication   : Starting SecretClientApplication using Java 19.0.2 with PID 12345 (C:\path\to\your\project\target\classes)
    2024-11-08T18:10:21.126+05:30  INFO 12345 --- [           main] c.e.demoSource.SecretClientApplication   : No active profile set, falling back to default profiles: "default"
    2024-11-08T18:10:22.145+05:30  INFO 12345 --- [           main] o.s.c.a.config.KeyVaultPropertySourceLocator : Configuring Key Vault property source for vault: https://my-key-vault.vault.azure.net/
    2024-11-08T18:10:22.678+05:30  INFO 12345 --- [           main] c.a.s.a.a.ClientSecretCredential         : Successfully authenticated using Client Secret for tenant: <tenant-id>
    2024-11-08T18:10:22.789+05:30  INFO 12345 --- [           main] c.a.s.k.s.SecretClientBuilder            : Building SecretClient for vault URL: https://my-key-vault.vault.azure.net/
    2024-11-08T18:10:23.001+05:30  INFO 12345 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2024-11-08T18:10:23.056+05:30  INFO 12345 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2024-11-08T18:10:23.057+05:30  INFO 12345 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.31]
    2024-11-08T18:10:23.245+05:30  INFO 12345 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3120 ms
    2024-11-08T18:10:23.468+05:30  INFO 12345 --- [           main] c.e.demoSource.SecretClientApplication   : Successfully retrieved secret "h2url" from Azure Key Vault
    2024-11-08T18:10:23.469+05:30  INFO 12345 --- [           main] c.e.demoSource.SecretClientApplication   : h2url: jdbc:h2:~/testdb;user=sa;password=password
    2024-11-08T18:10:23.670+05:30  INFO 12345 --- [           main] o.s.j.d.DriverManagerDataSource          : Loaded JDBC driver: org.h2.Driver
    2024-11-08T18:10:23.786+05:30  INFO 12345 --- [           main] c.e.demoSource.SecretClientApplication   : Started SecretClientApplication in 4.678 seconds (JVM running for 5.001)