azure-sdk-for-java
azure-sdk-for-java copied to clipboard
Azure Key Vault- How to use AzureCliCredential first when using spring.cloud.azure.keyvault.secret.property-sources[0].endpoint
Discussed in https://github.com/Azure/azure-sdk-for-java/discussions/38982
regarding this https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/configure-spring-boot-starter-java-app-with-azure-key-vault#use-spring-key-vault-propertysource
Issue with spring-cloud-azure-starter-keyvault 5.9.1
Originally posted by lavercr February 28, 2024 There is a really large delay when using spring.cloud.azure.keyvault.secret.property-sources[0].endpoint The delay is more than 2 mins.
When I do this using AzureCliCredential directly my spring boot app loads and finds the key in seconds. How can I configure spring.cloud.azure.keyvault.secret.property-sources[0].endpoint to only use AzureCliCredential for authentication.
using : springboot 3.2.2 sring-cloud-azure-dependencies 5.9.1 JavaSE-17 (OpenJDK 21.0.1) az cli 2.57.0 running on MacOS 14.3
logs
[2m2024-02-28T11:46:45.153-05:00 [0;39m [32m INFO [0;39m [35m34603 [0;39m [2m--- [0;39m [2m[ main] [0;39m [2m [0;39m [36mm.p.s.SpringbootAzureKeyvaultApplication [0;39m [2m: [0;39m Starting SpringbootAzureKeyvaultApplication using Java 21.0.1 with PID 34603 (/Users/lavercr/src/springboot-azure-keyvault/target/classes started by lavercr in /Users/lavercr/src/springboot-azure-keyvault)
[2m2024-02-28T11:46:45.154-05:00 [0;39m [32m INFO [0;39m [35m34603 [0;39m [2m--- [0;39m [2m[ main] [0;39m [2m [0;39m [36mm.p.s.SpringbootAzureKeyvaultApplication [0;39m [2m: [0;39m No active profile set, falling back to 1 default profile: "default"
[2m2024-02-28T11:46:45.642-05:00 [0;39m [32m INFO [0;39m [35m34603 [0;39m [2m--- [0;39m [2m[ main] [0;39m [2m [0;39m [36mAbstractAzureServiceClientBuilderFactory [0;39m [2m: [0;39m Will configure the default credential of type DefaultAzureCredential for class com.azure.identity.DefaultAzureCredentialBuilder.
[2m2024-02-28T11:46:45.710-05:00 [0;39m [32m INFO [0;39m [35m34603 [0;39m [2m--- [0;39m [2m[ main] [0;39m [2m [0;39m [36mm.p.s.SpringbootAzureKeyvaultApplication [0;39m [2m: [0;39m Started **SpringbootAzureKeyvaultApplication in 141.667 seconds (process running for 142.235)**
Hi @lavercr thanks for reaching out to us via this github issue. @saragluna @backwind1233 could you please follow up?
/cc @vcolin7
Hi @lavercr , thanks for reaching out, Could help provide more info about how to use AzureCliCredential directly?
If I create my own secretClient using AzureCliCredentialBuilder I can connect and pull passwords, but this way I have to write all the code. I would like to keep to the one liner that spring.cloud.azure.keyvault.secret.property-sources[0].endpoint gives us. This loads all the secrets and makes them available to the spring beans right away. If I do it myself it is more code, and the beans with secrets have to depend on this bean loading first. That gets messy quick.
@Configuration
public class AzureKeyVaultConfig {
@Value("${spring.cloud.azure.keyvault.secret.uri}")
private String keyVaultUri;
@Bean
SecretClient secretClient() {
AzureCliCredential cliCredential = new AzureCliCredentialBuilder().build();
// Azure SDK client builders accept the credential as a parameter.
return new SecretClientBuilder()
.vaultUrl(keyVaultUri)
.credential(cliCredential)
.buildClient();
}
}
Hi @lavercr , we don't support use AzureCliCredential directly, but you can add this code to only use AzureCliCredential for authentication.
@Bean(name = DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)
TokenCredential tokenCredential( ) {
return new AzureCliCredentialBuilder().build();
}
Hi, I don't understand your solution. Does this need a specific bean name ? I put a dummy name in and it still took a long time to respond.
can you provide a more complete example that uses
spring.cloud.azure.keyvault.secret.property-sources[0].endpoint
and
@Bean(name = DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)
TokenCredential tokenCredential( ) {
return new AzureCliCredentialBuilder().build();
}
Hi @lavercr , could you help provide your minimal project?
can you provide a more complete example that uses
spring.cloud.azure.keyvault.secret.property-sources[0].endpointand
@Bean(name = DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME) TokenCredential tokenCredential( ) { return new AzureCliCredentialBuilder().build(); }
can you provide me an example with this working. where spring.cloud.azure.keyvault.secret.property-sources uses TokenCredential tokenCredential( ) {
create a springboot application with required azure dependencies
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-keyvault</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-dependencies</artifactId>
<version>5.9.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
add this entry into your application.properties file that points to your working key vault
spring.cloud.azure.keyvault.secret.property-sources[0].endpoint=[Your key vault url]
Add a secret to your vault called TestSecret
Setup your main class like this
package com.mbc.poc.springbootazurekeyvault;
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 SpringbootAzureKeyvaultApplication implements CommandLineRunner {
@Value("${TestSecret}")
private String testSecret;
public static void main(String[] args) {
SpringApplication.run(SpringbootAzureKeyvaultApplication.class, args);
}
@Override
public void run(String... args) {
System.out.println("TestSecret: " + testSecret);
}
}
Determine how to use AzureCliCredentialBuilder in the authentication options first
create a springboot application with required azure dependencies
<dependencies> <dependency> <groupId>com.azure.spring</groupId> <artifactId>spring-cloud-azure-starter-keyvault</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>com.azure.spring</groupId> <artifactId>spring-cloud-azure-dependencies</artifactId> <version>5.9.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>add this entry into your application.properties file that points to your working key vault
spring.cloud.azure.keyvault.secret.property-sources[0].endpoint=[Your key vault url]Add a secret to your vault called TestSecret
Setup your main class like this
package com.mbc.poc.springbootazurekeyvault; 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 SpringbootAzureKeyvaultApplication implements CommandLineRunner { @Value("${TestSecret}") private String testSecret; public static void main(String[] args) { SpringApplication.run(SpringbootAzureKeyvaultApplication.class, args); } @Override public void run(String... args) { System.out.println("TestSecret: " + testSecret); } }Determine how to use AzureCliCredentialBuilder in the authentication options first
OK, I update your codes, hope this can help
package com.mbc.poc.springbootazurekeyvault;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME;
@SpringBootApplication
public class SpringbootAzureKeyvaultApplication implements CommandLineRunner {
@Value("${TestSecret}")
private String testSecret;
public static void main(String[] args) {
SpringApplication.run(SpringbootAzureKeyvaultApplication.class, args);
}
@Override
public void run(String... args) {
System.out.println("TestSecret: " + testSecret);
}
@Bean(name = DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)
TokenCredential tokenCredential( ) {
return new AzureCliCredentialBuilder().build();
}
}
This doesn't work for myself. We have a similar issue where development is done on Azure VMs and would like to override the Default to CLI so that property placeholders also work.
Setting the SecretClientBuilder bean to CLI works inside Application but then the KV EnvironmentPostProcessor just uses the Default.
I agree, this still seems to be using the default. I will see if I can find any logging category I can turn on.
Started SpringbootAzureKeyvaultApplication in 148.961 seconds (process running for 149.767)
Unable to find any logging I can turn on to give clarity to what is delaying startup. I am still assuming it is because it trys AzureCliCredential last to connect to azure key vault.
I believe there is a bug that needs fixing
spring.cloud.azure.keyvault.secret.property-sources does not adhere to
@Bean(name = DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)
TokenCredential tokenCredential( ) {
return new AzureCliCredentialBuilder().build();
}
I've got it working using a custom/changed version KeyVaultEnvironmentPostProcessor, setting it to use CLI, using a custom prefix for the properties and adding it to spring.factories in META-INF. It's a nasty hack but best available right now. Loading takes ~10s.
Can we confirm then that this is a bug. The fact that spring.cloud.azure.keyvault.secret.property-sources does not adhere to DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME
any update?
sorry for the late response and we will take a look about that
@lavercr, this is because the environment processor at an earlier stage, before the default azure credential bean's initialization. To change this behavior, we need to do some refactor, but users need to register the DAC bean in another way.
we need to do some refactor.. So there may be a fix coming our way ?
we need to be able to control the order.
@saragluna Can I have an update for this fix?
Sorry, this update requires code refactoring, which we need more time to discuss.
Do you have an update? This is going to be critical for our business unit in the next few months.
any possible way to get more frequent updates? or are you able to give me a patch to work around this issue ?
Not yet, but your contributions are welcome if you are interested
Okay. I get it. I will have to live with it or create a bandage.
@Netyyyy I have been asked for a date of fix. Please provide. This issue is holding up a security compliancy issue at our company. If there is another place or contact we can reach out to so we can get this fixed please let me know.
Thank you