Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 5, 2025

When spring.cloud.azure.profile.cloud-type=azure_china is set globally but scopes are not explicitly configured for JDBC/Redis passwordless connections, the scopes incorrectly default to Azure Global (https://ossrdbms-aad.database.windows.net/.default) instead of Azure China (https://ossrdbms-aad.database.chinacloudapi.cn/.default).

Root Cause

AzurePasswordlessPropertiesUtils.copyAzureCommonPropertiesIgnoreNull() unconditionally copies scopes by calling source.getScopes(). For implementations like AzureJdbcPasswordlessProperties, this returns a computed default based on cloud type. During property merging:

  1. Global properties (with cloud-type=AZURE_CHINA) are copied to target
  2. Datasource-specific properties are merged via copyAzureCommonPropertiesIgnoreNull()
  3. source.getScopes() computes default using source's unset cloud type → returns Azure Global scope
  4. This overwrites the target's correct cloud type, preventing proper scope computation

Changes

Modified scope copying logic in AzurePasswordlessPropertiesUtils:

  • Only copy scopes if explicitly set by user (scopes field is non-null)
  • Use reflection to distinguish explicit values from computed defaults
  • Preserve backward compatibility with fallback behavior

Added tests:

  • Azure China cloud type scenario with default scopes
  • Explicit scopes override behavior
  • Integration test in JdbcPropertiesBeanPostProcessorTest
// Before: scopes always copied, overwriting correct defaults
target.setScopes(source.getScopes());

// After: only copy if explicitly set
if (isScopesExplicitlySet(source)) {
    target.setScopes(source.getScopes());
}

Fixes #43195

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • login.microsoftonline.com
  • oss.jfrog.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.11/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.11/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.11 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.11/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure org.codehaus.plexus.classworlds.launcher.Launcher clean test -Dtest=JdbcPropertiesBeanPostProcessorTest (dns block)
  • sample-propertysource.vault.azure.net
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -javaagent:/home/REDACTED/.m2/repository/org/jacoco/org.jacoco.agent/0.8.13/org.jacoco.agent-0.8.13-runtime.jar=destfile=/home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/jacoco-unit.exec,excludes=META-INF/** -Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/spring-cloud-azure-autoconfigure-oom.hprof -XX:+CrashOnOutOfMemoryError --add-opens java.base/java.lang.invoke=com.azure.core org.apache.maven.surefire.booter.ForkedBooter /home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/surefire 2025-11-05T09-17-25_166-jvmRun1 surefire-20251105091725250_1tmp surefire_0-20251105091725250_2tmp (dns block)
  • sample.servicebus.windows.net
  • sample.somelocation.eventgrid.azure.net
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -javaagent:/home/REDACTED/.m2/repository/org/jacoco/org.jacoco.agent/0.8.13/org.jacoco.agent-0.8.13-runtime.jar=destfile=/home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/jacoco-unit.exec,excludes=META-INF/** -Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/spring-cloud-azure-autoconfigure-oom.hprof -XX:+CrashOnOutOfMemoryError --add-opens java.base/java.lang.invoke=com.azure.core org.apache.maven.surefire.booter.ForkedBooter /home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/surefire 2025-11-05T09-17-25_166-jvmRun1 surefire-20251105091725250_1tmp surefire_0-20251105091725250_2tmp (dns block)
  • sample.vault.azure.net
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -javaagent:/home/REDACTED/.m2/repository/org/jacoco/org.jacoco.agent/0.8.13/org.jacoco.agent-0.8.13-runtime.jar=destfile=/home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/jacoco-unit.exec,excludes=META-INF/** -Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/spring-cloud-azure-autoconfigure-oom.hprof -XX:+CrashOnOutOfMemoryError --add-opens java.base/java.lang.invoke=com.azure.core org.apache.maven.surefire.booter.ForkedBooter /home/REDACTED/work/azure-sdk-for-java/azure-sdk-for-java/sdk/spring/spring-cloud-azure-autoconfigure/target/surefire 2025-11-05T09-17-25_166-jvmRun1 surefire-20251105091725250_1tmp surefire_0-20251105091725250_2tmp (dns block)
  • test-namespace.servicebus.windows.net

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>[BUG] azure.scopes is wrong when set spring.cloud.azure.profile.cloud-type=azure_china</issue_title>
<issue_description>Describe the bug
When use the passwordless feature of PostgreSQL, the azure.scopes is https://ossrdbms-aad.database.windows.net/.default when set spring.cloud.azure.profile.cloud-type=azure_china. The https://ossrdbms-aad.database.windows.net/.default is for Azure Global, not for Azure China

Exception or Stack Trace

Failed to connect to PostgreSQL: Something unusual has occurred to cause the driver to fail. Please report this exception.
org.postgresql.util.PSQLException: Something unusual has occurred to cause the driver to fail. Please report this exception.
	at org.postgresql.Driver.connect(Driver.java:320)
	at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
	at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359)
	at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201)
	at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470)
	at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561)
	at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100)
	at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112)
	at com.example.Main.lambda$run$0(Main.java:22)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:786)
	at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:770)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:765)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:330)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331)
	at com.example.Main.main(Main.java:16)
Caused by: com.azure.identity.CredentialUnavailableException: Managed Identity authentication is not available.
	at com.azure.identity.implementation.IdentityClient.lambda$getTokenFromMsalMIClient$28(IdentityClient.java:535)
	at reactor.core.publisher.Mono.lambda$onErrorMap$28(Mono.java:3799)
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:241)
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:315)
	at reactor.core.publisher.MonoCompletionStage$MonoCompletionStageSubscription.apply(MonoCompletionStage.java:115)
	at reactor.core.publisher.MonoCompletionStage$MonoCompletionStageSubscription.apply(MonoCompletionStage.java:67)
	at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)
	at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1773)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java)
	at --- Async.Stack.Trace --- (captured by IntelliJ IDEA debugger)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.<init>(CompletableFuture.java:1754)
	at java.base/java.util.concurrent.CompletableFuture.asyncSupplyStage(CompletableFuture.java:1782)
	at java.base/java.util.concurrent.CompletableFuture.supplyAsync(CompletableFuture.java:2005)
	at com.microsoft.aad.msal4j.AbstractApplicationBase.executeRequest(AbstractApplicationBase.java:47)
	at com.microsoft.aad.msal4j.ManagedIdentityApplication.acquireTokenForManagedIdentity(ManagedIdentityApplication.java:40)
	at com.azure.identity.implementation.IdentityClient.lambda$getTokenFromMsalMIClient$26(IdentityClient.java:530)
	at reactor.core.publisher.Mono.lambda$fromFuture$1(Mono.java:685)
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:45)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:165)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1865)
	at reactor.core.publisher.MonoCacheTime.subscribeOrReturn(Mon...

</details>

- Fixes Azure/azure-sdk-for-java#47096

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Copilot AI and others added 2 commits November 5, 2025 09:14
- Modified AzurePasswordlessPropertiesUtils.copyAzureCommonPropertiesIgnoreNull to only copy scopes if explicitly set
- Added reflection-based check to determine if scopes field is null before copying
- This ensures that when cloud-type is set globally but scopes are not explicitly configured, the merged properties will use the correct default scopes based on cloud type
- Added tests for Azure China cloud type scenario
- Updated Azure US Government test to use correct scopes

Co-authored-by: saragluna <[email protected]>
- Improved documentation for isScopesExplicitlySet() method explaining why reflection is used
- Enhanced exception handling to cover SecurityException and provide better fallback behavior
- Fixed hardcoded scope URL in test to use constant from test class
- Made test constants public static for better reusability

Co-authored-by: saragluna <[email protected]>
Copilot AI changed the title [WIP] Fix azure.scopes for azure_china cloud type Fix Azure scopes defaulting to Global when cloud-type is Azure China Nov 5, 2025
Copilot AI requested a review from saragluna November 5, 2025 09:25
Copilot finished work on behalf of saragluna November 5, 2025 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants