Skip to content

Support multiple data source prop passwordless and new prop of credential bean name #42486

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c0de5df
Fix primitive type copy issue
moarychan Sep 27, 2024
acc1255
Support enhance multiple datasource properties
moarychan Oct 21, 2024
3cad5ad
Avoid configuring conn string if credential has been configured.
moarychan Oct 21, 2024
fa32e5a
Avoid overriding service bus client credential and make the resource …
moarychan Oct 21, 2024
433f082
Support customizing the credential for Service Bus sPRING Integration…
moarychan Oct 21, 2024
28ac8cd
Support customizing the credential for Service Bus sPRING Integration…
moarychan Oct 21, 2024
f3abae4
Support customizing the credential for Redis passwordless scenario
moarychan Oct 21, 2024
052537a
Fix ut failures: duplicate global properties beans, new dependency fo…
moarychan Oct 21, 2024
52263a7
Update change log
moarychan Oct 21, 2024
ba4f2f9
Fix code smells
moarychan Oct 21, 2024
5591dec
Update revapi: addedToInterface
moarychan Oct 21, 2024
0a68acb
Decouple application context for AzureRedisCredentials
moarychan Oct 22, 2024
641fde3
Remove public access modifier and static keyword
moarychan Oct 23, 2024
de2b137
Resolve comments
moarychan Oct 28, 2024
cf4df22
Fix code smells
moarychan Oct 29, 2024
e34a913
Use the fixed class loader
moarychan Oct 29, 2024
e4f22a7
Use null class loader
moarychan Oct 29, 2024
993d338
Fix ut failure, ignore provider bean creation since the custom class …
moarychan Oct 29, 2024
4d31743
Resolve comments
moarychan Oct 29, 2024
3413d56
Resolve comments
moarychan Oct 30, 2024
5504e05
Resolve comments
moarychan Oct 30, 2024
26ef977
Resolve comments
moarychan Oct 30, 2024
26fe49e
Remove unused code
moarychan Oct 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,11 @@
"new": "method void com.mysql.cj.protocol.ServerSession::setOldStatusFlags(int)",
"justification": "Method was added to an interface."
},
{
"code": "java.method.addedToInterface",
"new": "method java.lang.String com.azure.spring.cloud.core.provider.authentication.TokenCredentialOptionsProvider.TokenCredentialOptions::getTokenCredentialBeanName()",
"justification": "Support to configure token credential bean name."
},
{
"code": "java.annotation.added",
"old": "method com.azure.cosmos.CosmosDiagnosticsContext com.azure.cosmos.CosmosDiagnostics::getDiagnosticsContext()",
Expand Down
7 changes: 7 additions & 0 deletions sdk/spring/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
### Spring Cloud Azure Autoconfigure
This section includes changes in `spring-cloud-azure-autoconfigure` module.

#### Features Added
- Support to configure token credential bean name. [#41977](https://github.com/Azure/azure-sdk-for-java/issues/41977).

#### Bugs Fixed
- Fix primitive type prop (isManagedIdentityEnabled) copy issue. [#41977](https://github.com/Azure/azure-sdk-for-java/issues/41977).
- Fix to support multiple JDBC datasource prop passwordless. [#41977](https://github.com/Azure/azure-sdk-for-java/issues/41977).

#### Breaking Changes
- Change the default Service Bus JMS connection factory to `JmsPoolConnectionFactory` from `CachingConnectionFactory`. Set `spring.jms.cache.enabled=true` to continue using `CachingConnectionFactory` [#42306](https://github.com/Azure/azure-sdk-for-java/pull/42306).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,10 @@ private AzureContextUtils() {
*/
public static final String PASSWORDLESS_KAFKA_PROPERTIES_BEAN_POST_PROCESSOR_BEAN_NAME =
"azurePasswordlessKafkaPropertiesBeanPostProcessor";

/**
* Bean name of the SpringTokenCredentialProviderContextProvider for the passwordless token credential acquisition.
*/
public static final String SPRING_TOKEN_CREDENTIAL_PROVIDER_CONTEXT_BEAN_NAME =
"springTokenCredentialProviderContextProvider";
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties;
import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
Expand All @@ -14,8 +15,10 @@
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;

import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.AZURE_GLOBAL_PROPERTY_BEAN_NAME;
import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.SPRING_TOKEN_CREDENTIAL_PROVIDER_CONTEXT_BEAN_NAME;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;

/**
Expand All @@ -29,6 +32,9 @@ public class AzureGlobalPropertiesAutoConfiguration {
static class Registrar implements EnvironmentAware, ImportBeanDefinitionRegistrar {
private Environment environment;

private static final String AZURE_AUTHENTICATION_TEMPLATE_CLASS_NAME =
"com.azure.identity.extensions.implementation.template.AzureAuthenticationTemplate";

@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
Expand All @@ -38,12 +44,14 @@ public void setEnvironment(Environment environment) {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(AZURE_GLOBAL_PROPERTY_BEAN_NAME)) {
registry.registerBeanDefinition(AZURE_GLOBAL_PROPERTY_BEAN_NAME,
genericBeanDefinition(AzureGlobalProperties.class,
() -> Binder.get(this.environment)
.bindOrCreate(AzureGlobalProperties.PREFIX,
AzureGlobalProperties.class))
.getBeanDefinition());
BeanDefinitionBuilder definitionBuilder = genericBeanDefinition(AzureGlobalProperties.class,
() -> Binder.get(this.environment)
.bindOrCreate(AzureGlobalProperties.PREFIX,
AzureGlobalProperties.class));
if (ClassUtils.isPresent(AZURE_AUTHENTICATION_TEMPLATE_CLASS_NAME, null)) {
definitionBuilder.addDependsOn(SPRING_TOKEN_CREDENTIAL_PROVIDER_CONTEXT_BEAN_NAME);
}
registry.registerBeanDefinition(AZURE_GLOBAL_PROPERTY_BEAN_NAME, definitionBuilder.getBeanDefinition());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.springframework.boot.task.TaskExecutorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils;
Expand All @@ -55,10 +56,12 @@
public class AzureTokenCredentialAutoConfiguration extends AzureServiceConfigurationBase {
private static final Logger LOGGER = LoggerFactory.getLogger(AzureTokenCredentialAutoConfiguration.class);

private final GenericApplicationContext applicationContext;
private final IdentityClientProperties identityClientProperties;

AzureTokenCredentialAutoConfiguration(AzureGlobalProperties azureGlobalProperties) {
AzureTokenCredentialAutoConfiguration(GenericApplicationContext applicationContext, AzureGlobalProperties azureGlobalProperties) {
super(azureGlobalProperties);
this.applicationContext = applicationContext;
this.identityClientProperties = loadProperties(azureGlobalProperties, new IdentityClientProperties());
}

Expand Down Expand Up @@ -101,6 +104,11 @@ AzureTokenCredentialResolver azureTokenCredentialResolver(
return null;
}

String tokenCredentialBeanName = azureProperties.getCredential().getTokenCredentialBeanName();
if (StringUtils.hasText(tokenCredentialBeanName)) {
return this.applicationContext.getBean(tokenCredentialBeanName, TokenCredential.class);
}

final TokenCredentialOptionsProvider.TokenCredentialOptions properties = azureProperties.getCredential();
final String tenantId = azureProperties.getProfile().getTenantId();
final String clientId = properties.getClientId();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.spring.cloud.autoconfigure.implementation.context;

import com.azure.identity.extensions.implementation.template.AzureAuthenticationTemplate;
import com.azure.spring.cloud.autoconfigure.implementation.jdbc.SpringTokenCredentialProviderContextProvider;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.SPRING_TOKEN_CREDENTIAL_PROVIDER_CONTEXT_BEAN_NAME;

/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Cloud Azure {@link SpringTokenCredentialProviderContextProvider}.
*
* @since 5.17.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(AzureAuthenticationTemplate.class)
class SpringTokenCredentialProviderContextProviderAutoConfiguration {

@Bean(name = SPRING_TOKEN_CREDENTIAL_PROVIDER_CONTEXT_BEAN_NAME)
@ConditionalOnMissingBean
SpringTokenCredentialProviderContextProvider springTokenCredentialProviderContextProvider() {
return new SpringTokenCredentialProviderContextProvider();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
package com.azure.spring.cloud.autoconfigure.implementation.data.redis;

import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties;
import com.azure.spring.cloud.autoconfigure.implementation.passwordless.properties.AzureRedisPasswordlessProperties;
import com.azure.spring.cloud.autoconfigure.implementation.data.redis.lettuce.AzureRedisCredentials;
import com.azure.spring.cloud.autoconfigure.implementation.passwordless.properties.AzureRedisPasswordlessProperties;
import com.azure.spring.cloud.core.implementation.util.AzurePasswordlessPropertiesUtils;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.RedisCredentials;
Expand Down Expand Up @@ -54,8 +54,8 @@ AzureRedisPasswordlessProperties redisPasswordlessProperties() {
AzureRedisCredentials azureRedisCredentials(RedisProperties redisProperties,
AzureRedisPasswordlessProperties azureRedisPasswordlessProperties,
AzureGlobalProperties azureGlobalProperties) {
return new AzureRedisCredentials(redisProperties.getUsername(),
mergeAzureProperties(azureGlobalProperties, azureRedisPasswordlessProperties));
AzureRedisPasswordlessProperties redisPasswordlessProperties = mergeAzureProperties(azureGlobalProperties, azureRedisPasswordlessProperties);
return new AzureRedisCredentials(redisProperties.getUsername(), redisPasswordlessProperties);
}

@Bean(name = "azureLettuceClientConfigurationBuilderCustomizer")
Expand All @@ -81,5 +81,4 @@ private AzureRedisPasswordlessProperties mergeAzureProperties(AzureGlobalPropert
AzurePasswordlessPropertiesUtils.mergeAzureCommonProperties(azureGlobalProperties, azurePasswordlessProperties, mergedProperties);
return mergedProperties;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.Properties;

import static com.azure.spring.cloud.autoconfigure.implementation.util.SpringPasswordlessPropertiesUtils.enhancePasswordlessProperties;

public class AzureRedisCredentials implements RedisCredentials {

Expand All @@ -25,9 +28,11 @@ public class AzureRedisCredentials implements RedisCredentials {
* Create instance of Azure Redis Credentials
*/
public AzureRedisCredentials(String username, PasswordlessProperties passwordlessProperties) {
Objects.requireNonNull(passwordlessProperties, "PasswordlessProperties is required");
Objects.requireNonNull(passwordlessProperties, "PasswordlessProperties is required.");
azureAuthenticationTemplate = new AzureAuthenticationTemplate();
azureAuthenticationTemplate.init(passwordlessProperties.toPasswordlessProperties());
Properties properties = passwordlessProperties.toPasswordlessProperties();
enhancePasswordlessProperties("spring.data.redis.azure", passwordlessProperties, properties);
azureAuthenticationTemplate.init(properties);
this.username = resolveUsername(azureAuthenticationTemplate, username);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;


/**
Expand All @@ -29,15 +28,7 @@ public class AzureJdbcAutoConfiguration {

@Bean
@ConditionalOnMissingBean
@DependsOn("springTokenCredentialProviderContextProvider")
JdbcPropertiesBeanPostProcessor jdbcConfigurationPropertiesBeanPostProcessor() {
return new JdbcPropertiesBeanPostProcessor();
}

@Bean
@ConditionalOnMissingBean
SpringTokenCredentialProviderContextProvider springTokenCredentialProviderContextProvider() {
return new SpringTokenCredentialProviderContextProvider();
}

}
Loading
Loading