Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions sdk/spring/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

### Spring Cloud Azure Autoconfigure

#### Features Added

- Added `spring.ssl.bundle.keyvault.<bundle-name>.keystore.certificate-alias-filter-patterns` and `spring.ssl.bundle.keyvault.<bundle-name>.truststore.certificate-alias-filter-patterns` configuration. The patterns are passed to the Key Vault JCA provider to limit which certificate aliases are loaded. ([#50013](https://github.com/Azure/azure-sdk-for-java/issues/50013))

#### Bugs Fixed

- Fixed Service Bus JMS listener containers using `JmsPoolConnectionFactory` when both `spring.jms.servicebus.pool.enabled=true` and `spring.jms.cache.enabled=false`. The sender continues to use `JmsPoolConnectionFactory`, while listener containers now use a dedicated `ServiceBusJmsConnectionFactory`, enabling topic subscriptions on the Standard tier. ([#49308](https://github.com/Azure/azure-sdk-for-java/issues/49308))
Expand Down
3 changes: 2 additions & 1 deletion sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Features Added

- Added `spring.ssl.bundle.keyvault.<bundle-name>.keystore.certificate-alias-filter-patterns` and `spring.ssl.bundle.keyvault.<bundle-name>.truststore.certificate-alias-filter-patterns` configuration. The patterns are passed to the Key Vault JCA provider to limit which certificate aliases are loaded. ([#50013](https://github.com/Azure/azure-sdk-for-java/issues/50013))

### Breaking Changes

### Bugs Fixed
Expand Down Expand Up @@ -253,4 +255,3 @@ Please refer to [spring/CHANGELOG.md](https://github.com/Azure/azure-sdk-for-jav
## 4.0.0-beta.2 (2021-11-22)

Please refer to [spring/CHANGELOG.md](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/spring/CHANGELOG.md#400-beta2-2021-11-22) for more details.

Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class AzureKeyVaultSslBundleRegistrar implements SslBundleRegistrar, Reso
"azure.keyvault.client-secret",
"azure.keyvault.managed-identity",
"azure.keyvault.jca.certificates-refresh-interval",
"azure.keyvault.jca.certificate-alias-filter-patterns",
"azure.keyvault.jca.refresh-certificates-when-have-un-trust-certificate",
"azure.cert-path.well-known",
"azure.cert-path.custom"
Expand Down Expand Up @@ -209,6 +210,10 @@ private static void configureJcaKeyStoreSystemProperties(AzureKeyVaultJcaPropert
pm.from(keyStoreProperties.getCertificatesRefreshInterval())
.when(Objects::nonNull)
.to(v -> System.setProperty("azure.keyvault.jca.certificates-refresh-interval", String.valueOf(v.toMillis())));
pm.from(keyStoreProperties.getCertificateAliasFilterPatterns())
.when(patterns -> !patterns.isEmpty())
.to(patterns -> System.setProperty("azure.keyvault.jca.certificate-alias-filter-patterns",
String.join(",", patterns)));
pm.from(keyStoreProperties.isRefreshCertificatesWhenHaveUntrustedCertificate())
.to(v -> System.setProperty("azure.keyvault.jca.refresh-certificates-when-have-un-trust-certificate", Boolean.toString(v)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
Expand Down Expand Up @@ -76,6 +78,12 @@ public static class KeyStoreProperties {
* Time interval to refresh all Key Vault certificate.
*/
private Duration certificatesRefreshInterval;
/**
* Key Vault certificate alias filter patterns. Include patterns are configured as regular expressions and
* exclude patterns are prefixed with {@code !}. If no patterns are configured, all certificate aliases are
* loaded.
*/
private final List<String> certificateAliasFilterPatterns = new ArrayList<>();

@NestedConfigurationProperty
private final CertificatePathsProperties certificatePaths = new CertificatePathsProperties();
Expand Down Expand Up @@ -104,6 +112,10 @@ public void setCertificatesRefreshInterval(Duration certificatesRefreshInterval)
this.certificatesRefreshInterval = certificatesRefreshInterval;
}

public List<String> getCertificateAliasFilterPatterns() {
return certificateAliasFilterPatterns;
}

public CertificatePathsProperties getCertificatePaths() {
return certificatePaths;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ void keyVaultJca() {
"spring.cloud.azure.keyvault.jca.vaults.kv2.endpoint=" + String.format(ENDPOINT, "test2"),
"spring.ssl.bundle.keyvault.testBundle1.truststore.certificate-paths.custom=classpath:keyvault/certificate-paths/custom",
"spring.ssl.bundle.keyvault.testBundle2.truststore.keyvault-ref=kv2",
"spring.ssl.bundle.keyvault.testBundle2.truststore.certificate-alias-filter-patterns[0]=^prod-.*",
"spring.ssl.bundle.keyvault.testBundle2.truststore.certificate-alias-filter-patterns[1]=!^prod-deprecated$",
"spring.ssl.bundle.keyvault.testBundle3.truststore.keyvault-ref=kv1",
"spring.ssl.bundle.keyvault.testBundle3.keystore.keyvault-ref=kv2"
"spring.ssl.bundle.keyvault.testBundle3.keystore.keyvault-ref=kv2",
"spring.ssl.bundle.keyvault.testBundle3.keystore.certificate-alias-filter-patterns[0]=client-cert",
"spring.ssl.bundle.keyvault.testBundle3.keystore.certificate-alias-filter-patterns[1]=!old-client-cert"
)
.run(context -> {
assertThat(context).hasSingleBean(AzureKeyVaultJcaAutoConfiguration.class);
Expand All @@ -71,8 +75,12 @@ void keyVaultJca() {
assertThat(sslBundlesProperties.getKeyvault()).hasSize(3);
assertThat(sslBundlesProperties.getKeyvault().get("testBundle1").getTruststore().getCertificatePaths().getCustom()).isEqualTo("classpath:keyvault/certificate-paths/custom");
assertThat(sslBundlesProperties.getKeyvault().get("testBundle2").getTruststore().getKeyvaultRef()).isEqualTo("kv2");
assertThat(sslBundlesProperties.getKeyvault().get("testBundle2").getTruststore()
.getCertificateAliasFilterPatterns()).containsExactly("^prod-.*", "!^prod-deprecated$");
assertThat(sslBundlesProperties.getKeyvault().get("testBundle3").getTruststore().getKeyvaultRef()).isEqualTo("kv1");
assertThat(sslBundlesProperties.getKeyvault().get("testBundle3").getKeystore().getKeyvaultRef()).isEqualTo("kv2");
assertThat(sslBundlesProperties.getKeyvault().get("testBundle3").getKeystore()
.getCertificateAliasFilterPatterns()).containsExactly("client-cert", "!old-client-cert");
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@

import java.security.KeyStore;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
Expand Down Expand Up @@ -95,7 +98,8 @@ void notConfigureEndpointOrSslBundleProperties(CapturedOutput capturedOutput) {
void registerKeyVaultSslBundle(CapturedOutput capturedOutput) {
AzureKeyVaultJcaProperties jcaProperties = new AzureKeyVaultJcaProperties();
AzureKeyVaultSslBundleProperties sslBundleProperties = new AzureKeyVaultSslBundleProperties();
AzureKeyVaultSslBundleRegistrar registrar = new AzureKeyVaultSslBundleRegistrar(jcaProperties, sslBundleProperties);
AzureKeyVaultSslBundleRegistrar registrar
= new AzureKeyVaultSslBundleRegistrar(jcaProperties, sslBundleProperties);
registrar.setResourceLoader(new DefaultResourceLoader());
SslBundleRegistry registry = Mockito.mock(SslBundleRegistry.class);

Expand Down Expand Up @@ -209,6 +213,47 @@ void registerMultipleSslBundles(CapturedOutput capturedOutput) {
}
}

@Test
void configureCertificateAliasFilterPatterns() {
AzureKeyVaultJcaProperties jcaProperties = new AzureKeyVaultJcaProperties();
AzureKeyVaultSslBundleProperties sslBundleProperties = new AzureKeyVaultSslBundleProperties();
AzureKeyVaultSslBundleRegistrar registrar = new AzureKeyVaultSslBundleRegistrar(jcaProperties, sslBundleProperties);
registrar.setResourceLoader(new DefaultResourceLoader());

try (MockedStatic<KeyStore> keyStoreMockedStatic = mockStatic(KeyStore.class)) {
KeyStore keyStore = Mockito.mock(KeyStore.class);
List<String> configuredFilterPatterns = new ArrayList<>();
keyStoreMockedStatic.when(() -> KeyStore.getInstance(KeyVaultJcaProvider.PROVIDER_NAME))
.thenAnswer(invocation -> {
configuredFilterPatterns.add(
System.getProperty("azure.keyvault.jca.certificate-alias-filter-patterns"));
return keyStore;
});

AzureKeyVaultJcaProperties.JcaVaultProperties vaultProperties
= new AzureKeyVaultJcaProperties.JcaVaultProperties();
vaultProperties.setEndpoint("https://test.vault.azure.net/");
jcaProperties.getVaults().put("keyvault1", vaultProperties);

AzureKeyVaultSslBundleProperties.KeyVaultSslBundleProperties bundleProperties
= new AzureKeyVaultSslBundleProperties.KeyVaultSslBundleProperties();
bundleProperties.getKeystore().setKeyvaultRef("keyvault1");
bundleProperties.getKeystore().getCertificateAliasFilterPatterns()
.addAll(Arrays.asList("^prod-.*", "!^prod-deprecated$"));
bundleProperties.getTruststore().setKeyvaultRef("keyvault1");
bundleProperties.getTruststore().getCertificateAliasFilterPatterns()
.addAll(Arrays.asList("^partner-.*", "!^partner-deprecated$"));
sslBundleProperties.getKeyvault().put("testBundle", bundleProperties);

registrar.registerBundles(Mockito.mock(SslBundleRegistry.class));

assertThat(configuredFilterPatterns)
.containsExactly("^prod-.*,!^prod-deprecated$", "^partner-.*,!^partner-deprecated$");
} finally {
System.clearProperty("azure.keyvault.jca.certificate-alias-filter-patterns");
}
}

@Test
void keyVaultProviderNotInsertedAtHighestPriority() {
AzureKeyVaultJcaProperties jcaProperties = new AzureKeyVaultJcaProperties();
Expand Down