Merge branch '2.2.x'
This commit is contained in:
@@ -525,10 +525,28 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp
|
||||
*/
|
||||
private String role = "";
|
||||
|
||||
/**
|
||||
* URI to the Azure MSI Identity Service.
|
||||
*/
|
||||
private String identityTokenService = "";
|
||||
|
||||
/**
|
||||
* URI to the Azure MSI Metadata Service.
|
||||
*/
|
||||
private String metadataService = "";
|
||||
|
||||
public String getAzurePath() {
|
||||
return this.azurePath;
|
||||
}
|
||||
|
||||
public String getIdentityTokenService() {
|
||||
return identityTokenService;
|
||||
}
|
||||
|
||||
public String getMetadataService() {
|
||||
return metadataService;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return this.role;
|
||||
}
|
||||
@@ -537,6 +555,14 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp
|
||||
this.azurePath = azurePath;
|
||||
}
|
||||
|
||||
public void setIdentityTokenService(String identityTokenService) {
|
||||
this.identityTokenService = identityTokenService;
|
||||
}
|
||||
|
||||
public void setMetadataService(String metadataService) {
|
||||
this.metadataService = metadataService;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
@@ -103,9 +103,7 @@ public class SpringVaultClientConfiguration extends AbstractVaultConfiguration
|
||||
endpointProvider, requestFactory);
|
||||
|
||||
if (vaultProperties.getNamespace() != null) {
|
||||
restTemplateBuilder.customizers(
|
||||
restTemplate -> restTemplate.getInterceptors().add(VaultClients
|
||||
.createNamespaceInterceptor(vaultProperties.getNamespace())));
|
||||
restTemplateBuilder.customizers(this::applyNamespaceInterceptor);
|
||||
}
|
||||
|
||||
return restTemplateBuilder;
|
||||
@@ -132,6 +130,19 @@ public class SpringVaultClientConfiguration extends AbstractVaultConfiguration
|
||||
return new SslConfiguration(keyStoreConfiguration, trustStoreConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a work-around for the Spring Vault issue documented in
|
||||
* https://github.com/spring-projects/spring-vault/issues/546. The method should be
|
||||
* removed when Spring Cloud Config is upgraded to the version of Spring Vault that
|
||||
* includes the fix for the issue.
|
||||
* @return the {@link RestOperations} to be used for Vault access
|
||||
*/
|
||||
@Override
|
||||
public RestOperations restOperations() {
|
||||
return restTemplateBuilder(vaultEndpointProvider(),
|
||||
clientHttpRequestFactoryWrapper().getClientHttpRequestFactory()).build();
|
||||
}
|
||||
|
||||
private SslConfiguration.KeyStoreConfiguration getKeyStoreConfiguration(
|
||||
Resource resourceProperty, String passwordProperty) {
|
||||
|
||||
@@ -147,6 +158,15 @@ public class SpringVaultClientConfiguration extends AbstractVaultConfiguration
|
||||
return SslConfiguration.KeyStoreConfiguration.of(resourceProperty);
|
||||
}
|
||||
|
||||
private RestOperations applyNamespaceInterceptor(RestTemplate restTemplate) {
|
||||
if (vaultProperties.getNamespace() != null) {
|
||||
restTemplate.getInterceptors().add(VaultClients
|
||||
.createNamespaceInterceptor(vaultProperties.getNamespace()));
|
||||
}
|
||||
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link ClientAuthentication}.
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.config.server.environment.vault.authentication;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.VaultEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.VaultEnvironmentProperties.AuthenticationMethod;
|
||||
import org.springframework.cloud.config.server.environment.vault.SpringVaultClientAuthenticationProvider;
|
||||
@@ -44,10 +46,22 @@ public class AzureMsiClientAuthenticationProvider
|
||||
AuthenticationMethod.AZURE_MSI));
|
||||
|
||||
AzureMsiAuthenticationOptions options = AzureMsiAuthenticationOptions.builder()
|
||||
.role(azureMsi.getRole()).build();
|
||||
.role(azureMsi.getRole()).path(azureMsi.getAzurePath())
|
||||
.instanceMetadataUri(getUri(azureMsi.getMetadataService(),
|
||||
AzureMsiAuthenticationOptions.DEFAULT_INSTANCE_METADATA_SERVICE_URI))
|
||||
.identityTokenServiceUri(getUri(azureMsi.getIdentityTokenService(),
|
||||
AzureMsiAuthenticationOptions.DEFAULT_IDENTITY_TOKEN_SERVICE_URI))
|
||||
.build();
|
||||
|
||||
return new AzureMsiAuthentication(options, vaultRestOperations,
|
||||
externalRestOperations);
|
||||
}
|
||||
|
||||
private URI getUri(String uriString, URI defaultUri) {
|
||||
if (uriString == null || uriString.isEmpty()) {
|
||||
return defaultUri;
|
||||
}
|
||||
return URI.create(uriString);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.context.annotation.UserConfigurations;
|
||||
@@ -45,11 +46,17 @@ import org.springframework.cloud.config.server.environment.vault.authentication.
|
||||
import org.springframework.cloud.config.server.environment.vault.authentication.PcfClientAuthenticationProvider;
|
||||
import org.springframework.cloud.config.server.environment.vault.authentication.TokenClientAuthenticationProvider;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.vault.authentication.AppRoleAuthentication;
|
||||
import org.springframework.vault.authentication.AwsEc2Authentication;
|
||||
import org.springframework.vault.authentication.AwsIamAuthentication;
|
||||
import org.springframework.vault.authentication.AzureMsiAuthentication;
|
||||
import org.springframework.vault.authentication.AzureMsiAuthenticationOptions;
|
||||
import org.springframework.vault.authentication.ClientAuthentication;
|
||||
import org.springframework.vault.authentication.ClientCertificateAuthentication;
|
||||
import org.springframework.vault.authentication.CubbyholeAuthentication;
|
||||
@@ -58,8 +65,11 @@ import org.springframework.vault.authentication.GcpIamAuthentication;
|
||||
import org.springframework.vault.authentication.KubernetesAuthentication;
|
||||
import org.springframework.vault.authentication.PcfAuthentication;
|
||||
import org.springframework.vault.authentication.TokenAuthentication;
|
||||
import org.springframework.vault.client.VaultHttpHeaders;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.vault.support.SslConfiguration.KeyStoreConfiguration;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.cloud.config.server.environment.VaultEnvironmentProperties.AuthenticationMethod.APPROLE;
|
||||
@@ -73,6 +83,8 @@ import static org.springframework.cloud.config.server.environment.VaultEnvironme
|
||||
import static org.springframework.cloud.config.server.environment.VaultEnvironmentProperties.AuthenticationMethod.KUBERNETES;
|
||||
import static org.springframework.cloud.config.server.environment.VaultEnvironmentProperties.AuthenticationMethod.PCF;
|
||||
import static org.springframework.cloud.config.server.environment.VaultEnvironmentProperties.AuthenticationMethod.TOKEN;
|
||||
import static org.springframework.vault.authentication.AzureMsiAuthenticationOptions.DEFAULT_IDENTITY_TOKEN_SERVICE_URI;
|
||||
import static org.springframework.vault.authentication.AzureMsiAuthenticationOptions.DEFAULT_INSTANCE_METADATA_SERVICE_URI;
|
||||
|
||||
class SpringVaultClientConfigurationTests {
|
||||
|
||||
@@ -137,6 +149,16 @@ class SpringVaultClientConfigurationTests {
|
||||
properties.getAzureMsi().setAzurePath("azure-msi");
|
||||
|
||||
assertClientAuthenticationOfType(properties, AzureMsiAuthentication.class);
|
||||
|
||||
AzureMsiAuthentication clientAuthentication = (AzureMsiAuthentication) getConfiguration(
|
||||
properties).clientAuthentication();
|
||||
AzureMsiAuthenticationOptions options = (AzureMsiAuthenticationOptions) ReflectionTestUtils
|
||||
.getField(clientAuthentication, "options");
|
||||
|
||||
assertThat(options.getIdentityTokenServiceUri())
|
||||
.isEqualTo(DEFAULT_IDENTITY_TOKEN_SERVICE_URI);
|
||||
assertThat(options.getInstanceMetadataServiceUri())
|
||||
.isEqualTo(DEFAULT_INSTANCE_METADATA_SERVICE_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -280,6 +302,42 @@ class SpringVaultClientConfigurationTests {
|
||||
.isEqualTo("password");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void namespaceHeaderNotAddedWhenNamespaceNotConfigured() throws IOException {
|
||||
VaultEnvironmentProperties properties = new VaultEnvironmentProperties();
|
||||
|
||||
SpringVaultClientConfiguration configuration = getConfiguration(properties);
|
||||
HttpRequest request = invokeInterceptors(configuration.restOperations());
|
||||
assertThat(request.getHeaders().getFirst(VaultHttpHeaders.VAULT_NAMESPACE))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void namespaceInterceptorAddedWhenNamespaceConfigured() throws IOException {
|
||||
VaultEnvironmentProperties properties = new VaultEnvironmentProperties();
|
||||
properties.setNamespace("test-namespace");
|
||||
|
||||
SpringVaultClientConfiguration configuration = getConfiguration(properties);
|
||||
HttpRequest request = invokeInterceptors(configuration.restOperations());
|
||||
assertThat(request.getHeaders().getFirst(VaultHttpHeaders.VAULT_NAMESPACE))
|
||||
.isEqualTo("test-namespace");
|
||||
}
|
||||
|
||||
private HttpRequest invokeInterceptors(RestOperations restOperations)
|
||||
throws IOException {
|
||||
assertThat(restOperations).isInstanceOf(RestTemplate.class);
|
||||
RestTemplate restTemplate = (RestTemplate) restOperations;
|
||||
|
||||
MockClientHttpRequest request = new MockClientHttpRequest();
|
||||
ClientHttpRequestExecution execution = Mockito
|
||||
.mock(ClientHttpRequestExecution.class);
|
||||
byte[] body = new byte[] {};
|
||||
for (ClientHttpRequestInterceptor interceptor : restTemplate.getInterceptors()) {
|
||||
interceptor.intercept(request, body, execution);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private void assertClientAuthenticationOfType(VaultEnvironmentProperties properties,
|
||||
Class<? extends ClientAuthentication> type) {
|
||||
ClientAuthentication clientAuthentication = getConfiguration(properties)
|
||||
|
||||
Reference in New Issue
Block a user