Split into modules #11
Split Spring Cloud Vault Config into multiple modules: Core, Config, Database/Consul/RabbitMQ integrations.
This commit is contained in:
@@ -12,7 +12,7 @@ install:
|
||||
- mkdir -p download
|
||||
- test -f download/apache-cassandra-2.2.6-bin.tar.gz || wget http://www-eu.apache.org/dist/cassandra/2.2.6/apache-cassandra-2.2.6-bin.tar.gz -O download/apache-cassandra-2.2.6-bin.tar.gz
|
||||
- tar xzf download/apache-cassandra-2.2.6-bin.tar.gz
|
||||
- cp -f spring-cloud-vault-config/src/test/resources/cassandra.yaml apache-cassandra-2.2.6/conf
|
||||
- cp -f spring-cloud-vault-config-databases/src/test/resources/cassandra.yaml apache-cassandra-2.2.6/conf
|
||||
- apache-cassandra-2.2.6/bin/cassandra
|
||||
- src/test/bash/create_certificates.sh
|
||||
- src/test/bash/install_vault.sh
|
||||
|
||||
72
pom.xml
72
pom.xml
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-build</artifactId>
|
||||
@@ -20,10 +20,74 @@
|
||||
<description>Configuration Integration with Hashicorp Vault</description>
|
||||
|
||||
<modules>
|
||||
<module>spring-cloud-vault-config</module>
|
||||
<module>docs</module>
|
||||
<module>spring-cloud-vault-core</module>
|
||||
<module>spring-cloud-vault-config</module>
|
||||
<module>spring-cloud-vault-config-databases</module>
|
||||
<module>spring-cloud-vault-config-consul</module>
|
||||
<module>spring-cloud-vault-config-rabbitmq</module>
|
||||
<module>docs</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.7</java.version>
|
||||
<httpclient.version>4.5.2</httpclient.version>
|
||||
<httpcore.version>4.4.4</httpcore.version>
|
||||
<netty.version>4.1.0.Final</netty.version>
|
||||
<okhttp.version>2.7.5</okhttp.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
<version>1.1.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${httpclient.version}</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>${httpcore.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
|
||||
83
spring-cloud-vault-config-consul/pom.xml
Normal file
83
spring-cloud-vault-config-consul/pom.xml
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config-consul</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Spring Cloud Vault Config Consul support</name>
|
||||
<description>Spring Cloud Vault Config Consul support</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.consul;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.vault.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessorFactory;
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public class VaultConfigConsulBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecureBackendAccessorFactory<VaultConsulProperties> secureBackendAccessorFactory() {
|
||||
return new ConsulSecureBackendAccessorFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultConsulProperties vaultConsulProperties() {
|
||||
return new VaultConsulProperties();
|
||||
}
|
||||
|
||||
static class ConsulSecureBackendAccessorFactory
|
||||
implements SecureBackendAccessorFactory<VaultConsulProperties> {
|
||||
|
||||
@Override
|
||||
public SecureBackendAccessor createSecureBackendAccessor(
|
||||
VaultConsulProperties properties) {
|
||||
return forConsul(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(VaultSecretBackend secretBackend) {
|
||||
return secretBackend instanceof VaultConsulProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure 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}
|
||||
*/
|
||||
public static SecureBackendAccessor forConsul(
|
||||
final VaultConsulProperties properties) {
|
||||
|
||||
Assert.notNull(properties, "VaultConsulProperties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
variables.put("backend", properties.getBackend());
|
||||
variables.put("key", String.format("creds/%s", properties.getRole()));
|
||||
return variables;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.consul;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Configuration properties for Hashicorp Consul.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault.consul")
|
||||
@Data
|
||||
public class VaultConsulProperties implements VaultSecretBackend {
|
||||
|
||||
/**
|
||||
* Enable consul backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* Consul backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "consul";
|
||||
|
||||
/**
|
||||
* Target property for the obtained token.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String tokenProperty = "spring.cloud.consul.token";
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Consul integration with Vault.
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
package org.springframework.cloud.vault.config.consul;
|
||||
@@ -0,0 +1,3 @@
|
||||
# Bootstrap Configuration
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.vault.config.consul.VaultConfigConsulBootstrapConfiguration
|
||||
@@ -13,21 +13,24 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault;
|
||||
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.SecureBackendAccessors.*;
|
||||
import static org.springframework.cloud.vault.config.consul.VaultConfigConsulBootstrapConfiguration.ConsulSecureBackendAccessorFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.test.TestRestTemplate;
|
||||
import org.springframework.cloud.vault.AbstractIntegrationTests;
|
||||
import org.springframework.cloud.vault.TestRestTemplateFactory;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.util.CanConnect;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
@@ -35,6 +38,7 @@ import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultClient} using the consul secret backend. This test
|
||||
@@ -58,7 +62,7 @@ public class ConsulSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
private VaultProperties vaultProperties = Settings.createVaultProperties();
|
||||
private VaultClient vaultClient = new VaultClient(vaultProperties);
|
||||
private VaultProperties.Consul consul = vaultProperties.getConsul();
|
||||
private VaultConsulProperties consul = new VaultConsulProperties();
|
||||
|
||||
private TestRestTemplate restTemplate = new TestRestTemplate();
|
||||
|
||||
@@ -84,8 +88,8 @@ public class ConsulSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
HttpEntity<String> requestEntity = new HttpEntity<>(
|
||||
"{\"Name\": \"sample\", \"Type\": \"management\"}", headers);
|
||||
ResponseEntity<Map<String, String>> tokenResponse = restTemplate.exchange(
|
||||
"http://{address}/v1/acl/create", HttpMethod.PUT, requestEntity,
|
||||
STRING_MAP, CONNECTION_URL);
|
||||
"http://{host}:{port}/v1/acl/create", HttpMethod.PUT, requestEntity,
|
||||
STRING_MAP, CONSUL_HOST, CONSUL_PORT);
|
||||
|
||||
Map<String, String> consulAccess = new HashMap<>();
|
||||
consulAccess.put("address", CONNECTION_URL);
|
||||
@@ -97,7 +101,7 @@ public class ConsulSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
prepare().write(
|
||||
String.format("%s/roles/%s", consul.getBackend(), consul.getRole()),
|
||||
Collections.singletonMap("policy",
|
||||
Base64.encodeBase64String(POLICY.getBytes())));
|
||||
Base64Utils.encodeToString(POLICY.getBytes())));
|
||||
|
||||
vaultClient.setRest(TestRestTemplateFactory.create(vaultProperties));
|
||||
}
|
||||
@@ -105,7 +109,7 @@ public class ConsulSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
@Test
|
||||
public void shouldCreateCredentialsCorrectly() throws Exception {
|
||||
|
||||
Map<String, String> secretProperties = vaultClient.read(consul(consul),
|
||||
Map<String, String> secretProperties = vaultClient.read(forConsul(consul),
|
||||
Settings.token());
|
||||
|
||||
assertThat(secretProperties).containsKeys("spring.cloud.consul.token");
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault.configclient;
|
||||
package org.springframework.cloud.vault.config.consul;
|
||||
|
||||
import static org.assertj.core.api.Java6Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
@@ -25,13 +25,13 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.boot.test.TestRestTemplate;
|
||||
@@ -42,6 +42,7 @@ import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.crypto.codec.Base64;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
@@ -53,10 +54,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = VaultConsulTests.TestApplication.class)
|
||||
@SpringApplicationConfiguration(classes = VaultConfigConsulTests.TestApplication.class)
|
||||
@IntegrationTest({ "spring.cloud.vault.consul.enabled=true",
|
||||
"spring.cloud.vault.consul.role=readonly" })
|
||||
public class VaultConsulTests {
|
||||
public class VaultConfigConsulTests {
|
||||
|
||||
private final static String CONSUL_HOST = "localhost";
|
||||
private final static int CONSUL_PORT = 8500;
|
||||
@@ -104,7 +105,7 @@ public class VaultConsulTests {
|
||||
vaultRule.prepare().write("consul/config/access", consulAccess);
|
||||
|
||||
vaultRule.prepare().write("consul/roles/readonly", Collections
|
||||
.singletonMap("policy", Base64.encodeBase64String(POLICY.getBytes())));
|
||||
.singletonMap("policy", Base64.encode(POLICY.getBytes())));
|
||||
}
|
||||
|
||||
@Value("${spring.cloud.consul.token}")
|
||||
@@ -0,0 +1,5 @@
|
||||
spring:
|
||||
application.name: testVaultApp
|
||||
cloud.vault.token: 00000000-0000-0000-0000-000000000000
|
||||
cloud.vault.ssl.trust-store: file:../work/keystore.jks
|
||||
cloud.vault.ssl.trust-store-password: changeit
|
||||
97
spring-cloud-vault-config-databases/pom.xml
Normal file
97
spring-cloud-vault-config-databases/pom.xml
Normal file
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config-databases</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Spring Cloud Vault Config Database support</name>
|
||||
<description>Spring Cloud Vault Config Database support</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.38</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>9.4.1208.jre7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-core</artifactId>
|
||||
<version>2.1.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.databases;
|
||||
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
|
||||
/**
|
||||
* Configuration properties interface for database secrets.
|
||||
*/
|
||||
public interface DatabaseSecretProperties extends VaultSecretBackend {
|
||||
|
||||
/**
|
||||
* Role name.
|
||||
*
|
||||
* @return the role name
|
||||
*/
|
||||
String getRole();
|
||||
|
||||
/**
|
||||
* Backend path.
|
||||
*
|
||||
* @return the backend path.
|
||||
*/
|
||||
String getBackend();
|
||||
|
||||
/**
|
||||
* Name of the target property for the obtained username.
|
||||
*/
|
||||
String getUsernameProperty();
|
||||
|
||||
/**
|
||||
* Name of the target property for the obtained password.
|
||||
*/
|
||||
String getPasswordProperty();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.databases;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Configuration properties for Vault using the Apache Cassandra integration.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault.cassandra")
|
||||
@Data
|
||||
public class VaultCassandraProperties implements DatabaseSecretProperties {
|
||||
|
||||
/**
|
||||
* Enable cassandra backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* Cassandra backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "cassandra";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String usernameProperty = "spring.data.cassandra.username";
|
||||
|
||||
/**
|
||||
* Target property for the obtained password.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String passwordProperty = "spring.data.cassandra.password";
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.databases;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.vault.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessorFactory;
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public class VaultConfigDatabaseBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecureBackendAccessorFactory<DatabaseSecretProperties> secureBackendAccessorFactory() {
|
||||
return new DatabaseSecureBackendAccessorFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultMySqlProperties mySqlProperties() {
|
||||
return new VaultMySqlProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultPostgreSqlProperties postgreSqlProperties() {
|
||||
return new VaultPostgreSqlProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultCassandraProperties cassandraProperties() {
|
||||
return new VaultCassandraProperties();
|
||||
}
|
||||
|
||||
static class DatabaseSecureBackendAccessorFactory
|
||||
implements SecureBackendAccessorFactory<DatabaseSecretProperties> {
|
||||
|
||||
@Override
|
||||
public SecureBackendAccessor createSecureBackendAccessor(
|
||||
DatabaseSecretProperties properties) {
|
||||
return forDatabase(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(VaultSecretBackend secretBackend) {
|
||||
return secretBackend instanceof DatabaseSecretProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure 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}
|
||||
*/
|
||||
public static SecureBackendAccessor forDatabase(
|
||||
final DatabaseSecretProperties properties) {
|
||||
Assert.notNull(properties, "DatabaseSecretProperties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
variables.put("backend", properties.getBackend());
|
||||
variables.put("key", String.format("creds/%s", properties.getRole()));
|
||||
return variables;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
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.VaultSecretBackend;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Configuration properties for Vault using the MySQL integration.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault.mysql")
|
||||
@Data
|
||||
public class VaultMySqlProperties implements DatabaseSecretProperties, VaultSecretBackend {
|
||||
|
||||
/**
|
||||
* Enable mysql backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* mysql backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "mysql";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String usernameProperty = "spring.datasource.username";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String passwordProperty = "spring.datasource.password";
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.databases;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Configuration properties for Vault using the PostgreSQL integration.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault.postgresql")
|
||||
@Data
|
||||
public class VaultPostgreSqlProperties implements DatabaseSecretProperties {
|
||||
|
||||
/**
|
||||
* Enable postgresql backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* postgresql backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "postgresql";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String usernameProperty = "spring.datasource.username";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String passwordProperty = "spring.datasource.password";
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Database integration with Vault.
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
package org.springframework.cloud.vault.config.databases;
|
||||
@@ -0,0 +1,3 @@
|
||||
# Bootstrap Configuration
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration
|
||||
@@ -13,20 +13,23 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault;
|
||||
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.SecureBackendAccessors.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecureBackendAccessorFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.vault.AbstractIntegrationTests;
|
||||
import org.springframework.cloud.vault.TestRestTemplateFactory;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.util.CanConnect;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
|
||||
@@ -50,7 +53,7 @@ public class CassandraSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
private VaultProperties vaultProperties = Settings.createVaultProperties();
|
||||
private VaultClient vaultClient = new VaultClient(vaultProperties);
|
||||
private VaultProperties.Cassandra cassandra = vaultProperties.getCassandra();
|
||||
private VaultCassandraProperties cassandra = new VaultCassandraProperties();
|
||||
|
||||
/**
|
||||
* Initialize cassandra secret backend.
|
||||
@@ -87,7 +90,7 @@ public class CassandraSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
@Test
|
||||
public void shouldCreateCredentialsCorrectly() throws Exception {
|
||||
|
||||
Map<String, String> secretProperties = vaultClient.read(database(cassandra),
|
||||
Map<String, String> secretProperties = vaultClient.read(forDatabase(cassandra),
|
||||
Settings.token());
|
||||
|
||||
assertThat(secretProperties).containsKeys("spring.data.cassandra.username",
|
||||
@@ -13,19 +13,22 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault;
|
||||
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.SecureBackendAccessors.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecureBackendAccessorFactory.forDatabase;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.vault.AbstractIntegrationTests;
|
||||
import org.springframework.cloud.vault.TestRestTemplateFactory;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.util.CanConnect;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
|
||||
@@ -46,7 +49,7 @@ public class MySqlSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
private VaultProperties vaultProperties = Settings.createVaultProperties();
|
||||
private VaultClient vaultClient = new VaultClient(vaultProperties);
|
||||
private VaultProperties.MySql mySql = vaultProperties.getMysql();
|
||||
private VaultMySqlProperties mySql = new VaultMySqlProperties();
|
||||
|
||||
/**
|
||||
* Initialize the mysql secret backend.
|
||||
@@ -77,7 +80,7 @@ public class MySqlSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
@Test
|
||||
public void shouldCreateCredentialsCorrectly() throws Exception {
|
||||
|
||||
Map<String, String> secretProperties = vaultClient.read(database(mySql),
|
||||
Map<String, String> secretProperties = vaultClient.read(forDatabase(mySql),
|
||||
Settings.token());
|
||||
|
||||
assertThat(secretProperties).containsKeys("spring.datasource.username",
|
||||
@@ -13,11 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault;
|
||||
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.SecureBackendAccessors.*;
|
||||
import static org.springframework.cloud.vault.config.databases.VaultConfigDatabaseBootstrapConfiguration.DatabaseSecureBackendAccessorFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
@@ -25,6 +25,10 @@ import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.vault.AbstractIntegrationTests;
|
||||
import org.springframework.cloud.vault.TestRestTemplateFactory;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.util.CanConnect;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
|
||||
@@ -49,7 +53,7 @@ public class PostgreSqlSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
private VaultProperties vaultProperties = Settings.createVaultProperties();
|
||||
private VaultClient vaultClient = new VaultClient(vaultProperties);
|
||||
private VaultProperties.PostgreSql postgreSql = vaultProperties.getPostgresql();
|
||||
private VaultPostgreSqlProperties postgreSql = new VaultPostgreSqlProperties();
|
||||
|
||||
/**
|
||||
* Initialize the postgresql secret backend.
|
||||
@@ -82,7 +86,7 @@ public class PostgreSqlSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
@Test
|
||||
public void shouldCreateCredentialsCorrectly() throws Exception {
|
||||
|
||||
Map<String, String> secretProperties = vaultClient.read(database(postgreSql),
|
||||
Map<String, String> secretProperties = vaultClient.read(forDatabase(postgreSql),
|
||||
Settings.token());
|
||||
|
||||
assertThat(secretProperties).containsKeys("spring.datasource.username",
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault.configclient;
|
||||
package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
@@ -49,10 +49,10 @@ import com.datastax.driver.core.Session;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = VaultCassandraTests.TestApplication.class)
|
||||
@SpringApplicationConfiguration(classes = VaultConfigCassandraTests.TestApplication.class)
|
||||
@IntegrationTest({ "spring.cloud.vault.cassandra.enabled=true",
|
||||
"spring.cloud.vault.cassandra.role=readonly" })
|
||||
public class VaultCassandraTests {
|
||||
public class VaultConfigCassandraTests {
|
||||
|
||||
private final static String CASSANDRA_HOST = "localhost";
|
||||
private final static int CASSANDRA_PORT = 9042;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault.configclient;
|
||||
package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
@@ -45,11 +45,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = VaultMySqlTests.TestApplication.class)
|
||||
@SpringApplicationConfiguration(classes = VaultConfigMySqlTests.TestApplication.class)
|
||||
@IntegrationTest({ "spring.cloud.vault.mysql.enabled=true",
|
||||
"spring.cloud.vault.mysql.role=readonly",
|
||||
"spring.datasource.url=jdbc:mysql://localhost:3306/mysql?useSSL=false" })
|
||||
public class VaultMySqlTests {
|
||||
public class VaultConfigMySqlTests {
|
||||
|
||||
private final static int MYSQL_PORT = 3306;
|
||||
private final static String MYSQL_HOST = "localhost";
|
||||
@@ -14,29 +14,28 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault.configclient;
|
||||
package org.springframework.cloud.vault.config.databases;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.postgresql.jdbc.PgConnection;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cglib.proxy.Proxy;
|
||||
import org.springframework.cloud.vault.util.CanConnect;
|
||||
import org.springframework.cloud.vault.util.VaultRule;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -49,10 +48,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = VaultPostgreSqlTests.TestApplication.class)
|
||||
@SpringApplicationConfiguration(classes = VaultConfigPostgreSqlTests.TestApplication.class)
|
||||
@IntegrationTest({ "spring.cloud.vault.postgresql.enabled=true",
|
||||
"spring.cloud.vault.postgresql.role=readonly", "spring.datasource.url=jdbc:postgresql://localhost:5432/postgres?ssl=false" })
|
||||
public class VaultPostgreSqlTests {
|
||||
public class VaultConfigPostgreSqlTests {
|
||||
|
||||
private final static String POSTGRES_HOST = "localhost";
|
||||
private final static int POSTGRES_PORT = 5432;
|
||||
@@ -0,0 +1,5 @@
|
||||
spring:
|
||||
application.name: testVaultApp
|
||||
cloud.vault.token: 00000000-0000-0000-0000-000000000000
|
||||
cloud.vault.ssl.trust-store: file:../work/keystore.jks
|
||||
cloud.vault.ssl.trust-store-password: changeit
|
||||
72
spring-cloud-vault-config-rabbitmq/pom.xml
Normal file
72
spring-cloud-vault-config-rabbitmq/pom.xml
Normal file
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config-rabbitmq</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Spring Cloud Vault Config RabbitMQ support</name>
|
||||
<description>Spring Cloud Vault Config RabbitMQ support</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.rabbitmq;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.vault.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.config.SecureBackendAccessorFactory;
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public class VaultConfigRabbitMqBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecureBackendAccessorFactory<VaultRabbitMqProperties> secureBackendAccessorFactory() {
|
||||
return new RabbitMqSecureBackendAccessorFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultRabbitMqProperties rabbitMqProperties() {
|
||||
return new VaultRabbitMqProperties();
|
||||
}
|
||||
|
||||
static class RabbitMqSecureBackendAccessorFactory
|
||||
implements SecureBackendAccessorFactory<VaultRabbitMqProperties> {
|
||||
|
||||
@Override
|
||||
public SecureBackendAccessor createSecureBackendAccessor(
|
||||
VaultRabbitMqProperties properties) {
|
||||
return forRabbitMq(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(VaultSecretBackend secretBackend) {
|
||||
return secretBackend instanceof VaultRabbitMqProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure 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}
|
||||
*/
|
||||
public static SecureBackendAccessor forRabbitMq(
|
||||
final VaultRabbitMqProperties properties) {
|
||||
Assert.notNull(properties, "DatabaseSecretProperties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
variables.put("backend", properties.getBackend());
|
||||
variables.put("key", String.format("creds/%s", properties.getRole()));
|
||||
return variables;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.rabbitmq;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Configuration properties for Vault using the RabbitMQ integration.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault.rabbitmq")
|
||||
@Data
|
||||
public class VaultRabbitMqProperties implements VaultSecretBackend {
|
||||
|
||||
/**
|
||||
* Enable rabbitmq backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* RabbitMQ backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "rabbitmq";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String usernameProperty = "spring.rabbitmq.username";
|
||||
|
||||
/**
|
||||
* Target property for the obtained password.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String passwordProperty = "spring.rabbitmq.password";
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* RabbitMQ integration with Vault.
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
package org.springframework.cloud.vault.config.rabbitmq;
|
||||
@@ -0,0 +1,3 @@
|
||||
# Bootstrap Configuration
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.vault.config.rabbitmq.VaultConfigRabbitMqBootstrapConfiguration
|
||||
@@ -13,11 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault;
|
||||
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.SecureBackendAccessors.*;
|
||||
import static org.springframework.cloud.vault.config.rabbitmq.VaultConfigRabbitMqBootstrapConfiguration.RabbitMqSecureBackendAccessorFactory.*;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
@@ -26,6 +26,10 @@ import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.vault.AbstractIntegrationTests;
|
||||
import org.springframework.cloud.vault.TestRestTemplateFactory;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.util.CanConnect;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
|
||||
@@ -35,7 +39,7 @@ import org.springframework.cloud.vault.util.Settings;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class RabbitMQSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
public class RabbitMqSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
|
||||
private final static int RABBITMQ_HTTP_MANAGEMENT_PORT = 15672;
|
||||
private final static String RABBITMQ_HOST = "localhost";
|
||||
@@ -43,14 +47,14 @@ public class RabbitMQSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
private final static String RABBITMQ_USERNAME = "guest";
|
||||
private final static String RABBITMQ_PASSWORD = "guest";
|
||||
|
||||
private final static String RABBITMQ_URI = String
|
||||
.format("http://%s:%d", RABBITMQ_HOST, RABBITMQ_HTTP_MANAGEMENT_PORT);
|
||||
private final static String RABBITMQ_URI = String.format("http://%s:%d",
|
||||
RABBITMQ_HOST, RABBITMQ_HTTP_MANAGEMENT_PORT);
|
||||
|
||||
private final static String VHOSTS_ROLE = "{\"/\":{\"write\": \".*\", \"read\": \".*\"}}";
|
||||
|
||||
private VaultProperties vaultProperties = Settings.createVaultProperties();
|
||||
private VaultClient vaultClient = new VaultClient(vaultProperties);
|
||||
private VaultProperties.Rabbitmq rabbitmq = vaultProperties.getRabbitmq();
|
||||
private VaultRabbitMqProperties rabbitmq = new VaultRabbitMqProperties();
|
||||
|
||||
/**
|
||||
* Initialize the mysql secret backend.
|
||||
@@ -60,7 +64,8 @@ public class RabbitMQSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
assumeTrue(CanConnect.to(new InetSocketAddress(RABBITMQ_HOST, RABBITMQ_HTTP_MANAGEMENT_PORT)));
|
||||
assumeTrue(CanConnect
|
||||
.to(new InetSocketAddress(RABBITMQ_HOST, RABBITMQ_HTTP_MANAGEMENT_PORT)));
|
||||
|
||||
rabbitmq.setEnabled(true);
|
||||
rabbitmq.setRole("readonly");
|
||||
@@ -77,7 +82,8 @@ public class RabbitMQSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
prepare().write(String.format("%s/config/connection", rabbitmq.getBackend()),
|
||||
connection);
|
||||
|
||||
prepare().write(String.format("%s/roles/%s", rabbitmq.getBackend(), rabbitmq.getRole()),
|
||||
prepare().write(
|
||||
String.format("%s/roles/%s", rabbitmq.getBackend(), rabbitmq.getRole()),
|
||||
Collections.singletonMap("vhosts", VHOSTS_ROLE));
|
||||
|
||||
vaultClient.setRest(TestRestTemplateFactory.create(vaultProperties));
|
||||
@@ -86,7 +92,7 @@ public class RabbitMQSecretIntegrationTests extends AbstractIntegrationTests {
|
||||
@Test
|
||||
public void shouldCreateCredentialsCorrectly() throws Exception {
|
||||
|
||||
Map<String, String> secretProperties = vaultClient.read(database(rabbitmq),
|
||||
Map<String, String> secretProperties = vaultClient.read(forRabbitMq(rabbitmq),
|
||||
Settings.token());
|
||||
|
||||
assertThat(secretProperties).containsKeys("spring.rabbitmq.username",
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault.configclient;
|
||||
package org.springframework.cloud.vault.config.rabbitmq;
|
||||
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
@@ -49,11 +49,11 @@ import com.rabbitmq.client.ConnectionFactory;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = VaultRabbitMQTests.TestApplication.class)
|
||||
@SpringApplicationConfiguration(classes = VaultConfigRabbitMqTests.TestApplication.class)
|
||||
@IntegrationTest({ "spring.cloud.vault.rabbitmq.enabled=true",
|
||||
"spring.cloud.vault.rabbitmq.role=readonly",
|
||||
"spring.rabbitmq.address=localhost" })
|
||||
public class VaultRabbitMQTests {
|
||||
public class VaultConfigRabbitMqTests {
|
||||
|
||||
private final static int RABBITMQ_HTTP_MANAGEMENT_PORT = 15672;
|
||||
private final static int RABBITMQ_PORT = 5672;
|
||||
@@ -133,4 +133,4 @@ public class VaultRabbitMQTests {
|
||||
SpringApplication.run(TestApplication.class, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
spring:
|
||||
application.name: testVaultApp
|
||||
cloud.vault.token: 00000000-0000-0000-0000-000000000000
|
||||
cloud.vault.ssl.trust-store: file:../work/keystore.jks
|
||||
cloud.vault.ssl.trust-store-password: changeit
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config-parent</artifactId>
|
||||
@@ -15,32 +15,22 @@
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-cloud-vault-config</name>
|
||||
<name>Spring Cloud Vault Configuration Integration</name>
|
||||
<description>Configuration Integration with Hashicorp Vault</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.7</java.version>
|
||||
<httpclient.version>4.5.2</httpclient.version>
|
||||
<httpcore.version>4.4.4</httpcore.version>
|
||||
<netty.version>4.1.0.Final</netty.version>
|
||||
<okhttp.version>2.7.5</okhttp.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
<version>1.1.0.BUILD-SNAPSHOT</version>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
@@ -52,99 +42,17 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${httpclient.version}</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>${httpcore.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.38</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>9.4.1208.jre7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-core</artifactId>
|
||||
<version>2.1.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,149 +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;
|
||||
|
||||
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
|
||||
*/
|
||||
public class SecureBackendAccessors {
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for the {@code generic} secure backend.
|
||||
*
|
||||
* @param vaultProperties must not be {@literal null}.
|
||||
* @param key must not be {@literal null} and not empty.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
*/
|
||||
public static SecureBackendAccessor generic(VaultProperties vaultProperties,
|
||||
String key) {
|
||||
|
||||
Assert.notNull(vaultProperties, "VaultProperties must not be null");
|
||||
return generic(vaultProperties.getBackend(), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Map<String, String> transformProperties(Map<String, String> input) {
|
||||
return input;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure backend using
|
||||
* {@link org.springframework.cloud.vault.VaultProperties.DatabaseSecretProperties}.
|
||||
* This accessor transforms Vault's username/password property names to names provided
|
||||
* with {@link VaultProperties.DatabaseSecretProperties#getUsernameProperty()} and
|
||||
* {@link VaultProperties.DatabaseSecretProperties#getUsernameProperty()}.
|
||||
*
|
||||
* @param properties must not be {@literal null}.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
*/
|
||||
public static SecureBackendAccessor database(
|
||||
final VaultProperties.DatabaseSecretProperties properties) {
|
||||
|
||||
Assert.notNull(properties, "DatabaseSecretProperties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
variables.put("backend", properties.getBackend());
|
||||
variables.put("key", String.format("creds/%s", properties.getRole()));
|
||||
return variables;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureBackendAccessor} for a secure backend using
|
||||
* {@link org.springframework.cloud.vault.VaultProperties.Consul}.
|
||||
* This accessor transforms Vault's token property names to names provided
|
||||
* with {@link VaultProperties.Consul#getTokenProperty()}.
|
||||
*
|
||||
* @param properties must not be {@literal null}.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
*/
|
||||
public static SecureBackendAccessor consul(
|
||||
final VaultProperties.Consul properties) {
|
||||
|
||||
Assert.notNull(properties, "Consul properties must not be null");
|
||||
|
||||
return new SecureBackendAccessor() {
|
||||
|
||||
@Override
|
||||
public Map<String, String> variables() {
|
||||
|
||||
Map<String, String> variables = new HashMap<>();
|
||||
variables.put("backend", properties.getBackend());
|
||||
variables.put("key", String.format("creds/%s", properties.getRole()));
|
||||
return variables;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2015 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;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault")
|
||||
@Data
|
||||
public class VaultProperties {
|
||||
|
||||
/**
|
||||
* Enable Vault config server.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Vault server host.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String host = "localhost";
|
||||
|
||||
/**
|
||||
* Vault server port.
|
||||
*/
|
||||
@Range(min = 1, max = 65535)
|
||||
private int port = 8200;
|
||||
|
||||
/**
|
||||
* Protocol scheme. Can be either "http" or "https".
|
||||
*/
|
||||
private String scheme = "https";
|
||||
|
||||
/**
|
||||
* Name of the default backend.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "secret";
|
||||
|
||||
/**
|
||||
* Name of the default context.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String defaultContext = "application";
|
||||
|
||||
/**
|
||||
* Profile-separator to combine application name and profile.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String profileSeparator = ",";
|
||||
|
||||
/**
|
||||
* Connection timeout;
|
||||
*/
|
||||
private int connectionTimeout = 5000;
|
||||
|
||||
/**
|
||||
* Read timeout;
|
||||
*/
|
||||
private int readTimeout = 15000;
|
||||
|
||||
/**
|
||||
* Fail fast if data cannot be obtained from Vault.
|
||||
*/
|
||||
private boolean failFast = false;
|
||||
|
||||
/**
|
||||
* Static vault token. Required if {@link #authentication} is {@code TOKEN}.
|
||||
*/
|
||||
private String token;
|
||||
|
||||
private AppIdProperties appId = new AppIdProperties();
|
||||
|
||||
private Ssl ssl = new Ssl();
|
||||
|
||||
private MySql mysql = new MySql();
|
||||
|
||||
private PostgreSql postgresql = new PostgreSql();
|
||||
|
||||
private Cassandra cassandra = new Cassandra();
|
||||
|
||||
private Consul consul = new Consul();
|
||||
|
||||
private Rabbitmq rabbitmq = new Rabbitmq();
|
||||
|
||||
/**
|
||||
* Application name for AppId authentication.
|
||||
*/
|
||||
@org.springframework.beans.factory.annotation.Value("${spring.application.name:application}")
|
||||
private String applicationName;
|
||||
|
||||
private AuthenticationMethod authentication = AuthenticationMethod.TOKEN;
|
||||
|
||||
@Data
|
||||
public static class AppIdProperties {
|
||||
|
||||
/**
|
||||
* Property value for UserId generation using a Mac-Address.
|
||||
* @see MacAddressUserId
|
||||
*/
|
||||
public final static String MAC_ADDRESS = "MAC_ADDRESS";
|
||||
|
||||
/**
|
||||
* Property value for UserId generation using an IP-Address.
|
||||
* @see IpAddressUserId
|
||||
*/
|
||||
public final static String IP_ADDRESS = "IP_ADDRESS";
|
||||
|
||||
/**
|
||||
* Mount path of the AppId authentication backend.
|
||||
*/
|
||||
private String appIdPath = "app-id";
|
||||
|
||||
/**
|
||||
* Network interface hint for the "MAC_ADDRESS" UserId mechanism.
|
||||
*/
|
||||
private String networkInterface = null;
|
||||
|
||||
/**
|
||||
* UserId mechanism. Can be either "MAC_ADDRESS", "IP_ADDRESS", a string or a
|
||||
* class name.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String userId = MAC_ADDRESS;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Ssl {
|
||||
|
||||
/**
|
||||
* Trust store that holds SSL certificates.
|
||||
*/
|
||||
private Resource trustStore;
|
||||
|
||||
/**
|
||||
* Password used to access the trust store.
|
||||
*/
|
||||
private String trustStorePassword;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class MySql implements DatabaseSecretProperties {
|
||||
|
||||
/**
|
||||
* Enable mysql backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* mysql backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "mysql";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String usernameProperty = "spring.datasource.username";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String passwordProperty = "spring.datasource.password";
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class PostgreSql implements DatabaseSecretProperties {
|
||||
|
||||
/**
|
||||
* Enable postgresql backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* postgresql backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "postgresql";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String usernameProperty = "spring.datasource.username";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String passwordProperty = "spring.datasource.password";
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Cassandra implements DatabaseSecretProperties {
|
||||
|
||||
/**
|
||||
* Enable cassandra backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* Cassandra backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "cassandra";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String usernameProperty = "spring.data.cassandra.username";
|
||||
|
||||
/**
|
||||
* Target property for the obtained password.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String passwordProperty = "spring.data.cassandra.password";
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Consul {
|
||||
|
||||
/**
|
||||
* Enable consul backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* Consul backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "consul";
|
||||
|
||||
/**
|
||||
* Target property for the obtained token.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String tokenProperty = "spring.cloud.consul.token";
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Rabbitmq implements DatabaseSecretProperties {
|
||||
|
||||
/**
|
||||
* Enable rabbitmq backend usage.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Role name for credentials.
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* RabbitMQ backend path.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "rabbitmq";
|
||||
|
||||
/**
|
||||
* Target property for the obtained username.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String usernameProperty = "spring.rabbitmq.username";
|
||||
|
||||
/**
|
||||
* Target property for the obtained password.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String passwordProperty = "spring.rabbitmq.password";
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration properties interface for database secrets.
|
||||
*/
|
||||
public interface DatabaseSecretProperties {
|
||||
|
||||
/**
|
||||
* Role name.
|
||||
*
|
||||
* @return the role name
|
||||
*/
|
||||
String getRole();
|
||||
|
||||
/**
|
||||
* Backend path.
|
||||
*
|
||||
* @return the backend path.
|
||||
*/
|
||||
String getBackend();
|
||||
|
||||
/**
|
||||
* Name of the target property for the obtained username.
|
||||
*/
|
||||
String getUsernameProperty();
|
||||
|
||||
/**
|
||||
* Name of the target property for the obtained password.
|
||||
*/
|
||||
String getPasswordProperty();
|
||||
}
|
||||
|
||||
public enum AuthenticationMethod {
|
||||
TOKEN, APPID,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 org.springframework.cloud.vault.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
|
||||
/**
|
||||
* Factory to convert {@link VaultSecretBackend} instance to a
|
||||
* {@link SecureBackendAccessor}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface SecureBackendAccessorFactory<T extends VaultSecretBackend> {
|
||||
|
||||
/**
|
||||
* Converts a {@link VaultSecretBackend} into a {@link SecureBackendAccessor}.
|
||||
* @param configurationProperties
|
||||
* @return the {@link SecureBackendAccessor}.
|
||||
*/
|
||||
SecureBackendAccessor createSecureBackendAccessor(T configurationProperties);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
boolean supports(VaultSecretBackend secretBackend);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.cloud.vault.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
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 vaultProperties must not be {@literal null}.
|
||||
* @param key must not be {@literal null} and not empty.
|
||||
* @return the {@link SecureBackendAccessor}
|
||||
*/
|
||||
public static SecureBackendAccessor generic(VaultProperties vaultProperties,
|
||||
String key) {
|
||||
|
||||
Assert.notNull(vaultProperties, "VaultProperties must not be null");
|
||||
return generic(vaultProperties.getBackend(), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Map<String, String> transformProperties(Map<String, String> input) {
|
||||
return input;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 org.springframework.cloud.vault.SecureBackendAccessor;
|
||||
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@CommonsLog
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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.Collection;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.vault.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.VaultBootstrapConfiguration;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.VaultSecretBackend;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnProperty(name = "spring.cloud.vault.enabled", matchIfMissing = true)
|
||||
@ConditionalOnBean(VaultBootstrapConfiguration.class)
|
||||
public class VaultConfigBootstrapConfiguration implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private Collection<VaultSecretBackend> vaultSecretBackends;
|
||||
private Collection<SecureBackendAccessorFactory<? super VaultSecretBackend>> factories;
|
||||
|
||||
@Bean
|
||||
public VaultPropertySourceLocator vaultPropertySourceLocator(VaultClient vaultClient,
|
||||
VaultProperties vaultProperties) {
|
||||
|
||||
Collection<SecureBackendAccessor> backendAccessors = SecureBackendFactories
|
||||
.createBackendAcessors(vaultSecretBackends, factories);
|
||||
|
||||
return new VaultPropertySourceLocator(vaultClient, vaultProperties,
|
||||
backendAccessors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void postConstruct() {
|
||||
|
||||
this.vaultSecretBackends = applicationContext
|
||||
.getBeansOfType(VaultSecretBackend.class).values();
|
||||
this.factories = (Collection) applicationContext
|
||||
.getBeansOfType(SecureBackendAccessorFactory.class).values();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -14,18 +14,29 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.cloud.vault.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.VaultProperties.AppIdProperties;
|
||||
import org.springframework.cloud.vault.VaultProperties.AuthenticationMethod;
|
||||
import org.springframework.cloud.vault.VaultToken;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
/**
|
||||
* A {@link EnumerablePropertySource} backed by {@link VaultClient}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -47,12 +58,13 @@ public class VaultPropertySource extends EnumerablePropertySource<VaultClient> {
|
||||
this.vaultState = state;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
public void init(Collection<SecureBackendAccessor> externalBackendAccessors) {
|
||||
|
||||
Assert.hasText(vaultProperties.getBackend(),
|
||||
"No generic secret backend configured (spring.cloud.vault.backend)");
|
||||
|
||||
List<SecureBackendAccessor> accessors = getSecureBackendAccessors();
|
||||
List<SecureBackendAccessor> accessors = getSecureBackendAccessors(
|
||||
externalBackendAccessors);
|
||||
|
||||
for (SecureBackendAccessor accessor : accessors) {
|
||||
try {
|
||||
@@ -80,37 +92,16 @@ public class VaultPropertySource extends EnumerablePropertySource<VaultClient> {
|
||||
}
|
||||
}
|
||||
|
||||
private List<SecureBackendAccessor> getSecureBackendAccessors() {
|
||||
private List<SecureBackendAccessor> getSecureBackendAccessors(
|
||||
Collection<SecureBackendAccessor> externalBackendAccessors) {
|
||||
|
||||
List<SecureBackendAccessor> accessors = new ArrayList<>();
|
||||
|
||||
accessors.add(SecureBackendAccessors.generic(vaultProperties.getBackend(),
|
||||
this.context));
|
||||
|
||||
VaultProperties.MySql mySql = vaultProperties.getMysql();
|
||||
if (mySql.isEnabled()) {
|
||||
accessors.add(SecureBackendAccessors.database(mySql));
|
||||
}
|
||||
accessors.addAll(externalBackendAccessors);
|
||||
|
||||
VaultProperties.PostgreSql postgreSql = vaultProperties.getPostgresql();
|
||||
if (postgreSql.isEnabled()) {
|
||||
accessors.add(SecureBackendAccessors.database(postgreSql));
|
||||
}
|
||||
|
||||
VaultProperties.Cassandra cassandra = vaultProperties.getCassandra();
|
||||
if (cassandra.isEnabled()) {
|
||||
accessors.add(SecureBackendAccessors.database(cassandra));
|
||||
}
|
||||
|
||||
VaultProperties.Consul consul = vaultProperties.getConsul();
|
||||
if (consul.isEnabled()) {
|
||||
accessors.add(SecureBackendAccessors.consul(consul));
|
||||
}
|
||||
|
||||
VaultProperties.Rabbitmq rabbitmq = vaultProperties.getRabbitmq();
|
||||
if (rabbitmq.isEnabled()) {
|
||||
accessors.add(SecureBackendAccessors.database(rabbitmq));
|
||||
}
|
||||
return accessors;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -14,38 +14,61 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
|
||||
import org.springframework.cloud.vault.SecureBackendAccessor;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.core.env.CompositePropertySource;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link PropertySourceLocator} using {@link VaultClient}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultPropertySourceLocator implements PropertySourceLocator {
|
||||
|
||||
private VaultClient vault;
|
||||
private VaultClient vaultClient;
|
||||
|
||||
private VaultProperties properties;
|
||||
private final Collection<SecureBackendAccessor> backendAcessors;
|
||||
|
||||
private transient final VaultState vaultState = new VaultState();
|
||||
|
||||
public VaultPropertySourceLocator(VaultClient vault, VaultProperties properties) {
|
||||
this.vault = vault;
|
||||
/**
|
||||
* Creates a new {@link VaultPropertySourceLocator}.
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
* @param properties must not be {@literal null}.
|
||||
* @param backendAccessors must not be {@literal null}.
|
||||
*/
|
||||
public VaultPropertySourceLocator(VaultClient vaultClient, VaultProperties properties,
|
||||
Collection<SecureBackendAccessor> backendAccessors) {
|
||||
|
||||
Assert.notNull(vaultClient, "VaultClient must not be null");
|
||||
Assert.notNull(properties, "VaultProperties must not be null");
|
||||
Assert.notNull(backendAccessors, "BackendAccessors must not be null");
|
||||
|
||||
this.vaultClient = vaultClient;
|
||||
this.properties = properties;
|
||||
this.backendAcessors = backendAccessors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertySource<?> locate(Environment environment) {
|
||||
|
||||
if (environment instanceof ConfigurableEnvironment) {
|
||||
ConfigurableEnvironment env = (ConfigurableEnvironment) environment;
|
||||
String appName = env.getProperty("spring.application.name");
|
||||
@@ -66,9 +89,12 @@ public class VaultPropertySourceLocator implements PropertySourceLocator {
|
||||
CompositePropertySource composite = new CompositePropertySource("vault");
|
||||
|
||||
for (String propertySourceContext : contexts) {
|
||||
VaultPropertySource propertySource = create(propertySourceContext);
|
||||
propertySource.init();
|
||||
composite.addPropertySource(propertySource);
|
||||
|
||||
if(StringUtils.hasText(propertySourceContext)) {
|
||||
VaultPropertySource propertySource = create(propertySourceContext);
|
||||
propertySource.init(backendAcessors);
|
||||
composite.addPropertySource(propertySource);
|
||||
}
|
||||
}
|
||||
|
||||
return composite;
|
||||
@@ -77,11 +103,12 @@ public class VaultPropertySourceLocator implements PropertySourceLocator {
|
||||
}
|
||||
|
||||
private VaultPropertySource create(String context) {
|
||||
return new VaultPropertySource(context, this.vault, this.properties, this.vaultState);
|
||||
return new VaultPropertySource(context, this.vaultClient, this.properties,
|
||||
this.vaultState);
|
||||
}
|
||||
|
||||
private void addProfiles(List<String> contexts, String baseContext,
|
||||
List<String> profiles) {
|
||||
List<String> profiles) {
|
||||
for (String profile : profiles) {
|
||||
contexts.add(baseContext + this.properties.getProfileSeparator() + profile);
|
||||
}
|
||||
@@ -14,9 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.cloud.vault.VaultToken;
|
||||
|
||||
/**
|
||||
* State of the Vault client.
|
||||
@@ -1,3 +1,3 @@
|
||||
# Bootstrap Configuration
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.vault.VaultBootstrapConfiguration
|
||||
org.springframework.cloud.vault.config.VaultConfigBootstrapConfiguration
|
||||
@@ -13,11 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.springframework.cloud.vault.IpAddressUserId;
|
||||
import org.springframework.cloud.vault.TestRestTemplateFactory;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties.AppIdProperties;
|
||||
import org.springframework.cloud.vault.VaultProperties.AuthenticationMethod;
|
||||
import org.springframework.cloud.vault.VaultToken;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault.configclient;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
@@ -13,16 +13,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.cloud.vault.SecureBackendAccessors.*;
|
||||
import static org.springframework.cloud.vault.config.SecureBackendAccessors.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.vault.AbstractIntegrationTests;
|
||||
import org.springframework.cloud.vault.TestRestTemplateFactory;
|
||||
import org.springframework.cloud.vault.VaultClient;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.VaultToken;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 org.junit.Test;
|
||||
import org.springframework.cloud.vault.TestRestTemplateFactory;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.VaultToken;
|
||||
import org.springframework.cloud.vault.util.PrepareVault;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link PrepareVault}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class PrepareVaultTests {
|
||||
|
||||
private VaultProperties vaultProperties = Settings.createVaultProperties();
|
||||
private PrepareVault prepareVault = new PrepareVault(TestRestTemplateFactory.create(vaultProperties));
|
||||
|
||||
@Test
|
||||
public void initializeShouldCreateANewVault() throws Exception {
|
||||
|
||||
prepareVault.setRootToken(Settings.token());
|
||||
prepareVault.setVaultProperties(vaultProperties);
|
||||
|
||||
if (!prepareVault.isAvailable()) {
|
||||
VaultToken rootToken = prepareVault.initializeVault();
|
||||
prepareVault.setRootToken(rootToken);
|
||||
prepareVault.createToken(vaultProperties.getToken(), "root");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
@@ -29,7 +29,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.vault.VaultAppIdCustomMechanismTests.BootstrapConfiguration;
|
||||
import org.springframework.cloud.vault.AppIdUserIdMechanism;
|
||||
import org.springframework.cloud.vault.config.VaultConfigAppIdCustomMechanismTests.BootstrapConfiguration;
|
||||
import org.springframework.cloud.vault.VaultProperties;
|
||||
import org.springframework.cloud.vault.util.Settings;
|
||||
import org.springframework.cloud.vault.util.VaultRule;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -41,10 +43,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = { BootstrapConfiguration.class,
|
||||
VaultAppIdCustomMechanismTests.TestApplication.class })
|
||||
VaultConfigAppIdCustomMechanismTests.TestApplication.class })
|
||||
@IntegrationTest({ "spring.cloud.vault.authentication=appid", "use.custom.config=true",
|
||||
"spring.application.name=VaultAppIdCustomMechanismTests" })
|
||||
public class VaultAppIdCustomMechanismTests {
|
||||
"spring.application.name=VaultConfigAppIdCustomMechanismTests" })
|
||||
public class VaultConfigAppIdCustomMechanismTests {
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
@@ -53,7 +55,7 @@ public class VaultAppIdCustomMechanismTests {
|
||||
vaultRule.before();
|
||||
|
||||
vaultRule.prepare().writeSecret(
|
||||
VaultAppIdCustomMechanismTests.class.getSimpleName(),
|
||||
VaultConfigAppIdCustomMechanismTests.class.getSimpleName(),
|
||||
Collections.singletonMap("vault.value", "foo"));
|
||||
|
||||
VaultProperties vaultProperties = Settings.createVaultProperties();
|
||||
@@ -64,9 +66,9 @@ public class VaultAppIdCustomMechanismTests {
|
||||
}
|
||||
|
||||
vaultRule.prepare()
|
||||
.mapAppId(VaultAppIdCustomMechanismTests.class.getSimpleName());
|
||||
.mapAppId(VaultConfigAppIdCustomMechanismTests.class.getSimpleName());
|
||||
vaultRule.prepare().mapUserId(
|
||||
VaultAppIdCustomMechanismTests.class.getSimpleName(),
|
||||
VaultConfigAppIdCustomMechanismTests.class.getSimpleName(),
|
||||
new StaticUserIdMechanism().createUserId());
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault.configclient;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
@@ -41,11 +41,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = VaultAppIdTests.TestApplication.class)
|
||||
@SpringApplicationConfiguration(classes = VaultConfigAppIdTests.TestApplication.class)
|
||||
@IntegrationTest({ "spring.cloud.vault.authentication=appid",
|
||||
"spring.cloud.vault.app-id.user-id=IP_ADDRESS",
|
||||
"spring.application.name=VaultAppIdTests" })
|
||||
public class VaultAppIdTests {
|
||||
"spring.application.name=VaultConfigAppIdTests" })
|
||||
public class VaultConfigAppIdTests {
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
@@ -53,7 +53,7 @@ public class VaultAppIdTests {
|
||||
VaultRule vaultRule = new VaultRule();
|
||||
vaultRule.before();
|
||||
|
||||
vaultRule.prepare().writeSecret(VaultAppIdTests.class.getSimpleName(),
|
||||
vaultRule.prepare().writeSecret(VaultConfigAppIdTests.class.getSimpleName(),
|
||||
Collections.singletonMap("vault.value", "foo"));
|
||||
|
||||
VaultProperties vaultProperties = Settings.createVaultProperties();
|
||||
@@ -64,8 +64,8 @@ public class VaultAppIdTests {
|
||||
vaultRule.prepare().mountAuth(vaultProperties.getAppId().getAppIdPath());
|
||||
}
|
||||
|
||||
vaultRule.prepare().mapAppId(VaultAppIdTests.class.getSimpleName());
|
||||
vaultRule.prepare().mapUserId(VaultAppIdTests.class.getSimpleName(),
|
||||
vaultRule.prepare().mapAppId(VaultConfigAppIdTests.class.getSimpleName());
|
||||
vaultRule.prepare().mapUserId(VaultConfigAppIdTests.class.getSimpleName(),
|
||||
new IpAddressUserId().createUserId());
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.vault.configclient;
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
@@ -37,8 +37,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = VaultTests.TestApplication.class)
|
||||
public class VaultTests {
|
||||
@SpringApplicationConfiguration(classes = VaultConfigTests.TestApplication.class)
|
||||
public class VaultConfigTests {
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
@@ -1,3 +1,3 @@
|
||||
# Bootstrap Configuration
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.vault.VaultAppIdCustomMechanismTests.BootstrapConfiguration
|
||||
org.springframework.cloud.vault.config.VaultConfigAppIdCustomMechanismTests.BootstrapConfiguration
|
||||
|
||||
92
spring-cloud-vault-core/pom.xml
Normal file
92
spring-cloud-vault-core/pom.xml
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-config-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-vault-core</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Spring Cloud Vault Core</name>
|
||||
<description>Spring Cloud Vault Core</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test-jar</id>
|
||||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -77,15 +77,15 @@ class ClientHttpRequestFactoryFactory {
|
||||
try {
|
||||
|
||||
if (HTTP_COMPONENTS_PRESENT) {
|
||||
return usingHttpComponents(vaultProperties);
|
||||
return HttpComponents.usingHttpComponents(vaultProperties);
|
||||
}
|
||||
|
||||
if (OKHTTP_PRESENT) {
|
||||
return usingOkHttp(vaultProperties);
|
||||
return OkHttp.usingOkHttp(vaultProperties);
|
||||
}
|
||||
|
||||
if (NETTY_PRESENT) {
|
||||
return usingNetty(vaultProperties);
|
||||
return Netty.usingNetty(vaultProperties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,87 +101,6 @@ class ClientHttpRequestFactoryFactory {
|
||||
return new SimpleClientHttpRequestFactory();
|
||||
}
|
||||
|
||||
protected static ClientHttpRequestFactory usingHttpComponents(
|
||||
VaultProperties vaultProperties)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||
|
||||
if (hasSslConfiguration(vaultProperties)) {
|
||||
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
|
||||
getSSLContext(vaultProperties.getSsl()));
|
||||
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
|
||||
}
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom() //
|
||||
.setConnectTimeout(vaultProperties.getConnectionTimeout()) //
|
||||
.setSocketTimeout(vaultProperties.getReadTimeout()) //
|
||||
.build();
|
||||
|
||||
httpClientBuilder.setDefaultRequestConfig(requestConfig);
|
||||
|
||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
|
||||
httpClientBuilder.build());
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
protected static ClientHttpRequestFactory usingNetty(VaultProperties vaultProperties)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
VaultProperties.Ssl ssl = vaultProperties.getSsl();
|
||||
|
||||
final Netty4ClientHttpRequestFactory requestFactory = new Netty4ClientHttpRequestFactory();
|
||||
|
||||
if (hasSslConfiguration(vaultProperties)) {
|
||||
|
||||
SslContext sslContext = SslContextBuilder //
|
||||
.forClient() //
|
||||
.trustManager(createTrustManagerFactory(ssl.getTrustStore(),
|
||||
ssl.getTrustStorePassword())) //
|
||||
.sslProvider(SslProvider.JDK) //
|
||||
.build();
|
||||
|
||||
requestFactory.setSslContext(sslContext);
|
||||
}
|
||||
|
||||
requestFactory.setConnectTimeout(vaultProperties.getConnectionTimeout());
|
||||
requestFactory.setReadTimeout(vaultProperties.getReadTimeout());
|
||||
|
||||
return requestFactory;
|
||||
}
|
||||
|
||||
protected static ClientHttpRequestFactory usingOkHttp(VaultProperties vaultProperties)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
final OkHttpClient okHttpClient = new OkHttpClient();
|
||||
|
||||
OkHttpClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory(
|
||||
okHttpClient) {
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
|
||||
if (okHttpClient.getCache() != null) {
|
||||
okHttpClient.getCache().close();
|
||||
}
|
||||
|
||||
okHttpClient.getDispatcher().getExecutorService().shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
if (hasSslConfiguration(vaultProperties)) {
|
||||
okHttpClient.setSslSocketFactory(
|
||||
getSSLContext(vaultProperties.getSsl()).getSocketFactory());
|
||||
}
|
||||
|
||||
requestFactory.setConnectTimeout(vaultProperties.getConnectionTimeout());
|
||||
requestFactory.setReadTimeout(vaultProperties.getReadTimeout());
|
||||
|
||||
return requestFactory;
|
||||
}
|
||||
|
||||
private static SSLContext getSSLContext(VaultProperties.Ssl ssl)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
@@ -217,4 +136,109 @@ class ClientHttpRequestFactoryFactory {
|
||||
return vaultProperties.getSsl() != null
|
||||
&& vaultProperties.getSsl().getTrustStore() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} for Apache Http Components.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
static class HttpComponents {
|
||||
protected static ClientHttpRequestFactory usingHttpComponents(
|
||||
VaultProperties vaultProperties)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||
|
||||
if (hasSslConfiguration(vaultProperties)) {
|
||||
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
|
||||
getSSLContext(vaultProperties.getSsl()));
|
||||
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
|
||||
}
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom() //
|
||||
.setConnectTimeout(vaultProperties.getConnectionTimeout()) //
|
||||
.setSocketTimeout(vaultProperties.getReadTimeout()) //
|
||||
.build();
|
||||
|
||||
httpClientBuilder.setDefaultRequestConfig(requestConfig);
|
||||
|
||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
|
||||
httpClientBuilder.build());
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} for the {@link OkHttpClient}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
static class OkHttp {
|
||||
|
||||
protected static ClientHttpRequestFactory usingOkHttp(
|
||||
VaultProperties vaultProperties)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
final OkHttpClient okHttpClient = new OkHttpClient();
|
||||
|
||||
OkHttpClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory(
|
||||
okHttpClient) {
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
|
||||
if (okHttpClient.getCache() != null) {
|
||||
okHttpClient.getCache().close();
|
||||
}
|
||||
|
||||
okHttpClient.getDispatcher().getExecutorService().shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
if (hasSslConfiguration(vaultProperties)) {
|
||||
okHttpClient.setSslSocketFactory(
|
||||
getSSLContext(vaultProperties.getSsl()).getSocketFactory());
|
||||
}
|
||||
|
||||
requestFactory.setConnectTimeout(vaultProperties.getConnectionTimeout());
|
||||
requestFactory.setReadTimeout(vaultProperties.getReadTimeout());
|
||||
|
||||
return requestFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} for Netty.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
static class Netty {
|
||||
protected static ClientHttpRequestFactory usingNetty(
|
||||
VaultProperties vaultProperties)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
VaultProperties.Ssl ssl = vaultProperties.getSsl();
|
||||
|
||||
final Netty4ClientHttpRequestFactory requestFactory = new Netty4ClientHttpRequestFactory();
|
||||
|
||||
if (hasSslConfiguration(vaultProperties)) {
|
||||
|
||||
SslContext sslContext = SslContextBuilder //
|
||||
.forClient() //
|
||||
.trustManager(createTrustManagerFactory(ssl.getTrustStore(),
|
||||
ssl.getTrustStorePassword())) //
|
||||
.sslProvider(SslProvider.JDK) //
|
||||
.build();
|
||||
|
||||
requestFactory.setSslContext(sslContext);
|
||||
}
|
||||
|
||||
requestFactory.setConnectTimeout(vaultProperties.getConnectionTimeout());
|
||||
requestFactory.setReadTimeout(vaultProperties.getReadTimeout());
|
||||
|
||||
return requestFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,16 +22,16 @@ import java.net.NetworkInterface;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Mechanism to generate a UserId based on the Mac address. {@link MacAddressUserId} creates a hex-encoded
|
||||
* representation of the Mac address without any separators (0123456789AB). A
|
||||
* {@link org.springframework.cloud.vault.VaultProperties.AppIdProperties#networkInterface} can be
|
||||
* {@link VaultProperties.AppIdProperties#networkInterface} can be
|
||||
* specified optionally to select a network interface (index/name).
|
||||
*
|
||||
* @author Mark Paluch
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -19,6 +19,8 @@ package org.springframework.cloud.vault;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -41,15 +43,16 @@ import org.springframework.web.client.RestTemplate;
|
||||
public class VaultBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
@Qualifier("vault-ClientHttpRequestFactory")
|
||||
public ClientHttpRequestFactory clientHttpRequestFactory(){
|
||||
return ClientHttpRequestFactoryFactory.create(vaultProperties());
|
||||
public ClientFactoryWrapper clientHttpRequestFactoryWrapper() {
|
||||
return new ClientFactoryWrapper(
|
||||
ClientHttpRequestFactoryFactory.create(vaultProperties()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Qualifier("vault-RestTemplate")
|
||||
public RestTemplate restTemplate(){
|
||||
return new RestTemplate(clientHttpRequestFactory());
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate(
|
||||
clientHttpRequestFactoryWrapper().getClientHttpRequestFactory());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -99,10 +102,34 @@ public class VaultBootstrapConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultPropertySourceLocator vaultPropertySourceLocator(
|
||||
ApplicationContext applicationContext) {
|
||||
return new VaultPropertySourceLocator(vaultClient(applicationContext),
|
||||
vaultProperties());
|
||||
/**
|
||||
* Wrapper for {@link ClientHttpRequestFactory} to not expose the bean globally.
|
||||
*/
|
||||
static class ClientFactoryWrapper implements InitializingBean, DisposableBean {
|
||||
|
||||
private final ClientHttpRequestFactory clientHttpRequestFactory;
|
||||
|
||||
public ClientFactoryWrapper(ClientHttpRequestFactory clientHttpRequestFactory) {
|
||||
this.clientHttpRequestFactory = clientHttpRequestFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
if (clientHttpRequestFactory instanceof DisposableBean) {
|
||||
((DisposableBean) clientHttpRequestFactory).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
if (clientHttpRequestFactory instanceof InitializingBean) {
|
||||
((InitializingBean) clientHttpRequestFactory).afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
|
||||
public ClientHttpRequestFactory getClientHttpRequestFactory() {
|
||||
return clientHttpRequestFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -57,7 +57,6 @@ public class VaultClient {
|
||||
@Setter
|
||||
private AppIdUserIdMechanism appIdUserIdMechanism;
|
||||
|
||||
private ClientHttpRequestFactory clientHttpRequestFactory;
|
||||
private final VaultProperties properties;
|
||||
|
||||
public VaultClient(VaultProperties properties) {
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.vault")
|
||||
@Data
|
||||
public class VaultProperties {
|
||||
|
||||
/**
|
||||
* Enable Vault config server.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Vault server host.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String host = "localhost";
|
||||
|
||||
/**
|
||||
* Vault server port.
|
||||
*/
|
||||
@Range(min = 1, max = 65535)
|
||||
private int port = 8200;
|
||||
|
||||
/**
|
||||
* Protocol scheme. Can be either "http" or "https".
|
||||
*/
|
||||
private String scheme = "https";
|
||||
|
||||
/**
|
||||
* Name of the default backend.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String backend = "secret";
|
||||
|
||||
/**
|
||||
* Name of the default context.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String defaultContext = "application";
|
||||
|
||||
/**
|
||||
* Profile-separator to combine application name and profile.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String profileSeparator = ",";
|
||||
|
||||
/**
|
||||
* Connection timeout;
|
||||
*/
|
||||
private int connectionTimeout = 5000;
|
||||
|
||||
/**
|
||||
* Read timeout;
|
||||
*/
|
||||
private int readTimeout = 15000;
|
||||
|
||||
/**
|
||||
* Fail fast if data cannot be obtained from Vault.
|
||||
*/
|
||||
private boolean failFast = false;
|
||||
|
||||
/**
|
||||
* Static vault token. Required if {@link #authentication} is {@code TOKEN}.
|
||||
*/
|
||||
private String token;
|
||||
|
||||
private AppIdProperties appId = new AppIdProperties();
|
||||
|
||||
private Ssl ssl = new Ssl();
|
||||
|
||||
/**
|
||||
* Application name for AppId authentication.
|
||||
*/
|
||||
@org.springframework.beans.factory.annotation.Value("${spring.application.name:application}")
|
||||
private String applicationName;
|
||||
|
||||
private AuthenticationMethod authentication = AuthenticationMethod.TOKEN;
|
||||
|
||||
@Data
|
||||
public static class AppIdProperties {
|
||||
|
||||
/**
|
||||
* Property value for UserId generation using a Mac-Address.
|
||||
* @see MacAddressUserId
|
||||
*/
|
||||
public final static String MAC_ADDRESS = "MAC_ADDRESS";
|
||||
|
||||
/**
|
||||
* Property value for UserId generation using an IP-Address.
|
||||
* @see IpAddressUserId
|
||||
*/
|
||||
public final static String IP_ADDRESS = "IP_ADDRESS";
|
||||
|
||||
/**
|
||||
* Mount path of the AppId authentication backend.
|
||||
*/
|
||||
private String appIdPath = "app-id";
|
||||
|
||||
/**
|
||||
* Network interface hint for the "MAC_ADDRESS" UserId mechanism.
|
||||
*/
|
||||
private String networkInterface = null;
|
||||
|
||||
/**
|
||||
* UserId mechanism. Can be either "MAC_ADDRESS", "IP_ADDRESS", a string or a
|
||||
* class name.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String userId = MAC_ADDRESS;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Ssl {
|
||||
|
||||
/**
|
||||
* Trust store that holds SSL certificates.
|
||||
*/
|
||||
private Resource trustStore;
|
||||
|
||||
/**
|
||||
* Password used to access the trust store.
|
||||
*/
|
||||
private String trustStorePassword;
|
||||
}
|
||||
|
||||
public enum AuthenticationMethod {
|
||||
TOKEN, APPID,
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,10 +18,10 @@ package org.springframework.cloud.vault;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Value object to bind HTTP API responses.
|
||||
*
|
||||
@@ -13,17 +13,25 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.vault;
|
||||
|
||||
/**
|
||||
* A secret backend that can return secrets from Vault.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class MyUserIdMechanism implements AppIdUserIdMechanism {
|
||||
public interface VaultSecretBackend {
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
String userId = "";
|
||||
return userId;
|
||||
}
|
||||
/**
|
||||
* Backend path.
|
||||
*
|
||||
* @return the backend path.
|
||||
*/
|
||||
String getBackend();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {@literal true} if the backend is enabled.
|
||||
*/
|
||||
boolean isEnabled();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Bootstrap Configuration
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.vault.VaultBootstrapConfiguration
|
||||
@@ -41,6 +41,11 @@ public class AppIdAuthenticationMethodsIntegrationTests extends AbstractIntegrat
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
if (!prepare().hasAuth("app-id")) {
|
||||
prepare().mountAuth("app-id");
|
||||
}
|
||||
|
||||
prepare().mapAppId("myapp");
|
||||
}
|
||||
|
||||
@@ -50,7 +55,8 @@ public class AppIdAuthenticationMethodsIntegrationTests extends AbstractIntegrat
|
||||
VaultClient vaultClient = new VaultClient(
|
||||
prepareAppIdAuthenticationMethod(AppIdProperties.IP_ADDRESS, "myapp"));
|
||||
|
||||
vaultClient.setRest(TestRestTemplateFactory.create(Settings.createVaultProperties()));
|
||||
vaultClient.setRest(
|
||||
TestRestTemplateFactory.create(Settings.createVaultProperties()));
|
||||
|
||||
vaultClient.setAppIdUserIdMechanism(new IpAddressUserId());
|
||||
assertThat(vaultClient.createToken()).isNotNull();
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.cloud.vault;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.*;
|
||||
import static org.springframework.cloud.vault.ClientHttpRequestFactoryFactory.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -42,7 +43,7 @@ public class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
@Test
|
||||
public void httpComponentsClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = ClientHttpRequestFactoryFactory
|
||||
ClientHttpRequestFactory factory = HttpComponents
|
||||
.usingHttpComponents(vaultProperties);
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
@@ -57,7 +58,7 @@ public class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
@Test
|
||||
public void nettyClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = ClientHttpRequestFactoryFactory
|
||||
ClientHttpRequestFactory factory = Netty
|
||||
.usingNetty(vaultProperties);
|
||||
((InitializingBean) factory).afterPropertiesSet();
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
@@ -73,7 +74,7 @@ public class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
@Test
|
||||
public void okHttpClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = ClientHttpRequestFactoryFactory
|
||||
ClientHttpRequestFactory factory = OkHttp
|
||||
.usingOkHttp(vaultProperties);
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
@@ -12,6 +12,6 @@ mkdir -p ${BASEDIR}/consul/data
|
||||
./consul/consul agent -server \
|
||||
-bootstrap-expect 1 \
|
||||
-data-dir ${BASEDIR}/consul/data \
|
||||
-config-file=${BASEDIR}/spring-cloud-vault-config/src/test/resources/consul.json
|
||||
-config-file=${BASEDIR}/spring-cloud-vault-core/src/test/resources/consul.json
|
||||
|
||||
exit $?
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
|
||||
BASEDIR=`dirname $0`/../../..
|
||||
|
||||
./vault/vault server -config=${BASEDIR}/spring-cloud-vault-config/src/test/resources/vault.conf
|
||||
./vault/vault server -config=${BASEDIR}/spring-cloud-vault-core/src/test/resources/vault.conf
|
||||
|
||||
exit $?
|
||||
|
||||
Reference in New Issue
Block a user