Add support for TLS certificate authentication

We now support TLS client certificate authentication. The client needs to enable SSL and configure a keystore containing the client certificate/private key pair.

spring.cloud.vault:
    authentication: CERT
    ssl:
        key-store: classpath:keystore.jks
        key-store-password: changeit

Fixes gh-25
This commit is contained in:
Mark Paluch
2016-07-21 17:02:18 +02:00
parent 5e3eb5d047
commit 33553bf051
10 changed files with 491 additions and 59 deletions

View File

@@ -218,6 +218,37 @@ authentication method
See also: https://www.vaultproject.io/docs/auth/aws-ec2.html[Vault Documentation: Using the aws-ec2 auth backend]
=== TLS certificate authentication
The `cert` auth backend allows authentication using SSL/TLS client
certificates that are either signed by a CA or self-signed.
To enable `cert` authentication you need to:
1. Use SSL, see <<vault-client-ssl>>
2. Configure a Java `Keystore` that contains the client
certificate and the private key
3. Set the `spring.cloud.vault.authentication` to `CERT`
[source,yaml]
.bootstrap.yml
----
spring.cloud.vault:
authentication: CERT
ssl:
key-store: classpath:keystore.jks
key-store-password: changeit
cert-auth-path: cert
----
* `key-store` sets the resource for the key-store. SSL-secured Vault
communication will validate the Vault SSL certificate with the specified
trust-store.
* `key-store-password` sets the key-store password
* `cert-auth-path` sets the path of the cert authentication mount to use
See also: https://www.vaultproject.io/docs/auth/cert.html[Vault Documentation: Using the cert auth backend]
== Backends
[[vault-client-generic]]

View File

@@ -0,0 +1,102 @@
/*
* 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.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
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.cloud.vault.VaultProperties;
import org.springframework.cloud.vault.util.Settings;
import org.springframework.cloud.vault.util.VaultRule;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.cloud.vault.util.Settings.*;
import org.assertj.core.util.Files;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Integration test using config infrastructure with TLS certificate authentication. In
* case this test should fail because of SSL make sure you run the test within the
* spring-cloud-vault-config/spring-cloud-vault-config directory as the keystore is
* referenced with {@code ../work/keystore.jks}.
*
* @author Mark Paluch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = VaultConfigTlsCertAuthenticationTests.TestApplication.class)
@IntegrationTest({ "spring.cloud.vault.authentication=cert",
"spring.cloud.vault.ssl.key-store=file:../work/client-cert.jks",
"spring.cloud.vault.ssl.key-store-password=changeit",
"spring.application.name=VaultConfigTlsCertAuthenticationTests" })
public class VaultConfigTlsCertAuthenticationTests {
@BeforeClass
public static void beforeClass() throws Exception {
VaultRule vaultRule = new VaultRule();
vaultRule.before();
vaultRule.prepare().writeSecret(
VaultConfigTlsCertAuthenticationTests.class.getSimpleName(),
Collections.singletonMap("vault.value", "foo"));
VaultProperties vaultProperties = Settings.createVaultProperties();
if (!vaultRule.prepare().hasAuth(vaultProperties.getSsl().getCertAuthPath())) {
vaultRule.prepare().mountAuth(vaultProperties.getSsl().getCertAuthPath());
}
File workDir = findWorkDir();
String certificate = Files.contentOf(
new File(workDir, "ca/certs/client.cert.pem"), StandardCharsets.US_ASCII);
Map<String, String> role = new HashMap<>();
role.put("certificate", certificate);
role.put("policies", "root");
vaultRule.prepare().write("auth/cert/certs/my-role", role);
}
@Value("${vault.value}")
String configValue;
@Test
public void contextLoads() {
assertThat(configValue).isEqualTo("foo");
}
@SpringBootApplication
public static class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
}

View File

@@ -20,13 +20,13 @@ import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.springframework.cloud.vault.VaultProperties.Ssl;
import org.springframework.core.io.Resource;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
@@ -38,11 +38,15 @@ import org.springframework.util.StringUtils;
import com.squareup.okhttp.OkHttpClient;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import lombok.extern.apachecommons.CommonsLog;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
/**
* Factory for {@link ClientHttpRequestFactory} that supports Apache HTTP Components,
* OkHttp, Netty and the JDK HTTP client (in that order). This factory configures a
@@ -104,25 +108,48 @@ class ClientHttpRequestFactoryFactory {
private static SSLContext getSSLContext(VaultProperties.Ssl ssl)
throws GeneralSecurityException, IOException {
KeyManager[] keyManagers = ssl.getKeyStore() != null ? createKeyManagerFactory(
ssl.getKeyStore(), ssl.getKeyStorePassword()).getKeyManagers() : null;
TrustManager[] trustManagers = ssl.getTrustStore() != null ? createTrustManagerFactory(
ssl.getTrustStore(), ssl.getTrustStorePassword()).getTrustManagers()
: null;
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, createTrustManagerFactory(ssl.getTrustStore(),
ssl.getTrustStorePassword()).getTrustManagers(), null);
sslContext.init(keyManagers, trustManagers, null);
return sslContext;
}
private static KeyManagerFactory createKeyManagerFactory(Resource keystoreFile,
String storePassword) throws GeneralSecurityException, IOException {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream inputStream = keystoreFile.getInputStream()) {
keyStore.load(inputStream,
StringUtils.hasText(storePassword) ? storePassword.toCharArray()
: null);
}
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore,
StringUtils.hasText(storePassword) ? storePassword.toCharArray()
: new char[0]);
return keyManagerFactory;
}
private static TrustManagerFactory createTrustManagerFactory(Resource trustFile,
String storePassword) throws GeneralSecurityException, IOException {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream inputStream = trustFile.getInputStream();
try {
trustStore.load(inputStream, StringUtils.hasText(storePassword)
? storePassword.toCharArray() : null);
}
finally {
inputStream.close();
try (InputStream inputStream = trustFile.getInputStream()) {
trustStore.load(inputStream,
StringUtils.hasText(storePassword) ? storePassword.toCharArray()
: null);
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory
@@ -133,8 +160,14 @@ class ClientHttpRequestFactoryFactory {
}
private static boolean hasSslConfiguration(VaultProperties vaultProperties) {
return vaultProperties.getSsl() != null
&& vaultProperties.getSsl().getTrustStore() != null;
Ssl ssl = vaultProperties.getSsl();
if (ssl == null) {
return false;
}
return ssl.getTrustStore() != null || ssl.getKeyStore() != null;
}
/**
@@ -143,30 +176,31 @@ class ClientHttpRequestFactoryFactory {
* @author Mark Paluch
*/
static class HttpComponents {
protected static ClientHttpRequestFactory usingHttpComponents(
VaultProperties vaultProperties)
throws GeneralSecurityException, IOException {
static ClientHttpRequestFactory usingHttpComponents(
VaultProperties vaultProperties) throws GeneralSecurityException,
IOException {
HttpClientBuilder httpClientBuilder = HttpClients.custom();
if (hasSslConfiguration(vaultProperties)) {
SSLContext sslContext = getSSLContext(vaultProperties.getSsl());
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
getSSLContext(vaultProperties.getSsl()));
sslContext);
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
httpClientBuilder.setSSLContext(sslContext);
}
RequestConfig requestConfig = RequestConfig.custom() //
.setConnectTimeout(vaultProperties.getConnectionTimeout()) //
.setSocketTimeout(vaultProperties.getReadTimeout()) //
.setAuthenticationEnabled(true) //
.build();
httpClientBuilder.setDefaultRequestConfig(requestConfig);
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
httpClientBuilder.build());
return factory;
return new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
}
}
@@ -177,8 +211,7 @@ class ClientHttpRequestFactoryFactory {
*/
static class OkHttp {
protected static ClientHttpRequestFactory usingOkHttp(
VaultProperties vaultProperties)
static ClientHttpRequestFactory usingOkHttp(VaultProperties vaultProperties)
throws GeneralSecurityException, IOException {
final OkHttpClient okHttpClient = new OkHttpClient();
@@ -198,8 +231,8 @@ class ClientHttpRequestFactoryFactory {
};
if (hasSslConfiguration(vaultProperties)) {
okHttpClient.setSslSocketFactory(
getSSLContext(vaultProperties.getSsl()).getSocketFactory());
okHttpClient.setSslSocketFactory(getSSLContext(vaultProperties.getSsl())
.getSocketFactory());
}
requestFactory.setConnectTimeout(vaultProperties.getConnectionTimeout());
@@ -215,8 +248,8 @@ class ClientHttpRequestFactoryFactory {
* @author Mark Paluch
*/
static class Netty {
protected static ClientHttpRequestFactory usingNetty(
VaultProperties vaultProperties)
static ClientHttpRequestFactory usingNetty(VaultProperties vaultProperties)
throws GeneralSecurityException, IOException {
VaultProperties.Ssl ssl = vaultProperties.getSsl();
@@ -225,14 +258,21 @@ class ClientHttpRequestFactoryFactory {
if (hasSslConfiguration(vaultProperties)) {
SslContext sslContext = SslContextBuilder //
.forClient() //
.trustManager(createTrustManagerFactory(ssl.getTrustStore(),
ssl.getTrustStorePassword())) //
.sslProvider(SslProvider.JDK) //
.build();
SslContextBuilder sslContextBuilder = SslContextBuilder //
.forClient();
requestFactory.setSslContext(sslContext);
if (ssl.getTrustStore() != null) {
sslContextBuilder.trustManager(createTrustManagerFactory(
ssl.getTrustStore(), ssl.getTrustStorePassword()));
}
if (ssl.getKeyStore() != null) {
sslContextBuilder.keyManager(createKeyManagerFactory(
ssl.getKeyStore(), ssl.getKeyStorePassword()));
}
requestFactory.setSslContext(sslContextBuilder.sslProvider(
SslProvider.JDK).build());
}
requestFactory.setConnectTimeout(vaultProperties.getConnectionTimeout());

View File

@@ -16,11 +16,13 @@
package org.springframework.cloud.vault;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.springframework.http.HttpStatus;
import org.springframework.cloud.vault.VaultProperties.AuthenticationMethod;
import org.springframework.cloud.vault.VaultProperties.Ssl;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
@@ -90,6 +92,13 @@ class DefaultClientAuthentication extends ClientAuthentication {
appIdUserIdMechanism.createUserId()), appId);
}
if (properties.getAuthentication() == AuthenticationMethod.CERT
&& properties.getSsl() != null) {
log.info("Using TLS Certificate authentication to log into Vault");
return createTokenUsingTlsCertAuthentication(properties.getSsl());
}
if (properties.getAuthentication() == VaultProperties.AuthenticationMethod.AWS_EC2) {
log.info("Using AWS-EC2 authentication to log into Vault");
@@ -104,14 +113,13 @@ class DefaultClientAuthentication extends ClientAuthentication {
private VaultToken createTokenUsingAppId(AppIdTuple appIdTuple,
VaultProperties.AppIdProperties appId) {
URI uri = vaultClient.buildUri(properties,
URI uri = VaultClient.buildUri(properties,
String.format("auth/%s/login", appId.getAppIdPath()));
Map<String, String> login = getAppIdLogin(appIdTuple);
VaultClientResponse response = vaultClient.write(uri, login);
HttpStatus status = response.getStatusCode();
if (!response.isSuccessful()) {
throw new IllegalStateException(String.format(
"Cannot login using app-id: %s", response.getMessage()));
@@ -125,6 +133,26 @@ class DefaultClientAuthentication extends ClientAuthentication {
return VaultToken.of(token, body.getLeaseDuration());
}
private VaultToken createTokenUsingTlsCertAuthentication(Ssl ssl) {
URI uri = VaultClient.buildUri(properties,
String.format("auth/%s/login", ssl.getCertAuthPath()));
VaultClientResponse response = vaultClient.write(uri, Collections.emptyMap());
if (!response.isSuccessful()) {
throw new IllegalStateException(String.format(
"Cannot login using TLS certificates: %s", response.getMessage()));
}
VaultResponse body = response.getBody();
String token = (String) body.getAuth().get("client_token");
log.debug("Login successful using TLS certificates");
return VaultToken.of(token, body.getLeaseDuration());
}
private Map<String, String> getAppIdLogin(AppIdTuple appIdTuple) {
Map<String, String> login = new HashMap<>();
@@ -138,7 +166,7 @@ class DefaultClientAuthentication extends ClientAuthentication {
VaultProperties.AwsEc2Properties awsEc2 = this.properties.getAwsEc2();
URI uri = vaultClient.buildUri(this.properties,
URI uri = VaultClient.buildUri(this.properties,
String.format("auth/%s/login", awsEc2.getAwsEc2Path()));
Map<String, String> login = getEc2Login(awsEc2);

View File

@@ -150,6 +150,16 @@ public class VaultProperties {
@Data
public static class Ssl {
/**
* Trust store that holds certificates and private keys.
*/
private Resource keyStore;
/**
* Password used to access the key store.
*/
private String keyStorePassword;
/**
* Trust store that holds SSL certificates.
*/
@@ -159,9 +169,15 @@ public class VaultProperties {
* Password used to access the trust store.
*/
private String trustStorePassword;
/**
* Mount path of the TLS cert authentication backend.
*/
@NotEmpty
private String certAuthPath = "cert";
}
public enum AuthenticationMethod {
TOKEN, APPID, AWS_EC2,
TOKEN, APPID, AWS_EC2, CERT
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.cloud.vault.ClientHttpRequestFactoryFactory.Netty;
import org.springframework.cloud.vault.ClientHttpRequestFactoryFactory.OkHttp;
import org.springframework.cloud.vault.VaultProperties.AuthenticationMethod;
import org.springframework.cloud.vault.util.Settings;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.client.ClientHttpRequestFactory;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.cloud.vault.util.Settings.*;
import org.assertj.core.util.Files;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
* Integration tests for {@link VaultClient} using TLS certificate authentication using
* various HTTP clients.
*
* @author Mark Paluch
*/
public class CertAuthenticationMethodsIntegrationTests extends AbstractIntegrationTests {
@Rule
public ExpectedException expectedException = ExpectedException.none();
VaultProperties vaultProperties = prepareCertAuthenticationMethod();
@Before
public void setUp() throws Exception {
if (!prepare().hasAuth("cert")) {
prepare().mountAuth("cert");
}
File workDir = findWorkDir();
String certificate = Files.contentOf(
new File(workDir, "ca/certs/client.cert.pem"), StandardCharsets.US_ASCII);
prepare().write("auth/cert/certs/my-role",
Collections.singletonMap("certificate", certificate));
}
@Test
public void shouldAuthenticateUsingCertificateAuthenticationUsingHttpComponents()
throws Exception {
VaultClient client = new VaultClient(
TestRestTemplateFactory
.create(ClientHttpRequestFactoryFactory.HttpComponents
.usingHttpComponents(vaultProperties)));
ClientAuthentication clientAuthentication = new DefaultClientAuthentication(
vaultProperties, client);
assertThat(clientAuthentication.login()).isNotNull();
}
@Test
public void shouldAuthenticateUsingCertificateAuthenticationUsingOkHttp()
throws Exception {
ClientHttpRequestFactory factory = OkHttp.usingOkHttp(vaultProperties);
VaultClient client = new VaultClient(TestRestTemplateFactory.create(factory));
ClientAuthentication clientAuthentication = new DefaultClientAuthentication(
vaultProperties, client);
assertThat(clientAuthentication.login()).isNotNull();
((DisposableBean) factory).destroy();
}
@Test
public void shouldAuthenticateUsingCertificateAuthenticationUsingNetty()
throws Exception {
ClientHttpRequestFactory factory = Netty.usingNetty(vaultProperties);
VaultClient client = new VaultClient(TestRestTemplateFactory.create(factory));
ClientAuthentication clientAuthentication = new DefaultClientAuthentication(
vaultProperties, client);
assertThat(clientAuthentication.login()).isNotNull();
((DisposableBean) factory).destroy();
}
private VaultProperties prepareCertAuthenticationMethod() {
VaultProperties vaultProperties = Settings.createVaultProperties();
vaultProperties.setAuthentication(AuthenticationMethod.CERT);
vaultProperties.getSsl().setKeyStorePassword("changeit");
vaultProperties.getSsl().setKeyStore(
new FileSystemResource(new File(findWorkDir(), "client-cert.jks")));
return vaultProperties;
}
}

View File

@@ -21,6 +21,7 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.util.Assert;
import org.springframework.web.client.DefaultResponseErrorHandler;
import lombok.SneakyThrows;
@@ -37,23 +38,47 @@ public class TestRestTemplateFactory {
private final static AtomicReference<ClientHttpRequestFactory> factoryCache = new AtomicReference<>();
/**
* @param vaultProperties
* Create a new {@link TestRestTemplate} using the {@link VaultProperties}. The
* underlying {@link ClientHttpRequestFactory} is cached. See
* {@link #create(ClientHttpRequestFactory)} to create {@link TestRestTemplate} for a
* given {@link ClientHttpRequestFactory}.
*
* @param vaultProperties must not be {@literal null}.
* @return
*/
@SneakyThrows
public static TestRestTemplate create(VaultProperties vaultProperties) {
Assert.notNull(vaultProperties, "VaultProperties must not be null!");
initializeClientHttpRequestFactory(vaultProperties);
return create(factoryCache.get());
}
/**
* Create a new {@link TestRestTemplate} using the {@link ClientHttpRequestFactory}.
* The {@link TestRestTemplate} will throw
* {@link org.springframework.web.client.HttpStatusCodeException exceptions} in error
* cases and behave in that aspect like the regular
* {@link org.springframework.web.client.RestTemplate}.
*
* @param requestFactory must not be {@literal null}.
* @return
*/
@SneakyThrows
public static TestRestTemplate create(ClientHttpRequestFactory requestFactory) {
Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null!");
TestRestTemplate testRestTemplate = new TestRestTemplate();
testRestTemplate.setErrorHandler(new DefaultResponseErrorHandler());
testRestTemplate.setRequestFactory(factoryCache.get());
testRestTemplate.setRequestFactory(requestFactory);
return testRestTemplate;
}
private static void initializeClientHttpRequestFactory(
VaultProperties vaultProperties) throws Exception {
private static void initializeClientHttpRequestFactory(VaultProperties vaultProperties)
throws Exception {
if (factoryCache.get() != null) {
return;

View File

@@ -33,20 +33,38 @@ public class Settings {
*/
public static VaultProperties createVaultProperties() {
File workDir = findWorkDir(new File(System.getProperty("user.dir")));
File workDir = findWorkDir();
VaultProperties vaultProperties = new VaultProperties();
vaultProperties.getSsl().setTrustStorePassword("changeit");
vaultProperties.getSsl().setTrustStore(new FileSystemResource(new File(workDir, "keystore.jks")));
vaultProperties.getSsl().setTrustStore(
new FileSystemResource(new File(workDir, "keystore.jks")));
vaultProperties.setToken(token().getToken());
return vaultProperties;
}
private static File findWorkDir(File file) {
/**
* Find the {@code work} directory, starting at the {@code user.dir} directory. Search
* is performed by walking the parent directories.
* @return the {@link File} pointing to the {@code work} directory
* @throws IllegalStateException If the {@code work} directory cannot be found.
*/
public static File findWorkDir() {
return findWorkDir(new File(System.getProperty("user.dir")));
}
File searchLevel = file;
while (searchLevel.getParentFile() != null && searchLevel.getParentFile() != searchLevel) {
/**
* Find the {@code work} directory, starting at the given {@code directory}. Search
* is performed by walking the parent directories.
* @return the {@link File} pointing to the {@code work} directory
* @throws IllegalStateException If the {@code work} directory cannot be found.
*/
public static File findWorkDir(File directory) {
File searchLevel = directory;
while (searchLevel.getParentFile() != null
&& searchLevel.getParentFile() != searchLevel) {
File work = new File(searchLevel, "work");
if (work.isDirectory() && work.exists()) {
@@ -56,14 +74,16 @@ public class Settings {
searchLevel = searchLevel.getParentFile();
}
throw new IllegalStateException(
String.format("Cannot find work directory in %s or any parent directories", file.getAbsoluteFile()));
throw new IllegalStateException(String.format(
"Cannot find work directory in %s or any parent directories",
directory.getAbsoluteFile()));
}
/**
* @return the token to use during tests.
*/
public static VaultToken token() {
return VaultToken.of(System.getProperty("vault.token", "00000000-0000-0000-0000-000000000000"));
return VaultToken.of(System.getProperty("vault.token",
"00000000-0000-0000-0000-000000000000"));
}
}

View File

@@ -2,13 +2,18 @@
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
CA_DIR=work/ca
JKS_FILE=work/keystore.jks
KEYSTORE_FILE=work/keystore.jks
CLIENT_CERT_KEYSTORE=work/client-cert.jks
if [[ -d work/ca ]] ; then
rm -Rf ${CA_DIR}
fi
if [[ -f ${JKS_FILE} ]] ; then
rm -Rf ${JKS_FILE}
if [[ -f ${KEYSTORE_FILE} ]] ; then
rm -Rf ${KEYSTORE_FILE}
fi
if [[ -f ${CLIENT_CERT_KEYSTORE} ]] ; then
rm -Rf ${CLIENT_CERT_KEYSTORE}
fi
mkdir -p ${CA_DIR}/private ${CA_DIR}/certs ${CA_DIR}/crl ${CA_DIR}/csr ${CA_DIR}/newcerts ${CA_DIR}/intermediate
@@ -57,4 +62,42 @@ openssl ca -config ${DIR}/openssl.cnf \
-in ${CA_DIR}/csr/localhost.csr.pem \
-out ${CA_DIR}/certs/localhost.cert.pem
${JAVA_HOME}/bin/keytool -importcert -keystore ${JKS_FILE} -file ${CA_DIR}/certs/ca.cert.pem -noprompt -storepass changeit
echo "[INFO] Generating client auth private key"
openssl genrsa -aes256 \
-passout pass:changeit \
-out ${CA_DIR}/private/client.key.pem 2048
openssl rsa -in ${CA_DIR}/private/client.key.pem \
-out ${CA_DIR}/private/client.decrypted.key.pem \
-passin pass:changeit
chmod 400 ${CA_DIR}/private/client.key.pem
echo "[INFO] Generating client certificate request"
openssl req -config ${DIR}/openssl.cnf \
-key ${CA_DIR}/private/client.key.pem \
-passin pass:changeit \
-new -sha256 -out ${CA_DIR}/csr/client.csr.pem \
-subj "/C=NN/ST=Unknown/L=Unknown/O=spring-cloud-vault-config/CN=client"
echo "[INFO] Signing certificate request"
openssl ca -config ${DIR}/openssl.cnf \
-extensions usr_cert -days 375 -notext -md sha256 \
-passin pass:changeit \
-batch \
-in ${CA_DIR}/csr/client.csr.pem \
-out ${CA_DIR}/certs/client.cert.pem
echo "[INFO] Creating PKCS12 file with client certificate"
openssl pkcs12 -export -clcerts \
-in ${CA_DIR}/certs/client.cert.pem \
-inkey ${CA_DIR}/private/client.decrypted.key.pem \
-passout pass:changeit \
-out ${CA_DIR}/client.p12
${JAVA_HOME}/bin/keytool -importcert -keystore ${KEYSTORE_FILE} -file ${CA_DIR}/certs/ca.cert.pem -noprompt -storepass changeit
${JAVA_HOME}/bin/keytool -importkeystore \
-srckeystore ${CA_DIR}/client.p12 -srcstoretype PKCS12 -srcstorepass changeit\
-destkeystore ${CLIENT_CERT_KEYSTORE} -deststoretype JKS \
-noprompt -storepass changeit

View File

@@ -43,4 +43,4 @@ unzip ../download/${VAULT_ZIP}
chmod a+x vault
# check
./vault --version
./vault --version