* BAEL-1784 Spring Vault Initial Commit

* Added Vault Process initalizer and integration tests

* Added comments and code clean up

* Skip IntegrationTest in pom file

* Fixed failing integration test

* Code indentation
This commit is contained in:
Bhargava-Kotharu 2018-09-07 12:33:13 +05:30 committed by Predrag Maric
parent 5a09cee678
commit a575f7b763
11 changed files with 436 additions and 0 deletions

View File

@ -1106,6 +1106,7 @@
<module>spring-remoting</module> <module>spring-remoting</module>
<module>spring-reactor</module> <module>spring-reactor</module>
<module>spring-vertx</module> <module>spring-vertx</module>
<module>spring-vault</module>
<module>spring-jinq</module> <module>spring-jinq</module>
<module>spring-rest-embedded-tomcat</module> <module>spring-rest-embedded-tomcat</module>
<module>testing-modules/testing</module> <module>testing-modules/testing</module>

67
spring-vault/pom.xml Normal file
View File

@ -0,0 +1,67 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-vault</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-vault</name>
<description>Spring Vault sample project</description>
<parent>
<artifactId>parent-boot-2</artifactId>
<groupId>com.baeldung</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.vault</groupId>
<artifactId>spring-vault-core</artifactId>
<version>${spring.vault.core.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.vault.core.version>2.0.1.RELEASE</spring.vault.core.version>
</properties>
</project>

View File

@ -0,0 +1,30 @@
package org.baeldung.springvault;
public class Credentials {
private String username;
private String password;
public Credentials() {
}
public Credentials(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
@Override
public String toString() {
return "Credential [username=" + username + ", password=" + password + "]";
}
}

View File

@ -0,0 +1,50 @@
package org.baeldung.springvault;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.core.VaultTemplate;
import org.springframework.vault.core.env.VaultPropertySource;
import org.springframework.vault.support.VaultResponse;
import org.springframework.vault.support.VaultResponseSupport;
/**
* Sample service to demonstrate storing and retrieval of secrets.
*
* NOTE: We need to configure Vault and provide the Vault uri in the properties file.
*
*/
@Service
public class CredentialsService {
@Autowired
private VaultTemplate vaultTemplate;
/**
* To Secure Credentials
* @param credentials
* @return VaultResponse
* @throws URISyntaxException
*/
public void secureCredentials(Credentials credentials) throws URISyntaxException {
vaultTemplate.write("credentials/myapp", credentials);
}
/**
* To Retrieve Credentials
* @return Credentials
* @throws URISyntaxException
*/
public Credentials accessCredentials() throws URISyntaxException {
VaultResponseSupport<Credentials> response = vaultTemplate.read("credentials/myapp", Credentials.class);
return response.getData();
}
}

View File

@ -0,0 +1,17 @@
package org.baeldung.springvault;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Sample application to demonstrate basics of Spring Vault
*
*/
@SpringBootApplication
public class SpringVaultApplication {
public static void main(String[] args) {
SpringApplication.run(SpringVaultApplication.class, args);
}
}

View File

@ -0,0 +1,26 @@
package org.baeldung.springvault;
import org.springframework.context.annotation.Configuration;
import org.springframework.vault.authentication.ClientAuthentication;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.config.AbstractVaultConfiguration;
/**
* Example class to configure Vault beans using AbstractVaultConfiguration
*
*/
@Configuration
public class VaultConfig extends AbstractVaultConfiguration {
@Override
public ClientAuthentication clientAuthentication() {
return new TokenAuthentication("00000000-0000-0000-0000-000000000000");
}
@Override
public VaultEndpoint vaultEndpoint() {
return VaultEndpoint.create("host", 8020);
}
}

View File

@ -0,0 +1,21 @@
package org.baeldung.springvault;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.vault.authentication.ClientAuthentication;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.config.AbstractVaultConfiguration;
import org.springframework.vault.config.EnvironmentVaultConfiguration;
/**
* Example class to configure Vault beans using EnvironmentVaultConfiguration
*
*/
@Configuration
@PropertySource(value = { "vault-config.properties" })
@Import(value = EnvironmentVaultConfiguration.class)
public class VaultEnvironmentConfig {
}

View File

@ -0,0 +1,2 @@
vault.uri=https://localhost:8200
vault.token=00000000-0000-0000-0000-000000000000

View File

@ -0,0 +1,113 @@
package org.baeldung.springvault;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
/**
*
* This is a test class to initialize Vault.
*/
public class VaultInitializer implements Closeable {
private static final String UNSEAL_KEY = "Unseal Key:";
private static final String ROOT_TOKEN = "Root Token:";
private Process vaultProcess;
private String unSealKey;
private String rootToken;
public String getRootToken() {
return rootToken;
}
public String getUnSealKey() {
return unSealKey;
}
public static final VaultInitializer initializeValut() {
VaultInitializer vaultProcess = new VaultInitializer();
vaultProcess.start();
// Secrets is by default enabled.
vaultProcess.enableSecrets();
return vaultProcess;
}
@SuppressWarnings("unused")
private void enableSecrets() {
System.out.println("Enabling Secrets at path credentials/myapp...");
ProcessBuilder pb = new ProcessBuilder("vault", "secrets", "enable", "-path=credentials/myapp", "kv");
Map<String, String> map = pb.environment();
map.put("VAULT_ADDR", "http://127.0.0.1:8200");
try {
Process p = pb.inheritIO()
.start();
p.waitFor();
} catch (IOException e) {
System.out.println("unable to enableSecrets" + e);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void start() {
System.out.println("starting vault");
// This starts the vault server.
ProcessBuilder pb = new ProcessBuilder("vault", "server", "-dev");
try {
vaultProcess = pb.start();
// wait for initialization to complete.
Thread.sleep(5000);
} catch (IOException e) {
System.out.println("unable to start vault in new process" + e);
} catch (InterruptedException e) {
System.out.println("Thread interrupted " + e);
}
extractUnsealKeyAndToken();
}
/**
* To get the root token which is generated every time server is initialized.
*/
private void extractUnsealKeyAndToken() {
BufferedReader reader = new BufferedReader(new InputStreamReader(vaultProcess.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
boolean tokenExtracted = false;
try {
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
if (line.contains(UNSEAL_KEY)) {
String tmp = line.replace(UNSEAL_KEY, "");
unSealKey = tmp.trim();
} else if (line.contains(ROOT_TOKEN)) {
String tmp = line.replace(ROOT_TOKEN, "");
rootToken = tmp.trim();
tokenExtracted = true;
}
if (tokenExtracted)
break;
System.out.println(line);
}
} catch (IOException e) {
System.out.println("unable to read vault output" + e);
}
String result = builder.toString();
System.out.println("Unseal Key {}" + unSealKey);
System.out.println("Root Token {}" + rootToken);
System.out.println(result);
}
@Override
public void close() throws IOException {
System.out.println("stoping vault");
vaultProcess.destroy();
}
}

View File

@ -0,0 +1,80 @@
package org.baeldung.springvault;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.annotation.Order;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.core.VaultTemplate;
import org.springframework.vault.support.VaultResponse;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CredentialsService.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = VaultTestConfiguration.class, loader = AnnotationConfigContextLoader.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class VaultIntegrationTest {
@Autowired
private CredentialsService credentialsService;
/**
* Test to secure credentials.
*
* @throws URISyntaxException
*/
@Test
public void givenCredentials_whenSecureCredentials_thenCredentialsSecured() throws URISyntaxException {
try {
// Given
Credentials credentials = new Credentials("username", "password");
// When
credentialsService.secureCredentials(credentials);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Test to access credentials
* @throws URISyntaxException
*/
@Test
public void whenAccessCredentials_thenCredentialsRetrieved() throws URISyntaxException {
// Given
Credentials credentials = credentialsService.accessCredentials();
// Then
assertNotNull(credentials);
assertEquals("username", credentials.getUsername());
assertEquals("password", credentials.getPassword());
}
}

View File

@ -0,0 +1,29 @@
package org.baeldung.springvault;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.core.VaultTemplate;
@Configuration
public class VaultTestConfiguration {
@Bean
public VaultInitializer vaultInitializer() {
VaultInitializer vaultInitializer = VaultInitializer.initializeValut();
return vaultInitializer;
}
@Bean
public VaultTemplate vaultTemplate() throws URISyntaxException {
VaultInitializer vaultInitializer = vaultInitializer();
VaultTemplate vaultTemplate = new VaultTemplate(VaultEndpoint.from(new URI("http://localhost:8200")), new TokenAuthentication(vaultInitializer.getRootToken()));
return vaultTemplate;
}
}