BAEL-1784 Spring Vault - Bhargava.Kotharu@gmail.com (#5094)
* 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:
parent
5a09cee678
commit
a575f7b763
1
pom.xml
1
pom.xml
|
@ -1106,6 +1106,7 @@
|
|||
<module>spring-remoting</module>
|
||||
<module>spring-reactor</module>
|
||||
<module>spring-vertx</module>
|
||||
<module>spring-vault</module>
|
||||
<module>spring-jinq</module>
|
||||
<module>spring-rest-embedded-tomcat</module>
|
||||
<module>testing-modules/testing</module>
|
||||
|
|
|
@ -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>
|
|
@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
vault.uri=https://localhost:8200
|
||||
vault.token=00000000-0000-0000-0000-000000000000
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue