Polishing.
Rename SecureBackend to SecretBackend. Refactor SecureBackendAccessor to SecretBackendMetadata. Move Property Transformation into PropertyTransformer. Enhance JavaDoc. Remove Properties beans and use EnableProperties annotation.
This commit is contained in:
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.aws;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -28,7 +28,7 @@ import lombok.Data;
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault.aws")
|
||||
@Data
|
||||
public class VaultAwsProperties implements VaultSecretBackend {
|
||||
public class VaultAwsProperties implements VaultSecretBackendDescriptor {
|
||||
|
||||
/**
|
||||
* Enable aws backend usage.
|
||||
|
||||
@@ -19,65 +19,73 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessorFactory;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.PropertyNameTransformer;
|
||||
import org.springframework.cloud.vault.config.PropertyTransformer;
|
||||
import org.springframework.cloud.vault.config.SecretBackendMetadata;
|
||||
import org.springframework.cloud.vault.config.SecretBackendMetadataFactory;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Bootstrap configuration providing support for the AWS secret backend.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@EnableConfigurationProperties(VaultAwsProperties.class)
|
||||
public class VaultConfigAwsBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecureBackendAccessorFactory<VaultAwsProperties> secureBackendAccessorFactory() {
|
||||
return new AwsSecureBackendAccessorFactory();
|
||||
public SecretBackendMetadataFactory<VaultAwsProperties> secretBackendMetadataFactory() {
|
||||
return new AwsSecretBackendMetadataFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultAwsProperties awsProperties() {
|
||||
return new VaultAwsProperties();
|
||||
}
|
||||
|
||||
static class AwsSecureBackendAccessorFactory
|
||||
implements SecureBackendAccessorFactory<VaultAwsProperties> {
|
||||
static class AwsSecretBackendMetadataFactory
|
||||
implements SecretBackendMetadataFactory<VaultAwsProperties> {
|
||||
|
||||
@Override
|
||||
public SecureBackendAccessor createSecureBackendAccessor(
|
||||
VaultAwsProperties properties) {
|
||||
return forAws(properties);
|
||||
public SecretBackendMetadata createMetadata(
|
||||
VaultAwsProperties backendDescriptor) {
|
||||
return forAws(backendDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(VaultSecretBackend secretBackend) {
|
||||
return secretBackend instanceof VaultAwsProperties;
|
||||
public boolean supports(VaultSecretBackendDescriptor backendDescriptor) {
|
||||
return backendDescriptor instanceof VaultAwsProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure backend using
|
||||
* Creates {@link SecretBackendMetadata} for a secret backend using
|
||||
* {@link VaultAwsProperties}. This accessor transforms Vault's username/password
|
||||
* property names to names provided with
|
||||
* {@link VaultAwsProperties#getAccessKeyProperty()} and
|
||||
* {@link VaultAwsProperties#getSecretKeyProperty()}.
|
||||
*
|
||||
* @param properties must not be {@literal null}.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
* @return the {@link SecretBackendMetadata}
|
||||
*/
|
||||
public static SecureBackendAccessor forAws(final VaultAwsProperties properties) {
|
||||
public static SecretBackendMetadata forAws(final VaultAwsProperties properties) {
|
||||
|
||||
Assert.notNull(properties, "VaultAwsProperties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
final PropertyNameTransformer transformer = new PropertyNameTransformer();
|
||||
transformer.addKeyTransformation("access_key",
|
||||
properties.getAccessKeyProperty());
|
||||
transformer.addKeyTransformation("secret_key",
|
||||
properties.getSecretKeyProperty());
|
||||
|
||||
return new SecretBackendMetadata() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
public Map<String, String> getVariables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
|
||||
variables.put("backend", properties.getBackend());
|
||||
variables.put("key", String.format("creds/%s", properties.getRole()));
|
||||
|
||||
return variables;
|
||||
}
|
||||
|
||||
@@ -88,16 +96,8 @@ public class VaultConfigAwsBootstrapConfiguration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> transformProperties(
|
||||
Map<String, String> input) {
|
||||
|
||||
Map<String, String> result = new HashMap();
|
||||
result.put(properties.getAccessKeyProperty(),
|
||||
input.get("access_key"));
|
||||
result.put(properties.getSecretKeyProperty(),
|
||||
input.get("secret_key"));
|
||||
|
||||
return result;
|
||||
public PropertyTransformer getPropertyTransformer() {
|
||||
return transformer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.aws;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.springframework.cloud.vault.config.aws.VaultConfigAwsBootstrapConfiguration.AwsSecureBackendAccessorFactory.*;
|
||||
import static org.springframework.cloud.vault.config.aws.VaultConfigAwsBootstrapConfiguration.AwsSecretBackendMetadataFactory.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -19,65 +19,69 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessorFactory;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.PropertyNameTransformer;
|
||||
import org.springframework.cloud.vault.config.PropertyTransformer;
|
||||
import org.springframework.cloud.vault.config.SecretBackendMetadata;
|
||||
import org.springframework.cloud.vault.config.SecretBackendMetadataFactory;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Bootstrap configuration providing support for the Consul secret backend.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@EnableConfigurationProperties(VaultConsulProperties.class)
|
||||
public class VaultConfigConsulBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecureBackendAccessorFactory<VaultConsulProperties> secureBackendAccessorFactory() {
|
||||
return new ConsulSecureBackendAccessorFactory();
|
||||
public SecretBackendMetadataFactory<VaultConsulProperties> secretBackendAccessorFactory() {
|
||||
return new ConsulSecretBackendMetadataFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultConsulProperties vaultConsulProperties() {
|
||||
return new VaultConsulProperties();
|
||||
}
|
||||
|
||||
static class ConsulSecureBackendAccessorFactory
|
||||
implements SecureBackendAccessorFactory<VaultConsulProperties> {
|
||||
static class ConsulSecretBackendMetadataFactory
|
||||
implements SecretBackendMetadataFactory<VaultConsulProperties> {
|
||||
|
||||
@Override
|
||||
public SecureBackendAccessor createSecureBackendAccessor(
|
||||
VaultConsulProperties properties) {
|
||||
return forConsul(properties);
|
||||
public SecretBackendMetadata createMetadata(
|
||||
VaultConsulProperties backendDescriptor) {
|
||||
return forConsul(backendDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(VaultSecretBackend secretBackend) {
|
||||
return secretBackend instanceof VaultConsulProperties;
|
||||
public boolean supports(VaultSecretBackendDescriptor backendDescriptor) {
|
||||
return backendDescriptor instanceof VaultConsulProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure backend using
|
||||
* Creates a {@link SecretBackendMetadata} for a secret backend using
|
||||
* {@link VaultConsulProperties}. This accessor transforms Vault's token property
|
||||
* names to names provided with {@link VaultConsulProperties#getTokenProperty()}.
|
||||
*
|
||||
* @param properties must not be {@literal null}.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
* @return the {@link SecretBackendMetadata}
|
||||
*/
|
||||
public static SecureBackendAccessor forConsul(
|
||||
public static SecretBackendMetadata forConsul(
|
||||
final VaultConsulProperties properties) {
|
||||
|
||||
Assert.notNull(properties, "VaultConsulProperties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
final PropertyNameTransformer transformer = new PropertyNameTransformer();
|
||||
transformer.addKeyTransformation("token", properties.getTokenProperty());
|
||||
|
||||
return new SecretBackendMetadata() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
public Map<String, String> getVariables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
|
||||
variables.put("backend", properties.getBackend());
|
||||
variables.put("key", String.format("creds/%s", properties.getRole()));
|
||||
|
||||
return variables;
|
||||
}
|
||||
|
||||
@@ -88,13 +92,8 @@ public class VaultConfigConsulBootstrapConfiguration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> transformProperties(
|
||||
Map<String, String> input) {
|
||||
|
||||
Map<String, String> result = new HashMap();
|
||||
result.put(properties.getTokenProperty(), input.get("token"));
|
||||
|
||||
return result;
|
||||
public PropertyTransformer getPropertyTransformer() {
|
||||
return transformer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.consul;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -28,7 +28,7 @@ import lombok.Data;
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault.consul")
|
||||
@Data
|
||||
public class VaultConsulProperties implements VaultSecretBackend {
|
||||
public class VaultConsulProperties implements VaultSecretBackendDescriptor {
|
||||
|
||||
/**
|
||||
* Enable consul backend usage.
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.consul;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.springframework.cloud.vault.config.consul.VaultConfigConsulBootstrapConfiguration.ConsulSecureBackendAccessorFactory.*;
|
||||
import static org.springframework.cloud.vault.config.consul.VaultConfigConsulBootstrapConfiguration.ConsulSecretBackendMetadataFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
@@ -26,7 +26,7 @@ import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.test.TestRestTemplate;
|
||||
|
||||
import org.springframework.cloud.vault.config.VaultConfigOperations;
|
||||
import org.springframework.cloud.vault.config.VaultConfigTemplate;
|
||||
import org.springframework.cloud.vault.config.VaultProperties;
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
*/
|
||||
package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
|
||||
/**
|
||||
* Configuration properties interface for database secrets.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface DatabaseSecretProperties extends VaultSecretBackend {
|
||||
public interface DatabaseSecretProperties extends VaultSecretBackendDescriptor {
|
||||
|
||||
/**
|
||||
* Role name.
|
||||
|
||||
@@ -19,14 +19,19 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessorFactory;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.PropertyNameTransformer;
|
||||
import org.springframework.cloud.vault.config.PropertyTransformer;
|
||||
import org.springframework.cloud.vault.config.SecretBackendMetadata;
|
||||
import org.springframework.cloud.vault.config.SecretBackendMetadataFactory;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Bootstrap configuration providing support for the Database secret backends such as
|
||||
* MySQL, PostreSQL, Apache Cassandra and MongoDB.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@@ -36,42 +41,49 @@ import org.springframework.util.Assert;
|
||||
public class VaultConfigDatabaseBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecureBackendAccessorFactory<DatabaseSecretProperties> secureBackendAccessorFactory() {
|
||||
return new DatabaseSecureBackendAccessorFactory();
|
||||
public SecretBackendMetadataFactory<DatabaseSecretProperties> secretBackendMetadataFactory() {
|
||||
return new DatabaseSecretBackendMetadataFactory();
|
||||
}
|
||||
|
||||
static class DatabaseSecureBackendAccessorFactory
|
||||
implements SecureBackendAccessorFactory<DatabaseSecretProperties> {
|
||||
static class DatabaseSecretBackendMetadataFactory
|
||||
implements SecretBackendMetadataFactory<DatabaseSecretProperties> {
|
||||
|
||||
@Override
|
||||
public SecureBackendAccessor createSecureBackendAccessor(
|
||||
DatabaseSecretProperties configurationProperties) {
|
||||
return forDatabase(configurationProperties);
|
||||
public SecretBackendMetadata createMetadata(
|
||||
DatabaseSecretProperties backendDescriptor) {
|
||||
return forDatabase(backendDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(VaultSecretBackend secretBackend) {
|
||||
return secretBackend instanceof DatabaseSecretProperties;
|
||||
public boolean supports(VaultSecretBackendDescriptor backendDescriptor) {
|
||||
return backendDescriptor instanceof DatabaseSecretProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure backend using
|
||||
* Creates a {@link SecretBackendMetadata} for a secret backend using
|
||||
* {@link DatabaseSecretProperties}. This accessor transforms Vault's
|
||||
* username/password property names to names provided with
|
||||
* {@link DatabaseSecretProperties#getUsernameProperty()} and
|
||||
* {@link DatabaseSecretProperties#getPasswordProperty()}.
|
||||
*
|
||||
* @param properties must not be {@literal null}.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
* @return the {@link SecretBackendMetadata}
|
||||
*/
|
||||
public static SecureBackendAccessor forDatabase(
|
||||
public static SecretBackendMetadata forDatabase(
|
||||
final DatabaseSecretProperties properties) {
|
||||
|
||||
Assert.notNull(properties, "DatabaseSecretProperties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
final PropertyNameTransformer transformer = new PropertyNameTransformer();
|
||||
transformer.addKeyTransformation("username",
|
||||
properties.getUsernameProperty());
|
||||
transformer.addKeyTransformation("password",
|
||||
properties.getPasswordProperty());
|
||||
|
||||
return new SecretBackendMetadata() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
public Map<String, String> getVariables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
variables.put("backend", properties.getBackend());
|
||||
@@ -86,14 +98,8 @@ public class VaultConfigDatabaseBootstrapConfiguration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> transformProperties(
|
||||
Map<String, String> input) {
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put(properties.getUsernameProperty(), input.get("username"));
|
||||
result.put(properties.getPasswordProperty(), input.get("password"));
|
||||
|
||||
return result;
|
||||
public PropertyTransformer getPropertyTransformer() {
|
||||
return transformer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -14,7 +14,7 @@ import lombok.Data;
|
||||
@ConfigurationProperties("spring.cloud.vault.mysql")
|
||||
@Data
|
||||
public class VaultMySqlProperties
|
||||
implements DatabaseSecretProperties, VaultSecretBackend {
|
||||
implements DatabaseSecretProperties, VaultSecretBackendDescriptor {
|
||||
|
||||
/**
|
||||
* Enable mysql backend usage.
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecureBackendAccessorFactory.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecretBackendMetadataFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecureBackendAccessorFactory.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecretBackendMetadataFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecureBackendAccessorFactory.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecretBackendMetadataFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecureBackendAccessorFactory.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecretBackendMetadataFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -19,14 +19,18 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessorFactory;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.PropertyNameTransformer;
|
||||
import org.springframework.cloud.vault.config.PropertyTransformer;
|
||||
import org.springframework.cloud.vault.config.SecretBackendMetadata;
|
||||
import org.springframework.cloud.vault.config.SecretBackendMetadataFactory;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Bootstrap configuration providing support for the RabbitMQ secret backend.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@@ -34,8 +38,8 @@ import org.springframework.util.Assert;
|
||||
public class VaultConfigRabbitMqBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecureBackendAccessorFactory<VaultRabbitMqProperties> secureBackendAccessorFactory() {
|
||||
return new RabbitMqSecureBackendAccessorFactory();
|
||||
public SecretBackendMetadataFactory<VaultRabbitMqProperties> secureBackendAccessorFactory() {
|
||||
return new RabbitMqSecretBackendMetadataFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -43,42 +47,51 @@ public class VaultConfigRabbitMqBootstrapConfiguration {
|
||||
return new VaultRabbitMqProperties();
|
||||
}
|
||||
|
||||
static class RabbitMqSecureBackendAccessorFactory
|
||||
implements SecureBackendAccessorFactory<VaultRabbitMqProperties> {
|
||||
static class RabbitMqSecretBackendMetadataFactory
|
||||
implements SecretBackendMetadataFactory<VaultRabbitMqProperties> {
|
||||
|
||||
@Override
|
||||
public SecureBackendAccessor createSecureBackendAccessor(
|
||||
VaultRabbitMqProperties properties) {
|
||||
return forRabbitMq(properties);
|
||||
public SecretBackendMetadata createMetadata(
|
||||
VaultRabbitMqProperties backendDescriptor) {
|
||||
return forRabbitMq(backendDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(VaultSecretBackend secretBackend) {
|
||||
return secretBackend instanceof VaultRabbitMqProperties;
|
||||
public boolean supports(VaultSecretBackendDescriptor backendDescriptor) {
|
||||
return backendDescriptor instanceof VaultRabbitMqProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure backend using
|
||||
* Creates a {@link SecretBackendMetadata} for a secret backend using
|
||||
* {@link VaultRabbitMqProperties}. This accessor transforms Vault's
|
||||
* username/password property names to names provided with
|
||||
* {@link VaultRabbitMqProperties#getUsernameProperty()} and
|
||||
* {@link VaultRabbitMqProperties#getPasswordProperty()}.
|
||||
*
|
||||
* @param properties must not be {@literal null}.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
* @return the {@link SecretBackendMetadata}
|
||||
*/
|
||||
public static SecureBackendAccessor forRabbitMq(
|
||||
public static SecretBackendMetadata forRabbitMq(
|
||||
final VaultRabbitMqProperties properties) {
|
||||
Assert.notNull(properties, "DatabaseSecretProperties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
Assert.notNull(properties, "VaultRabbitMqProperties must not be null");
|
||||
|
||||
final PropertyNameTransformer transformer = new PropertyNameTransformer();
|
||||
transformer.addKeyTransformation("username",
|
||||
properties.getUsernameProperty());
|
||||
transformer.addKeyTransformation("password",
|
||||
properties.getPasswordProperty());
|
||||
|
||||
return new SecretBackendMetadata() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
public Map<String, String> getVariables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
|
||||
variables.put("backend", properties.getBackend());
|
||||
variables.put("key", String.format("creds/%s", properties.getRole()));
|
||||
|
||||
return variables;
|
||||
}
|
||||
|
||||
@@ -89,14 +102,8 @@ public class VaultConfigRabbitMqBootstrapConfiguration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> transformProperties(
|
||||
Map<String, String> input) {
|
||||
|
||||
Map<String, String> result = new HashMap();
|
||||
result.put(properties.getUsernameProperty(), input.get("username"));
|
||||
result.put(properties.getPasswordProperty(), input.get("password"));
|
||||
|
||||
return result;
|
||||
public PropertyTransformer getPropertyTransformer() {
|
||||
return transformer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.rabbitmq;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackend;
|
||||
import org.springframework.cloud.vault.config.VaultSecretBackendDescriptor;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -28,7 +28,7 @@ import lombok.Data;
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault.rabbitmq")
|
||||
@Data
|
||||
public class VaultRabbitMqProperties implements VaultSecretBackend {
|
||||
public class VaultRabbitMqProperties implements VaultSecretBackendDescriptor {
|
||||
|
||||
/**
|
||||
* Enable rabbitmq backend usage.
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.vault.config.rabbitmq;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.springframework.cloud.vault.config.rabbitmq.VaultConfigRabbitMqBootstrapConfiguration.RabbitMqSecureBackendAccessorFactory.*;
|
||||
import static org.springframework.cloud.vault.config.rabbitmq.VaultConfigRabbitMqBootstrapConfiguration.RabbitMqSecretBackendMetadataFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.vault.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link SecretBackendMetadata} for the {@code generic} secret backend.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class GenericSecretBackendMetadata implements SecretBackendMetadata {
|
||||
|
||||
private final String secretBackendPath;
|
||||
|
||||
private final String key;
|
||||
|
||||
private GenericSecretBackendMetadata(String secretBackendPath, String key) {
|
||||
|
||||
Assert.hasText(secretBackendPath, "Secret backend path must not be empty");
|
||||
Assert.hasText(key, "Key must not be empty");
|
||||
|
||||
this.key = key;
|
||||
this.secretBackendPath = secretBackendPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link SecretBackendMetadata} for the {@code generic} secret backend given
|
||||
* a {@code secretBackendPath} and {@code key}.
|
||||
*
|
||||
* @param secretBackendPath the secret backend mount path without leading/trailing
|
||||
* slashes, must not be empty or {@literal null}.
|
||||
* @param key the key within the secret backend. May contain slashes but not
|
||||
* leading/trailing slashes, must not be empty or {@literal null}.
|
||||
* @return the {@link SecretBackendMetadata}
|
||||
*/
|
||||
public static SecretBackendMetadata create(final String secretBackendPath,
|
||||
final String key) {
|
||||
return new GenericSecretBackendMetadata(secretBackendPath, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return String.format("%s/%s", secretBackendPath, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyTransformer getPropertyTransformer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getVariables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
|
||||
variables.put("backend", secretBackendPath);
|
||||
variables.put("key", key);
|
||||
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
@@ -66,15 +66,15 @@ class LeasingVaultPropertySource extends VaultPropertySource implements Disposab
|
||||
* Creates a new {@link VaultPropertySource}.
|
||||
*
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param properties must not be {@literal null}.
|
||||
* @param secureBackendAccessor must not be {@literal null}.
|
||||
* @param failFast fail if properties could not be read because of access errors.
|
||||
* @param secretBackendMetadata must not be {@literal null}.
|
||||
* @param taskScheduler must not be {@literal null}.
|
||||
*/
|
||||
public LeasingVaultPropertySource(VaultConfigTemplate operations,
|
||||
VaultProperties properties, SecureBackendAccessor secureBackendAccessor,
|
||||
public LeasingVaultPropertySource(VaultConfigOperations operations, boolean failFast,
|
||||
SecretBackendMetadata secretBackendMetadata,
|
||||
TaskScheduler taskScheduler) {
|
||||
|
||||
super(operations, properties, secureBackendAccessor);
|
||||
super(operations, failFast, secretBackendMetadata);
|
||||
|
||||
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
class LeasingVaultPropertySourceLocator extends VaultPropertySourceLocator
|
||||
implements DisposableBean {
|
||||
|
||||
private final VaultConfigTemplate operations;
|
||||
private final VaultConfigOperations operations;
|
||||
|
||||
private final VaultProperties properties;
|
||||
|
||||
@@ -53,10 +53,10 @@ class LeasingVaultPropertySourceLocator extends VaultPropertySourceLocator
|
||||
* @param backendAccessors must not be {@literal null}.
|
||||
* @param taskScheduler must not be {@literal null}.
|
||||
*/
|
||||
public LeasingVaultPropertySourceLocator(VaultConfigTemplate operations,
|
||||
public LeasingVaultPropertySourceLocator(VaultConfigOperations operations,
|
||||
VaultProperties properties,
|
||||
VaultGenericBackendProperties genericBackendProperties,
|
||||
Collection<SecureBackendAccessor> backendAccessors,
|
||||
Collection<SecretBackendMetadata> backendAccessors,
|
||||
TaskScheduler taskScheduler) {
|
||||
|
||||
super(operations, properties, genericBackendProperties, backendAccessors);
|
||||
@@ -72,9 +72,10 @@ class LeasingVaultPropertySourceLocator extends VaultPropertySourceLocator
|
||||
|
||||
@Override
|
||||
protected VaultPropertySource createVaultPropertySource(
|
||||
SecureBackendAccessor accessor) {
|
||||
SecretBackendMetadata accessor) {
|
||||
|
||||
LeasingVaultPropertySource propertySource = new LeasingVaultPropertySource(
|
||||
this.operations, this.properties, accessor, taskScheduler);
|
||||
this.operations, this.properties.isFailFast(), accessor, taskScheduler);
|
||||
|
||||
locatedPropertySources.add(propertySource);
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.vault.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link PropertyTransformer} to transform a {@link Map} of properties by applying key
|
||||
* name translation.
|
||||
* <p>
|
||||
* Existing keys will be transformed to a target key name while retaining the original
|
||||
* value. Key name translation will leave other, not specified key names untouched.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class PropertyNameTransformer implements PropertyTransformer {
|
||||
|
||||
private final Map<String, String> nameMapping = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new {@link PropertyNameTransformer}.
|
||||
*/
|
||||
public PropertyNameTransformer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a key name transformation by providing a {@code sourceKeyName} and a
|
||||
* {@code targetKeyName}.
|
||||
*
|
||||
* @param sourceKeyName must not be empty or {@literal null}.
|
||||
* @param targetKeyName must not be empty or {@literal null}.
|
||||
*/
|
||||
public void addKeyTransformation(String sourceKeyName, String targetKeyName) {
|
||||
|
||||
Assert.hasText(sourceKeyName, "Source key name must not be empty");
|
||||
Assert.hasText(targetKeyName, "Target key name must not be empty");
|
||||
|
||||
nameMapping.put(sourceKeyName, targetKeyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> transformProperties(Map<String, String> input) {
|
||||
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, String> transformed = new LinkedHashMap<>(input.size(), 1);
|
||||
|
||||
for (String key : input.keySet()) {
|
||||
|
||||
String value = input.get(key);
|
||||
String translatedKey = key;
|
||||
|
||||
if (nameMapping.containsKey(key)) {
|
||||
translatedKey = nameMapping.get(key);
|
||||
}
|
||||
|
||||
transformed.put(translatedKey, value);
|
||||
}
|
||||
|
||||
return transformed;
|
||||
}
|
||||
}
|
||||
@@ -13,34 +13,27 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Accessor for a secure backend. Provides URL path variables and can transform
|
||||
* properties.
|
||||
* Strategy interface to transform properties to a new key-value {@link Map}. Property
|
||||
* transformation can remap property names, adjust values or change the property map
|
||||
* entirely.
|
||||
* <p>
|
||||
* Implementors usually transform property names to target property names by retaining the
|
||||
* value.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface SecureBackendAccessor {
|
||||
public interface PropertyTransformer {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return URL template variables.
|
||||
*/
|
||||
Map<String, String> variables();
|
||||
|
||||
/**
|
||||
*
|
||||
* Transform properties by creating a new map using the transformed property set.
|
||||
*
|
||||
* @param input must not be {@literal null}.
|
||||
* @return transformed properties.
|
||||
*/
|
||||
Map<String, String> transformProperties(Map<String, String> input);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the name for this accessor.
|
||||
*/
|
||||
String getName();
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.vault.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Utility class to create {@link SecretBackendMetadata} from a
|
||||
* {@link SecretBackendMetadataFactory}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
class SecretBackendFactories {
|
||||
|
||||
public static Collection<SecretBackendMetadata> createSecretBackendMetadata(
|
||||
Collection<VaultSecretBackendDescriptor> vaultSecretBackendDescriptors,
|
||||
Collection<SecretBackendMetadataFactory<? super VaultSecretBackendDescriptor>> factories) {
|
||||
|
||||
List<SecretBackendMetadata> accessors = new ArrayList<>();
|
||||
|
||||
for (VaultSecretBackendDescriptor vaultSecretBackendDescriptor : vaultSecretBackendDescriptors) {
|
||||
|
||||
if (!vaultSecretBackendDescriptor.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SecretBackendMetadata metadata = createSecretBackendMetadata(factories,
|
||||
vaultSecretBackendDescriptor);
|
||||
|
||||
if (metadata == null) {
|
||||
log.warn(String.format("Cannot create SecretBackendMetadata for %s",
|
||||
vaultSecretBackendDescriptor));
|
||||
continue;
|
||||
}
|
||||
|
||||
accessors.add(metadata);
|
||||
}
|
||||
|
||||
return accessors;
|
||||
}
|
||||
|
||||
private static SecretBackendMetadata createSecretBackendMetadata(
|
||||
Collection<SecretBackendMetadataFactory<? super VaultSecretBackendDescriptor>> factories,
|
||||
VaultSecretBackendDescriptor vaultSecretBackendDescriptor) {
|
||||
|
||||
SecretBackendMetadata accessor = null;
|
||||
for (SecretBackendMetadataFactory<? super VaultSecretBackendDescriptor> factory : factories) {
|
||||
|
||||
if (factory.supports(vaultSecretBackendDescriptor)) {
|
||||
accessor = factory.createMetadata(vaultSecretBackendDescriptor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return accessor;
|
||||
}
|
||||
}
|
||||
@@ -13,28 +13,38 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Factory to convert {@link VaultSecretBackend} instance to a
|
||||
* {@link SecureBackendAccessor}.
|
||||
* Interface specifying the API to obtain URL variables and optionally a
|
||||
* {@link PropertyTransformer}. Typically used by {@link VaultPropertySource}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see PropertyTransformer
|
||||
*/
|
||||
public interface SecureBackendAccessorFactory<T extends VaultSecretBackend> {
|
||||
public interface SecretBackendMetadata {
|
||||
|
||||
/**
|
||||
* Converts a {@link VaultSecretBackend} into a {@link SecureBackendAccessor}.
|
||||
* @param configurationProperties
|
||||
* @return the {@link SecureBackendAccessor}.
|
||||
* Return a readable name of this secret backend.
|
||||
*
|
||||
* @return the name of this secret backend.
|
||||
*/
|
||||
SecureBackendAccessor createSecureBackendAccessor(T configurationProperties);
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Checks whether the {@link VaultSecretBackend} is supported by this
|
||||
* {@link SecureBackendAccessorFactory}.
|
||||
* @param secretBackend must not be {@literal null}.
|
||||
* @return {@literal true} if the given {@link VaultSecretBackend} is supported
|
||||
* Return a {@link PropertyTransformer} to post-process properties retrieved from
|
||||
* Vault.
|
||||
*
|
||||
* @return the property transformer or {@literal null} if there's no property
|
||||
* transformer.
|
||||
*/
|
||||
boolean supports(VaultSecretBackend secretBackend);
|
||||
PropertyTransformer getPropertyTransformer();
|
||||
|
||||
/**
|
||||
* @return URL template variables.
|
||||
*/
|
||||
Map<String, String> getVariables();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.vault.config;
|
||||
|
||||
/**
|
||||
* Strategy interface to create {@link SecretBackendMetadata} from
|
||||
* {@link VaultSecretBackendDescriptor} properties.
|
||||
*
|
||||
* <p>
|
||||
* Classes implementing this interface must implement
|
||||
* {@link #supports(VaultSecretBackendDescriptor)} to determine whether a particular
|
||||
* {@link VaultSecretBackendDescriptor} is supported by this implementation. If a
|
||||
* {@link VaultSecretBackendDescriptor} instance is supported by the implementation, it
|
||||
* must be able to create {@link SecretBackendMetadata}, see
|
||||
* {@link #createMetadata(VaultSecretBackendDescriptor)}.
|
||||
*
|
||||
* <p>
|
||||
* Typically implemented by secret backend providers that implement access to a particular
|
||||
* backend using read operations.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see SecretBackendMetadata
|
||||
* @see VaultSecretBackendDescriptor
|
||||
*/
|
||||
public interface SecretBackendMetadataFactory<T extends VaultSecretBackendDescriptor> {
|
||||
|
||||
/**
|
||||
* Converts a {@link VaultSecretBackendDescriptor} into a
|
||||
* {@link SecretBackendMetadata}.
|
||||
*
|
||||
* @param backendDescriptor must not be {@literal null}.
|
||||
* @return the {@link SecretBackendMetadata}.
|
||||
*/
|
||||
SecretBackendMetadata createMetadata(T backendDescriptor);
|
||||
|
||||
/**
|
||||
* Checks whether the {@link VaultSecretBackendDescriptor} is supported by this
|
||||
* {@link SecretBackendMetadataFactory}.
|
||||
*
|
||||
* @param backendDescriptor must not be {@literal null}.
|
||||
* @return {@literal true} if the given {@link VaultSecretBackendDescriptor} is
|
||||
* supported.
|
||||
*/
|
||||
boolean supports(VaultSecretBackendDescriptor backendDescriptor);
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.vault.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Collection of common used {@link SecureBackendAccessor accessors} to access secure
|
||||
* backends.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class SecureBackendAccessors {
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for the {@code generic} secure backend.
|
||||
*
|
||||
* @param secretBackendPath must not be {@literal null} and not empty.
|
||||
* @param key must not be {@literal null} and not empty.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
*/
|
||||
public static SecureBackendAccessor generic(final String secretBackendPath,
|
||||
final String key) {
|
||||
|
||||
Assert.hasText(secretBackendPath, "Secret Backend Path must not be empty");
|
||||
Assert.hasText(key, "Key must not be empty");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
variables.put("backend", secretBackendPath);
|
||||
variables.put("key", key);
|
||||
return variables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return String.format("%s/%s", secretBackendPath, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> transformProperties(Map<String, String> input) {
|
||||
return input;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.vault.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Slf4j
|
||||
public class SecureBackendFactories {
|
||||
|
||||
public static Collection<SecureBackendAccessor> createBackendAcessors(
|
||||
Collection<VaultSecretBackend> vaultSecretBackends,
|
||||
Collection<SecureBackendAccessorFactory<? super VaultSecretBackend>> factories) {
|
||||
|
||||
List<SecureBackendAccessor> accessors = new ArrayList<>();
|
||||
|
||||
for (VaultSecretBackend vaultSecretBackend : vaultSecretBackends) {
|
||||
|
||||
if (!vaultSecretBackend.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SecureBackendAccessor accessor = createSecureBackendAccessor(factories,
|
||||
vaultSecretBackend);
|
||||
if (accessor == null) {
|
||||
log.warn(String.format("Cannot create SecureBackendAccessor for %s",
|
||||
vaultSecretBackend));
|
||||
continue;
|
||||
}
|
||||
|
||||
accessors.add(accessor);
|
||||
}
|
||||
|
||||
return accessors;
|
||||
}
|
||||
|
||||
private static SecureBackendAccessor createSecureBackendAccessor(
|
||||
Collection<SecureBackendAccessorFactory<? super VaultSecretBackend>> factories,
|
||||
VaultSecretBackend vaultSecretBackend) {
|
||||
SecureBackendAccessor accessor = null;
|
||||
for (SecureBackendAccessorFactory<? super VaultSecretBackend> factory : factories) {
|
||||
|
||||
if (factory.supports(vaultSecretBackend)) {
|
||||
accessor = factory.createSecureBackendAccessor(vaultSecretBackend);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return accessor;
|
||||
}
|
||||
}
|
||||
@@ -81,20 +81,21 @@ public class VaultBootstrapConfiguration {
|
||||
|
||||
private final VaultProperties vaultProperties;
|
||||
|
||||
private final Collection<VaultSecretBackend> vaultSecretBackends;
|
||||
private final Collection<VaultSecretBackendDescriptor> vaultSecretBackendDescriptors;
|
||||
|
||||
private final Collection<SecureBackendAccessorFactory<? super VaultSecretBackend>> factories;
|
||||
private final Collection<SecretBackendMetadataFactory<? super VaultSecretBackendDescriptor>> factories;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public VaultBootstrapConfiguration(ConfigurableApplicationContext applicationContext,
|
||||
VaultProperties vaultProperties) {
|
||||
|
||||
this.applicationContext = applicationContext;
|
||||
this.vaultProperties = vaultProperties;
|
||||
|
||||
this.vaultSecretBackends = applicationContext
|
||||
.getBeansOfType(VaultSecretBackend.class).values();
|
||||
this.vaultSecretBackendDescriptors = applicationContext
|
||||
.getBeansOfType(VaultSecretBackendDescriptor.class).values();
|
||||
this.factories = (Collection) applicationContext
|
||||
.getBeansOfType(SecureBackendAccessorFactory.class).values();
|
||||
.getBeansOfType(SecretBackendMetadataFactory.class).values();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -103,8 +104,8 @@ public class VaultBootstrapConfiguration {
|
||||
VaultGenericBackendProperties vaultGenericBackendProperties,
|
||||
ObjectProvider<TaskSchedulerWrapper<? extends TaskScheduler>> taskSchedulerProvider) {
|
||||
|
||||
Collection<SecureBackendAccessor> backendAccessors = SecureBackendFactories
|
||||
.createBackendAcessors(vaultSecretBackends, factories);
|
||||
Collection<SecretBackendMetadata> backendAccessors = SecretBackendFactories
|
||||
.createSecretBackendMetadata(vaultSecretBackendDescriptors, factories);
|
||||
VaultConfigTemplate vaultConfigTemplate = new VaultConfigTemplate(operations,
|
||||
vaultProperties);
|
||||
|
||||
@@ -123,114 +124,6 @@ public class VaultBootstrapConfiguration {
|
||||
vaultGenericBackendProperties, backendAccessors);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
|
||||
VaultClient vaultClient = vaultClient();
|
||||
|
||||
switch (vaultProperties.getAuthentication()) {
|
||||
|
||||
case TOKEN:
|
||||
Assert.hasText(vaultProperties.getToken(),
|
||||
"Token (spring.cloud.vault.token) must not be empty");
|
||||
return new TokenAuthentication(vaultProperties.getToken());
|
||||
|
||||
case APPID:
|
||||
return appIdAuthentication(vaultProperties, vaultClient);
|
||||
|
||||
case CERT:
|
||||
return new ClientCertificateAuthentication(vaultClient);
|
||||
|
||||
case AWS_EC2:
|
||||
return awsEc2Authentication(vaultProperties, vaultClient);
|
||||
|
||||
case CUBBYHOLE:
|
||||
return cubbyholeAuthentication(vaultClient);
|
||||
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(
|
||||
String.format("Client authentication %s not supported",
|
||||
vaultProperties.getAuthentication()));
|
||||
}
|
||||
|
||||
private ClientAuthentication appIdAuthentication(VaultProperties vaultProperties,
|
||||
VaultClient vaultClient) {
|
||||
|
||||
VaultProperties.AppIdProperties appId = vaultProperties.getAppId();
|
||||
Assert.hasText(appId.getUserId(),
|
||||
"UserId (spring.cloud.vault.app-id.user-id) must not be empty");
|
||||
|
||||
AppIdAuthenticationOptions authenticationOptions = AppIdAuthenticationOptions
|
||||
.builder().appId(vaultProperties.getApplicationName()) //
|
||||
.path(appId.getAppIdPath()) //
|
||||
.userIdMechanism(getClientAuthentication(appId)).build();
|
||||
|
||||
return new AppIdAuthentication(authenticationOptions, vaultClient);
|
||||
}
|
||||
|
||||
private AppIdUserIdMechanism getClientAuthentication(
|
||||
VaultProperties.AppIdProperties appId) {
|
||||
|
||||
try {
|
||||
Class<?> userIdClass = ClassUtils.forName(appId.getUserId(), null);
|
||||
return (AppIdUserIdMechanism) BeanUtils.instantiateClass(userIdClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
|
||||
switch (appId.getUserId().toUpperCase()) {
|
||||
|
||||
case VaultProperties.AppIdProperties.IP_ADDRESS:
|
||||
return new IpAddressUserId();
|
||||
|
||||
case VaultProperties.AppIdProperties.MAC_ADDRESS:
|
||||
|
||||
if (StringUtils.hasText(appId.getNetworkInterface())) {
|
||||
try {
|
||||
return new MacAddressUserId(
|
||||
Integer.parseInt(appId.getNetworkInterface()));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return new MacAddressUserId(appId.getNetworkInterface());
|
||||
}
|
||||
}
|
||||
|
||||
return new MacAddressUserId();
|
||||
default:
|
||||
return new StaticUserId(appId.getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClientAuthentication awsEc2Authentication(VaultProperties vaultProperties,
|
||||
VaultClient vaultClient) {
|
||||
|
||||
VaultProperties.AwsEc2Properties awsEc2 = vaultProperties.getAwsEc2();
|
||||
|
||||
AwsEc2AuthenticationOptions authenticationOptions = AwsEc2AuthenticationOptions
|
||||
.builder().role(awsEc2.getRole()) //
|
||||
.path(awsEc2.getAwsEc2Path()) //
|
||||
.identityDocumentUri(URI.create(awsEc2.getIdentityDocument())) //
|
||||
.build();
|
||||
|
||||
return new AwsEc2Authentication(authenticationOptions, vaultClient,
|
||||
vaultClient.getRestTemplate());
|
||||
}
|
||||
|
||||
private ClientAuthentication cubbyholeAuthentication(VaultClient vaultClient) {
|
||||
|
||||
Assert.hasText(vaultProperties.getToken(),
|
||||
"Initial Token (spring.cloud.vault.token) for Cubbyhole authentication must not be empty");
|
||||
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions.builder() //
|
||||
.wrapped() //
|
||||
.initialToken(VaultToken.of(vaultProperties.getToken())) //
|
||||
.build();
|
||||
|
||||
return new CubbyholeAuthentication(options, vaultClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ClientFactoryWrapper} containing a
|
||||
* {@link ClientHttpRequestFactory}. {@link ClientHttpRequestFactory} is not exposed
|
||||
@@ -344,6 +237,114 @@ public class VaultBootstrapConfiguration {
|
||||
return new SimpleSessionManager(clientAuthentication);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
|
||||
VaultClient vaultClient = vaultClient();
|
||||
|
||||
switch (vaultProperties.getAuthentication()) {
|
||||
|
||||
case TOKEN:
|
||||
Assert.hasText(vaultProperties.getToken(),
|
||||
"Token (spring.cloud.vault.token) must not be empty");
|
||||
return new TokenAuthentication(vaultProperties.getToken());
|
||||
|
||||
case APPID:
|
||||
return appIdAuthentication(vaultProperties, vaultClient);
|
||||
|
||||
case CERT:
|
||||
return new ClientCertificateAuthentication(vaultClient);
|
||||
|
||||
case AWS_EC2:
|
||||
return awsEc2Authentication(vaultProperties, vaultClient);
|
||||
|
||||
case CUBBYHOLE:
|
||||
return cubbyholeAuthentication(vaultClient);
|
||||
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(
|
||||
String.format("Client authentication %s not supported",
|
||||
vaultProperties.getAuthentication()));
|
||||
}
|
||||
|
||||
private ClientAuthentication appIdAuthentication(VaultProperties vaultProperties,
|
||||
VaultClient vaultClient) {
|
||||
|
||||
VaultProperties.AppIdProperties appId = vaultProperties.getAppId();
|
||||
Assert.hasText(appId.getUserId(),
|
||||
"UserId (spring.cloud.vault.app-id.user-id) must not be empty");
|
||||
|
||||
AppIdAuthenticationOptions authenticationOptions = AppIdAuthenticationOptions
|
||||
.builder().appId(vaultProperties.getApplicationName()) //
|
||||
.path(appId.getAppIdPath()) //
|
||||
.userIdMechanism(getClientAuthentication(appId)).build();
|
||||
|
||||
return new AppIdAuthentication(authenticationOptions, vaultClient);
|
||||
}
|
||||
|
||||
private AppIdUserIdMechanism getClientAuthentication(
|
||||
VaultProperties.AppIdProperties appId) {
|
||||
|
||||
try {
|
||||
Class<?> userIdClass = ClassUtils.forName(appId.getUserId(), null);
|
||||
return (AppIdUserIdMechanism) BeanUtils.instantiateClass(userIdClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
|
||||
switch (appId.getUserId().toUpperCase()) {
|
||||
|
||||
case VaultProperties.AppIdProperties.IP_ADDRESS:
|
||||
return new IpAddressUserId();
|
||||
|
||||
case VaultProperties.AppIdProperties.MAC_ADDRESS:
|
||||
|
||||
if (StringUtils.hasText(appId.getNetworkInterface())) {
|
||||
try {
|
||||
return new MacAddressUserId(
|
||||
Integer.parseInt(appId.getNetworkInterface()));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return new MacAddressUserId(appId.getNetworkInterface());
|
||||
}
|
||||
}
|
||||
|
||||
return new MacAddressUserId();
|
||||
default:
|
||||
return new StaticUserId(appId.getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClientAuthentication awsEc2Authentication(VaultProperties vaultProperties,
|
||||
VaultClient vaultClient) {
|
||||
|
||||
VaultProperties.AwsEc2Properties awsEc2 = vaultProperties.getAwsEc2();
|
||||
|
||||
AwsEc2AuthenticationOptions authenticationOptions = AwsEc2AuthenticationOptions
|
||||
.builder().role(awsEc2.getRole()) //
|
||||
.path(awsEc2.getAwsEc2Path()) //
|
||||
.identityDocumentUri(URI.create(awsEc2.getIdentityDocument())) //
|
||||
.build();
|
||||
|
||||
return new AwsEc2Authentication(authenticationOptions, vaultClient,
|
||||
vaultClient.getRestTemplate());
|
||||
}
|
||||
|
||||
private ClientAuthentication cubbyholeAuthentication(VaultClient vaultClient) {
|
||||
|
||||
Assert.hasText(vaultProperties.getToken(),
|
||||
"Initial Token (spring.cloud.vault.token) for Cubbyhole authentication must not be empty");
|
||||
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions.builder() //
|
||||
.wrapped() //
|
||||
.initialToken(VaultToken.of(vaultProperties.getToken())) //
|
||||
.build();
|
||||
|
||||
return new CubbyholeAuthentication(options, vaultClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to keep {@link TaskScheduler} local to Spring Cloud Vault.
|
||||
* @param <T>
|
||||
|
||||
@@ -22,22 +22,23 @@ import org.springframework.vault.core.VaultOperations;
|
||||
* {@link VaultConfigTemplate}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see VaultConfigTemplate
|
||||
* @see Secrets
|
||||
*/
|
||||
public interface VaultConfigOperations {
|
||||
|
||||
/**
|
||||
* Read secrets from a secret backend encapsulated within a
|
||||
* {@link SecureBackendAccessor}. Reading data using this method is suitable for
|
||||
* {@link SecretBackendMetadata}. Reading data using this method is suitable for
|
||||
* secret backends that do not require a request body.
|
||||
*
|
||||
* @param secureBackendAccessor must not be {@literal null}.
|
||||
* @param secretBackendMetadata must not be {@literal null}.
|
||||
* @return the configuration data. May be empty but never {@literal null}.
|
||||
* @throws IllegalStateException if {@link VaultProperties#isFailFast()} is enabled.
|
||||
*/
|
||||
Secrets read(SecureBackendAccessor secureBackendAccessor);
|
||||
Secrets read(SecretBackendMetadata secretBackendMetadata);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the underlying {@link VaultOperations}.
|
||||
*/
|
||||
VaultOperations getVaultOperations();
|
||||
|
||||
@@ -36,7 +36,7 @@ public class VaultConfigTemplate implements VaultConfigOperations {
|
||||
private final VaultProperties properties;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultConfigTemplate}.
|
||||
* Create a new {@link VaultConfigTemplate} given {@link VaultOperations}.
|
||||
*
|
||||
* @param vaultOperations must not be {@literal null}.
|
||||
* @param properties must not be {@literal null}.
|
||||
@@ -51,9 +51,10 @@ public class VaultConfigTemplate implements VaultConfigOperations {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public Secrets read(final SecureBackendAccessor secureBackendAccessor) {
|
||||
@Override
|
||||
public Secrets read(final SecretBackendMetadata secretBackendMetadata) {
|
||||
|
||||
Assert.notNull(secureBackendAccessor, "SecureBackendAccessor must not be null!");
|
||||
Assert.notNull(secretBackendMetadata, "SecureBackendAccessor must not be null!");
|
||||
|
||||
VaultResponseEntity<Secrets> response = vaultOperations.doWithVault(
|
||||
new VaultOperations.SessionCallback<VaultResponseEntity<Secrets>>() {
|
||||
@@ -62,7 +63,7 @@ public class VaultConfigTemplate implements VaultConfigOperations {
|
||||
VaultOperations.VaultSession session) {
|
||||
|
||||
return session.exchange("{backend}/{key}", HttpMethod.GET, null,
|
||||
Secrets.class, secureBackendAccessor.variables());
|
||||
Secrets.class, secretBackendMetadata.getVariables());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -71,7 +72,14 @@ public class VaultConfigTemplate implements VaultConfigOperations {
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
|
||||
Secrets secrets = response.getBody();
|
||||
secrets.setData(secureBackendAccessor.transformProperties(secrets.getData()));
|
||||
|
||||
PropertyTransformer propertyTransformer = secretBackendMetadata
|
||||
.getPropertyTransformer();
|
||||
|
||||
if (propertyTransformer != null) {
|
||||
secrets.setData(
|
||||
propertyTransformer.transformProperties(secrets.getData()));
|
||||
}
|
||||
|
||||
return secrets;
|
||||
}
|
||||
|
||||
@@ -31,31 +31,33 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Slf4j
|
||||
class VaultPropertySource extends EnumerablePropertySource<VaultConfigTemplate> {
|
||||
class VaultPropertySource extends EnumerablePropertySource<VaultConfigOperations> {
|
||||
|
||||
private final boolean failFast;
|
||||
|
||||
private final SecretBackendMetadata secretBackendMetadata;
|
||||
|
||||
private final VaultProperties vaultProperties;
|
||||
private final SecureBackendAccessor secureBackendAccessor;
|
||||
private final Map<String, String> properties = new LinkedHashMap<>();
|
||||
|
||||
private Secrets secrets;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultPropertySource}.
|
||||
*
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param properties must not be {@literal null}.
|
||||
* @param secureBackendAccessor must not be {@literal null}.
|
||||
* @param failFast fail if properties could not be read because of access errors.
|
||||
* @param secretBackendMetadata must not be {@literal null}.
|
||||
*/
|
||||
public VaultPropertySource(VaultConfigTemplate operations, VaultProperties properties,
|
||||
SecureBackendAccessor secureBackendAccessor) {
|
||||
public VaultPropertySource(VaultConfigOperations operations, boolean failFast,
|
||||
SecretBackendMetadata secretBackendMetadata) {
|
||||
|
||||
super(secureBackendAccessor.getName(), operations);
|
||||
super(secretBackendMetadata.getName(), operations);
|
||||
|
||||
Assert.notNull(operations, "VaultConfigTemplate must not be null!");
|
||||
Assert.notNull(properties, "VaultProperties must not be null!");
|
||||
Assert.notNull(secureBackendAccessor, "SecureBackendAccessor must not be null!");
|
||||
Assert.notNull(secretBackendMetadata, "SecretBackendMetadata must not be null!");
|
||||
|
||||
this.vaultProperties = properties;
|
||||
this.secureBackendAccessor = secureBackendAccessor;
|
||||
this.failFast = failFast;
|
||||
this.secretBackendMetadata = secretBackendMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,22 +66,19 @@ class VaultPropertySource extends EnumerablePropertySource<VaultConfigTemplate>
|
||||
public void init() {
|
||||
|
||||
try {
|
||||
this.secrets = this.source.read(this.secureBackendAccessor);
|
||||
this.secrets = this.source.read(this.secretBackendMetadata);
|
||||
if (this.secrets != null) {
|
||||
this.properties.putAll(secrets.getData());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (RuntimeException e) {
|
||||
|
||||
String message = String.format(
|
||||
"Unable to read properties from Vault using %s for %s ", getName(),
|
||||
secureBackendAccessor.variables());
|
||||
if (vaultProperties.isFailFast()) {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw e;
|
||||
}
|
||||
secretBackendMetadata.getVariables());
|
||||
|
||||
throw new IllegalStateException(message, e);
|
||||
if (failFast) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
log.error(message, e);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import static org.springframework.cloud.vault.config.SecureBackendAccessors.*;
|
||||
import static org.springframework.cloud.vault.config.GenericSecretBackendMetadata.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -41,10 +41,10 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
class VaultPropertySourceLocator implements PropertySourceLocator, PriorityOrdered {
|
||||
|
||||
private final VaultConfigTemplate operations;
|
||||
private final VaultConfigOperations operations;
|
||||
private final VaultProperties properties;
|
||||
private final VaultGenericBackendProperties genericBackendProperties;
|
||||
private final Collection<SecureBackendAccessor> backendAccessors;
|
||||
private final Collection<SecretBackendMetadata> backendAccessors;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultPropertySourceLocator}.
|
||||
@@ -54,10 +54,10 @@ class VaultPropertySourceLocator implements PropertySourceLocator, PriorityOrder
|
||||
* @param genericBackendProperties must not be {@literal null}.
|
||||
* @param backendAccessors must not be {@literal null}.
|
||||
*/
|
||||
public VaultPropertySourceLocator(VaultConfigTemplate operations,
|
||||
public VaultPropertySourceLocator(VaultConfigOperations operations,
|
||||
VaultProperties properties,
|
||||
VaultGenericBackendProperties genericBackendProperties,
|
||||
Collection<SecureBackendAccessor> backendAccessors) {
|
||||
Collection<SecretBackendMetadata> backendAccessors) {
|
||||
|
||||
Assert.notNull(operations, "VaultConfigOperations must not be null");
|
||||
Assert.notNull(properties, "VaultProperties must not be null");
|
||||
@@ -129,7 +129,7 @@ class VaultPropertySourceLocator implements PropertySourceLocator, PriorityOrder
|
||||
if (StringUtils.hasText(propertySourceContext)) {
|
||||
|
||||
VaultPropertySource vaultPropertySource = createVaultPropertySource(
|
||||
generic(genericBackendProperties.getBackend(),
|
||||
create(genericBackendProperties.getBackend(),
|
||||
propertySourceContext));
|
||||
|
||||
propertySources.add(vaultPropertySource);
|
||||
@@ -137,7 +137,7 @@ class VaultPropertySourceLocator implements PropertySourceLocator, PriorityOrder
|
||||
}
|
||||
}
|
||||
|
||||
for (SecureBackendAccessor backendAccessor : backendAccessors) {
|
||||
for (SecretBackendMetadata backendAccessor : backendAccessors) {
|
||||
|
||||
VaultPropertySource vaultPropertySource = createVaultPropertySource(
|
||||
backendAccessor);
|
||||
@@ -185,14 +185,15 @@ class VaultPropertySourceLocator implements PropertySourceLocator, PriorityOrder
|
||||
|
||||
/**
|
||||
* Create {@link VaultPropertySource} initialized with a
|
||||
* {@link SecureBackendAccessor}.
|
||||
* {@link SecretBackendMetadata}.
|
||||
*
|
||||
* @param accessor the {@link SecureBackendAccessor}.
|
||||
* @param accessor the {@link SecretBackendMetadata}.
|
||||
* @return the {@link VaultPropertySource} to use.
|
||||
*/
|
||||
protected VaultPropertySource createVaultPropertySource(
|
||||
SecureBackendAccessor accessor) {
|
||||
return new VaultPropertySource(this.operations, this.properties, accessor);
|
||||
SecretBackendMetadata accessor) {
|
||||
return new VaultPropertySource(this.operations, this.properties.isFailFast(),
|
||||
accessor);
|
||||
}
|
||||
|
||||
private void addProfiles(List<String> contexts, String baseContext,
|
||||
|
||||
@@ -17,21 +17,26 @@
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
/**
|
||||
* A secret backend that can return secrets from Vault.
|
||||
* Interface to be implemented by objects that describe a Vault secret backend.
|
||||
*
|
||||
* <p>
|
||||
* Typically used by {@link SecretBackendMetadataFactory} to provide path and
|
||||
* configuration to create a {@link SecretBackendMetadata} object.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see SecretBackendMetadataFactory
|
||||
* @see SecretBackendMetadata
|
||||
*/
|
||||
public interface VaultSecretBackend {
|
||||
public interface VaultSecretBackendDescriptor {
|
||||
|
||||
/**
|
||||
* Backend path.
|
||||
* Backend path without leading/trailing slashes.
|
||||
*
|
||||
* @return the backend path.
|
||||
* @return the backend path such as {@code secret} or {@code mysql}.
|
||||
*/
|
||||
String getBackend();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {@literal true} if the backend is enabled.
|
||||
*/
|
||||
boolean isEnabled();
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.cloud.vault.config.SecureBackendAccessors.*;
|
||||
import static org.springframework.cloud.vault.config.GenericSecretBackendMetadata.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -51,7 +51,7 @@ public class GenericSecretIntegrationTests extends IntegrationTestSupport {
|
||||
public void shouldReturnSecretsCorrectly() throws Exception {
|
||||
|
||||
Map<String, String> secretProperties = configOperations
|
||||
.read(generic("secret", "app-name")).getData();
|
||||
.read(create("secret", "app-name")).getData();
|
||||
|
||||
assertThat(secretProperties).containsAllEntriesOf(createExpectedMap());
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class GenericSecretIntegrationTests extends IntegrationTestSupport {
|
||||
@Test
|
||||
public void shouldReturnNullIfNotFound() throws Exception {
|
||||
|
||||
Secrets secrets = configOperations.read(generic("secret", "missing"));
|
||||
Secrets secrets = configOperations.read(create("secret", "missing"));
|
||||
|
||||
assertThat(secrets).isNull();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class LeasingVaultPropertySourceLocatorUnitTests {
|
||||
|
||||
propertySourceLocator = new LeasingVaultPropertySourceLocator(operations,
|
||||
new VaultProperties(), new VaultGenericBackendProperties(),
|
||||
Collections.<SecureBackendAccessor> emptyList(), taskScheduler);
|
||||
Collections.<SecretBackendMetadata> emptyList(), taskScheduler);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,7 +71,7 @@ public class LeasingVaultPropertySourceLocatorUnitTests {
|
||||
|
||||
propertySourceLocator = new LeasingVaultPropertySourceLocator(operations,
|
||||
vaultProperties, new VaultGenericBackendProperties(),
|
||||
Collections.<SecureBackendAccessor> emptyList(), taskScheduler);
|
||||
Collections.<SecretBackendMetadata> emptyList(), taskScheduler);
|
||||
|
||||
assertThat(propertySourceLocator.getOrder()).isEqualTo(10);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class LeasingVaultPropertySourceUnitTests {
|
||||
private VaultOperations vaultOperations;
|
||||
|
||||
@Mock
|
||||
private SecureBackendAccessor secureBackendAccessor;
|
||||
private SecretBackendMetadata secretBackendMetadata;
|
||||
|
||||
@Mock
|
||||
private TaskScheduler taskScheduler;
|
||||
@@ -66,11 +66,11 @@ public class LeasingVaultPropertySourceUnitTests {
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
||||
when(secureBackendAccessor.getName()).thenReturn("test");
|
||||
when(secretBackendMetadata.getName()).thenReturn("test");
|
||||
when(configOperations.getVaultOperations()).thenReturn(vaultOperations);
|
||||
|
||||
propertySource = new LeasingVaultPropertySource(configOperations,
|
||||
new VaultProperties(), secureBackendAccessor, taskScheduler);
|
||||
false, secretBackendMetadata, taskScheduler);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,7 +87,7 @@ public class LeasingVaultPropertySourceUnitTests {
|
||||
Secrets secrets = new Secrets();
|
||||
secrets.setData(Collections.singletonMap("key", "value"));
|
||||
|
||||
when(configOperations.read(secureBackendAccessor)).thenReturn(secrets);
|
||||
when(configOperations.read(secretBackendMetadata)).thenReturn(secrets);
|
||||
|
||||
propertySource.init();
|
||||
|
||||
@@ -103,7 +103,7 @@ public class LeasingVaultPropertySourceUnitTests {
|
||||
secrets.setRenewable(false);
|
||||
secrets.setData(Collections.singletonMap("key", "value"));
|
||||
|
||||
when(configOperations.read(secureBackendAccessor)).thenReturn(secrets);
|
||||
when(configOperations.read(secretBackendMetadata)).thenReturn(secrets);
|
||||
|
||||
propertySource.init();
|
||||
|
||||
@@ -116,7 +116,7 @@ public class LeasingVaultPropertySourceUnitTests {
|
||||
|
||||
when(taskScheduler.schedule(any(Runnable.class), any(Trigger.class)))
|
||||
.thenReturn(scheduledFuture);
|
||||
when(configOperations.read(secureBackendAccessor)).thenReturn(createSecrets());
|
||||
when(configOperations.read(secretBackendMetadata)).thenReturn(createSecrets());
|
||||
|
||||
propertySource.init();
|
||||
|
||||
@@ -237,7 +237,7 @@ public class LeasingVaultPropertySourceUnitTests {
|
||||
|
||||
when(taskScheduler.schedule(any(Runnable.class), any(Trigger.class)))
|
||||
.thenReturn(scheduledFuture);
|
||||
when(configOperations.read(secureBackendAccessor)).thenReturn(createSecrets());
|
||||
when(configOperations.read(secretBackendMetadata)).thenReturn(createSecrets());
|
||||
propertySource.init();
|
||||
when(vaultOperations.doWithVault(any(VaultOperations.SessionCallback.class)))
|
||||
.thenReturn(getResponseEntity("new_lease", true, 70, HttpStatus.OK));
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.vault.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PropertyNameTransformer}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class PropertyNameTransformerUnitTests {
|
||||
|
||||
@Test
|
||||
public void shouldTranslateProperties() throws Exception {
|
||||
|
||||
PropertyNameTransformer transformer = new PropertyNameTransformer();
|
||||
transformer.addKeyTransformation("old-key", "new-key");
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("old-key", "value");
|
||||
map.put("other-key", "other-value");
|
||||
|
||||
assertThat(transformer.transformProperties(map)).containsEntry("new-key", "value")
|
||||
.containsEntry("other-key", "other-value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAllowNullInput() throws Exception {
|
||||
|
||||
PropertyNameTransformer transformer = new PropertyNameTransformer();
|
||||
transformer.addKeyTransformation("old-key", "new-key");
|
||||
|
||||
assertThat(transformer.transformProperties(null)).isNull();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.vault.util.IntegrationTestSupport;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
|
||||
@@ -44,7 +45,7 @@ public class VaultPropertySourceIntegrationTests extends IntegrationTestSupport
|
||||
|
||||
VaultPropertySource propertySource = new VaultPropertySource(
|
||||
new VaultConfigTemplate(prepare().getVaultOperations(), vaultProperties),
|
||||
vaultProperties, SecureBackendAccessors.generic("secret", "myapp"));
|
||||
false, GenericSecretBackendMetadata.create("secret", "myapp"));
|
||||
|
||||
propertySource.init();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user