From f4f24e312ff30f298ed9a237cf41ff7e4095a3a0 Mon Sep 17 00:00:00 2001 From: Kaveh Shamsi Date: Fri, 18 Oct 2024 15:59:44 +0200 Subject: [PATCH] Fixes the SpringVaultEnvironmentRepository issue with composite profile (#2595) Signed-off-by: kvmw --- .../EnvironmentRepositoryConfiguration.java | 14 +++-- ...ringVaultEnvironmentRepositoryFactory.java | 14 ++++- .../vault/SpringVaultTemplateBuilder.java | 52 +++++++++++++++++++ ...aultEnvironmentRepositoryFactoryTests.java | 52 ++++++++++++++++--- 4 files changed, 119 insertions(+), 13 deletions(-) create mode 100644 spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultTemplateBuilder.java diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java index bdfd8237..e0bd26ee 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java @@ -85,12 +85,15 @@ import org.springframework.cloud.config.server.environment.SvnKitEnvironmentRepo import org.springframework.cloud.config.server.environment.VaultEnvironmentProperties; import org.springframework.cloud.config.server.environment.VaultEnvironmentRepository; import org.springframework.cloud.config.server.environment.VaultEnvironmentRepositoryFactory; +import org.springframework.cloud.config.server.environment.vault.SpringVaultClientAuthenticationProvider; import org.springframework.cloud.config.server.environment.vault.SpringVaultClientConfiguration; import org.springframework.cloud.config.server.environment.vault.SpringVaultEnvironmentRepository; import org.springframework.cloud.config.server.environment.vault.SpringVaultEnvironmentRepositoryFactory; +import org.springframework.cloud.config.server.environment.vault.SpringVaultTemplateBuilder; import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory; import org.springframework.cloud.config.server.support.GoogleCloudSourceSupport; import org.springframework.cloud.config.server.support.TransportConfigCallbackFactory; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -312,11 +315,16 @@ public class EnvironmentRepositoryConfiguration { @Import(SpringVaultClientConfiguration.class) static class SpringVaultFactoryConfig { + @Bean + public SpringVaultTemplateBuilder springVaultTemplateBuilder(ConfigTokenProvider configTokenProvider, + List authProviders, ApplicationContext applicationContext) { + return new SpringVaultTemplateBuilder(configTokenProvider, authProviders, applicationContext); + } + @Bean public SpringVaultEnvironmentRepositoryFactory vaultEnvironmentRepositoryFactory( - ObjectProvider request, EnvironmentWatch watch, - SpringVaultClientConfiguration vaultClientConfiguration) { - return new SpringVaultEnvironmentRepositoryFactory(request, watch, vaultClientConfiguration); + ObjectProvider request, EnvironmentWatch watch, SpringVaultTemplateBuilder springVaultTemplateBuilder) { + return new SpringVaultEnvironmentRepositoryFactory(request, watch, springVaultTemplateBuilder); } } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactory.java index a1cfdb96..ffc7b12d 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactory.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactory.java @@ -37,8 +37,11 @@ public class SpringVaultEnvironmentRepositoryFactory private final EnvironmentWatch watch; - private final SpringVaultClientConfiguration clientConfiguration; + private SpringVaultClientConfiguration clientConfiguration; + private SpringVaultTemplateBuilder vaultTemplateBuilder; + + @Deprecated public SpringVaultEnvironmentRepositoryFactory(ObjectProvider request, EnvironmentWatch watch, SpringVaultClientConfiguration clientConfiguration) { this.request = request; @@ -46,9 +49,16 @@ public class SpringVaultEnvironmentRepositoryFactory this.clientConfiguration = clientConfiguration; } + public SpringVaultEnvironmentRepositoryFactory(ObjectProvider request, EnvironmentWatch watch, SpringVaultTemplateBuilder vaultTemplateBuilder) { + this.request = request; + this.watch = watch; + this.vaultTemplateBuilder = vaultTemplateBuilder; + } + @Override public SpringVaultEnvironmentRepository build(VaultEnvironmentProperties vaultProperties) { - VaultTemplate vaultTemplate = clientConfiguration.vaultTemplate(); + VaultTemplate vaultTemplate = this.vaultTemplateBuilder != null + ? this.vaultTemplateBuilder.build(vaultProperties) : clientConfiguration.vaultTemplate(); VaultKeyValueOperations accessStrategy = buildVaultAccessStrategy(vaultProperties, vaultTemplate); diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultTemplateBuilder.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultTemplateBuilder.java new file mode 100644 index 00000000..ad60c7e5 --- /dev/null +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultTemplateBuilder.java @@ -0,0 +1,52 @@ +/* + * Copyright 2018-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.config.server.environment.vault; + +import java.util.List; + +import org.springframework.cloud.config.server.environment.ConfigTokenProvider; +import org.springframework.cloud.config.server.environment.VaultEnvironmentProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.vault.core.VaultTemplate; + +/** + * @author Kaveh Shamsi + */ +public class SpringVaultTemplateBuilder { + + private final ConfigTokenProvider configTokenProvider; + + private final List authProviders; + + private final ApplicationContext applicationContext; + + public SpringVaultTemplateBuilder(ConfigTokenProvider configTokenProvider, + List authProviders, ApplicationContext applicationContext) { + + this.configTokenProvider = configTokenProvider; + this.authProviders = authProviders; + this.applicationContext = applicationContext; + } + + public VaultTemplate build(VaultEnvironmentProperties vaultProperties) { + SpringVaultClientConfiguration clientConfiguration = new SpringVaultClientConfiguration(vaultProperties, + configTokenProvider, authProviders); + clientConfiguration.setApplicationContext(applicationContext); + return clientConfiguration.vaultTemplate(); + } + +} diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactoryTests.java index 17c2d1de..fe50111c 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactoryTests.java @@ -30,6 +30,8 @@ import org.springframework.vault.core.VaultTemplate; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; /** @@ -37,39 +39,73 @@ import static org.mockito.Mockito.when; */ public class SpringVaultEnvironmentRepositoryFactoryTests { + private final SpringVaultClientConfiguration clientConfiguration = mock(SpringVaultClientConfiguration.class); + + private final SpringVaultTemplateBuilder vaultTemplateBuilder = mock(SpringVaultTemplateBuilder.class); + + private final VaultTemplate vaultTemplate = new VaultTemplate(VaultEndpoint.create("localhost", 8200), + new TokenAuthentication("token")); + @Test public void buildForVersion1() { VaultEnvironmentProperties properties = new VaultEnvironmentProperties(); + when(clientConfiguration.vaultTemplate()).thenReturn(vaultTemplate); SpringVaultEnvironmentRepository environmentRepository = new SpringVaultEnvironmentRepositoryFactory( - mockHttpRequest(), new EnvironmentWatch.Default(), mockClientConfiguration()) + mockHttpRequest(), new EnvironmentWatch.Default(), clientConfiguration) .build(properties); VaultKeyValueOperations keyValueTemplate = environmentRepository.getKeyValueTemplate(); assertThat(keyValueTemplate.getApiVersion()).isEqualTo(VaultKeyValueOperationsSupport.KeyValueBackend.KV_1); + verify(clientConfiguration).vaultTemplate(); + verifyNoMoreInteractions(clientConfiguration, vaultTemplateBuilder); + } + + @Test + public void buildForVersion1WithVaultTemplateBuilder() { + VaultEnvironmentProperties properties = new VaultEnvironmentProperties(); + when(vaultTemplateBuilder.build(properties)).thenReturn(vaultTemplate); + + SpringVaultEnvironmentRepository environmentRepository = new SpringVaultEnvironmentRepositoryFactory( + mockHttpRequest(), new EnvironmentWatch.Default(), vaultTemplateBuilder) + .build(properties); + + VaultKeyValueOperations keyValueTemplate = environmentRepository.getKeyValueTemplate(); + assertThat(keyValueTemplate.getApiVersion()).isEqualTo(VaultKeyValueOperationsSupport.KeyValueBackend.KV_1); + verify(vaultTemplateBuilder).build(properties); + verifyNoMoreInteractions(clientConfiguration, vaultTemplateBuilder); } @Test public void buildForVersion2() { VaultEnvironmentProperties properties = new VaultEnvironmentProperties(); properties.setKvVersion(2); + when(clientConfiguration.vaultTemplate()).thenReturn(vaultTemplate); SpringVaultEnvironmentRepository environmentRepository = new SpringVaultEnvironmentRepositoryFactory( - mockHttpRequest(), new EnvironmentWatch.Default(), mockClientConfiguration()) + mockHttpRequest(), new EnvironmentWatch.Default(), clientConfiguration) .build(properties); VaultKeyValueOperations keyValueTemplate = environmentRepository.getKeyValueTemplate(); assertThat(keyValueTemplate.getApiVersion()).isEqualTo(VaultKeyValueOperationsSupport.KeyValueBackend.KV_2); + verify(clientConfiguration).vaultTemplate(); + verifyNoMoreInteractions(clientConfiguration, vaultTemplateBuilder); } - private SpringVaultClientConfiguration mockClientConfiguration() { - VaultTemplate vaultTemplate = new VaultTemplate(VaultEndpoint.create("localhost", 8200), - new TokenAuthentication("token")); + @Test + public void buildForVersion2WithVaultTemplateBuilder() { + VaultEnvironmentProperties properties = new VaultEnvironmentProperties(); + properties.setKvVersion(2); + when(vaultTemplateBuilder.build(properties)).thenReturn(vaultTemplate); - SpringVaultClientConfiguration clientConfiguration = mock(SpringVaultClientConfiguration.class); - when(clientConfiguration.vaultTemplate()).thenReturn(vaultTemplate); + SpringVaultEnvironmentRepository environmentRepository = new SpringVaultEnvironmentRepositoryFactory( + mockHttpRequest(), new EnvironmentWatch.Default(), vaultTemplateBuilder) + .build(properties); - return clientConfiguration; + VaultKeyValueOperations keyValueTemplate = environmentRepository.getKeyValueTemplate(); + assertThat(keyValueTemplate.getApiVersion()).isEqualTo(VaultKeyValueOperationsSupport.KeyValueBackend.KV_2); + verify(vaultTemplateBuilder).build(properties); + verifyNoMoreInteractions(clientConfiguration, vaultTemplateBuilder); } @SuppressWarnings("unchecked")