Add support for PCF authentication.
We now support PCF authentication:
spring.cloud.vault:
authentication: PCF
pcf:
role: my-dev-role
Closes gh-354.
This commit is contained in:
68
.travis.yml
68
.travis.yml
@@ -1,68 +0,0 @@
|
||||
language: java
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
||||
- rabbitmq
|
||||
- mongodb
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- mongodb-3.0-precise
|
||||
packages:
|
||||
- mongodb-org-server
|
||||
- mongodb-org-shell
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- VAULT_VER=0.6.5
|
||||
- VAULT_VER=0.7.3
|
||||
- VAULT_VER=0.8.3
|
||||
- VAULT_VER=0.9.6
|
||||
- VAULT_VER=0.10.3
|
||||
- VAULT_VER=0.11.5
|
||||
- VAULT_VER=1.0.3
|
||||
- VAULT_VER=1.1.5
|
||||
- VAULT_VER=1.2.2
|
||||
|
||||
before_install:
|
||||
- sed -i.bak -e 's|https://nexus.codehaus.org/snapshots/|https://oss.sonatype.org/content/repositories/codehaus-snapshots/|g' ~/.m2/settings.xml
|
||||
|
||||
install:
|
||||
- mkdir -p download
|
||||
- test -f download/apache-cassandra-3.11.4-bin.tar.gz || wget https://archive.apache.org/dist/cassandra/3.11.4/apache-cassandra-3.11.4-bin.tar.gz -O download/apache-cassandra-3.11.4-bin.tar.gz
|
||||
- tar xzf download/apache-cassandra-3.11.4-bin.tar.gz
|
||||
- cp -f spring-cloud-vault-config-databases/src/test/resources/cassandra.yaml apache-cassandra-3.11.4/conf
|
||||
- apache-cassandra-3.11.4/bin/cassandra
|
||||
- src/test/bash/create_certificates.sh
|
||||
- src/test/bash/install_vault.sh
|
||||
- src/test/bash/install_consul.sh
|
||||
- src/test/bash/local_run_vault.sh &
|
||||
- src/test/bash/local_run_consul.sh &
|
||||
- sudo rabbitmq-plugins enable rabbitmq_management
|
||||
- sudo service rabbitmq-server restart
|
||||
|
||||
before_script:
|
||||
- mysql -e "CREATE USER 'springvault' IDENTIFIED by 'springvault';"
|
||||
- mysql -uroot -e "GRANT ALL PRIVILEGES ON *.* TO 'springvault'@'%' WITH GRANT OPTION;";
|
||||
- psql -U postgres -c "CREATE ROLE springvault WITH LOGIN PASSWORD 'springvault' CREATEROLE CREATEUSER;"
|
||||
- |-
|
||||
mongo admin --eval "db.createUser({user: 'springvault', pwd:'springvault', roles:['root']});"
|
||||
- sleep 30 # wait until Cassandra is up
|
||||
- apache-cassandra-3.11.4/bin/cqlsh localhost -u cassandra -p cassandra -e "CREATE USER 'springvault' WITH PASSWORD 'springvault' SUPERUSER"
|
||||
|
||||
script: mvn clean verify -Pspring,java8
|
||||
|
||||
after_script:
|
||||
- apache-cassandra-3.11.4/bin/nodetool stopdaemon
|
||||
- pkill vault
|
||||
- pkill consul
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
- 'download'
|
||||
@@ -636,6 +636,50 @@ See also:
|
||||
* https://www.vaultproject.io/docs/auth/kubernetes.html[Vault Documentation: Kubernetes]
|
||||
* https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/[Kubernetes Documentation: Configure Service Accounts for Pods]
|
||||
|
||||
[[vault.config.authentication.pcf]]
|
||||
=== Pivotal CloudFoundry authentication
|
||||
|
||||
The https://www.vaultproject.io/docs/auth/pcf.html[pcf]
|
||||
auth backend provides a secure introduction mechanism for applications running within Pivotal's CloudFoundry instances allowing automated retrieval of a Vault token.
|
||||
Unlike most Vault authentication backends, this backend does not require first-deploying, or provisioning security-sensitive credentials (tokens, username/password, client certificates, etc.) as identity provisioning is handled by PCF itself.
|
||||
Instead, it treats PCF as a Trusted Third Party and uses the managed instance identity.
|
||||
|
||||
.bootstrap.yml with required PCF Authentication properties
|
||||
====
|
||||
[source,yaml]
|
||||
----
|
||||
spring.cloud.vault:
|
||||
authentication: PCF
|
||||
pcf:
|
||||
role: my-dev-role
|
||||
----
|
||||
====
|
||||
|
||||
.bootstrap.yml with all PCF Authentication properties
|
||||
====
|
||||
[source,yaml]
|
||||
----
|
||||
spring.cloud.vault:
|
||||
authentication: PCF
|
||||
pcf:
|
||||
role: my-dev-role
|
||||
pcf-path: path
|
||||
instance-certificate: /etc/cf-instance-credentials/instance.crt
|
||||
instance-key: /etc/cf-instance-credentials/instance.key
|
||||
----
|
||||
====
|
||||
|
||||
* `role` sets the name of the role against which the login is being attempted.
|
||||
* `pcf-path` sets the path of the PCF mount to use.
|
||||
* `instance-certificate` sets the path to the PCF instance identity certificate.
|
||||
Defaults to `${CF_INSTANCE_CERT}` env variable.
|
||||
* `instance-key` sets the path to the PCF instance identity key.
|
||||
Defaults to `${CF_INSTANCE_KEY}` env variable.
|
||||
|
||||
NOTE: PCF authentication requires BouncyCastle (bcpkix-jdk15on) to be on the classpath for RSA PSS signing.
|
||||
|
||||
See also: https://www.vaultproject.io/docs/auth/pcf.html[Vault Documentation: Using the pcf auth backend]
|
||||
|
||||
[[vault.config.backends]]
|
||||
== Secret Backends
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.cloud.vault.config;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Base64;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -69,6 +68,9 @@ import org.springframework.vault.authentication.KubernetesAuthentication;
|
||||
import org.springframework.vault.authentication.KubernetesAuthenticationOptions;
|
||||
import org.springframework.vault.authentication.KubernetesServiceAccountTokenFile;
|
||||
import org.springframework.vault.authentication.MacAddressUserId;
|
||||
import org.springframework.vault.authentication.PcfAuthentication;
|
||||
import org.springframework.vault.authentication.PcfAuthenticationOptions;
|
||||
import org.springframework.vault.authentication.ResourceCredentialSupplier;
|
||||
import org.springframework.vault.authentication.StaticUserId;
|
||||
import org.springframework.vault.authentication.TokenAuthentication;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
@@ -97,6 +99,104 @@ class ClientAuthenticationFactory {
|
||||
this.externalRestOperations = externalRestOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link ClientAuthentication}.
|
||||
*/
|
||||
ClientAuthentication createClientAuthentication() {
|
||||
|
||||
switch (this.vaultProperties.getAuthentication()) {
|
||||
|
||||
case APPID:
|
||||
return appIdAuthentication(this.vaultProperties);
|
||||
|
||||
case APPROLE:
|
||||
return appRoleAuthentication(this.vaultProperties);
|
||||
|
||||
case AWS_EC2:
|
||||
return awsEc2Authentication(this.vaultProperties);
|
||||
|
||||
case AWS_IAM:
|
||||
return awsIamAuthentication(this.vaultProperties);
|
||||
|
||||
case AZURE_MSI:
|
||||
return azureMsiAuthentication(this.vaultProperties);
|
||||
|
||||
case CERT:
|
||||
return new ClientCertificateAuthentication(this.restOperations);
|
||||
|
||||
case CUBBYHOLE:
|
||||
return cubbyholeAuthentication();
|
||||
|
||||
case GCP_GCE:
|
||||
return gcpGceAuthentication(this.vaultProperties);
|
||||
|
||||
case GCP_IAM:
|
||||
return gcpIamAuthentication(this.vaultProperties);
|
||||
|
||||
case KUBERNETES:
|
||||
return kubernetesAuthentication(this.vaultProperties);
|
||||
|
||||
case PCF:
|
||||
return pcfAuthentication(this.vaultProperties);
|
||||
|
||||
case TOKEN:
|
||||
Assert.hasText(this.vaultProperties.getToken(),
|
||||
"Token (spring.cloud.vault.token) must not be empty");
|
||||
return new TokenAuthentication(this.vaultProperties.getToken());
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(
|
||||
String.format("Client authentication %s not supported",
|
||||
this.vaultProperties.getAuthentication()));
|
||||
}
|
||||
|
||||
private ClientAuthentication appIdAuthentication(VaultProperties vaultProperties) {
|
||||
|
||||
VaultProperties.AppIdProperties appId = vaultProperties.getAppId();
|
||||
Assert.hasText(appId.getUserId(),
|
||||
"UserId (spring.cloud.vault.app-id.user-id) must not be empty");
|
||||
|
||||
AppIdAuthenticationOptions authenticationOptions = AppIdAuthenticationOptions
|
||||
.builder().appId(vaultProperties.getApplicationName()) //
|
||||
.path(appId.getAppIdPath()) //
|
||||
.userIdMechanism(getClientAuthentication(appId)).build();
|
||||
|
||||
return new AppIdAuthentication(authenticationOptions, this.restOperations);
|
||||
}
|
||||
|
||||
private AppIdUserIdMechanism getClientAuthentication(
|
||||
VaultProperties.AppIdProperties appId) {
|
||||
|
||||
try {
|
||||
Class<?> userIdClass = ClassUtils.forName(appId.getUserId(), null);
|
||||
return (AppIdUserIdMechanism) BeanUtils.instantiateClass(userIdClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
|
||||
switch (appId.getUserId().toUpperCase()) {
|
||||
|
||||
case VaultProperties.AppIdProperties.IP_ADDRESS:
|
||||
return new IpAddressUserId();
|
||||
|
||||
case VaultProperties.AppIdProperties.MAC_ADDRESS:
|
||||
|
||||
if (StringUtils.hasText(appId.getNetworkInterface())) {
|
||||
try {
|
||||
return new MacAddressUserId(
|
||||
Integer.parseInt(appId.getNetworkInterface()));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return new MacAddressUserId(appId.getNetworkInterface());
|
||||
}
|
||||
}
|
||||
|
||||
return new MacAddressUserId();
|
||||
default:
|
||||
return new StaticUserId(appId.getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AppRoleAuthenticationOptions getAppRoleAuthenticationOptions(
|
||||
VaultProperties vaultProperties) {
|
||||
|
||||
@@ -156,101 +256,6 @@ class ClientAuthenticationFactory {
|
||||
return SecretId.absent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link ClientAuthentication}.
|
||||
*/
|
||||
ClientAuthentication createClientAuthentication() {
|
||||
|
||||
switch (this.vaultProperties.getAuthentication()) {
|
||||
|
||||
case APPID:
|
||||
return appIdAuthentication(this.vaultProperties);
|
||||
|
||||
case APPROLE:
|
||||
return appRoleAuthentication(this.vaultProperties);
|
||||
|
||||
case AWS_EC2:
|
||||
return awsEc2Authentication(this.vaultProperties);
|
||||
|
||||
case AWS_IAM:
|
||||
return awsIamAuthentication(this.vaultProperties);
|
||||
|
||||
case AZURE_MSI:
|
||||
return azureMsiAuthentication(this.vaultProperties);
|
||||
|
||||
case CERT:
|
||||
return new ClientCertificateAuthentication(this.restOperations);
|
||||
|
||||
case CUBBYHOLE:
|
||||
return cubbyholeAuthentication();
|
||||
|
||||
case GCP_GCE:
|
||||
return gcpGceAuthentication(this.vaultProperties);
|
||||
|
||||
case GCP_IAM:
|
||||
return gcpIamAuthentication(this.vaultProperties);
|
||||
|
||||
case KUBERNETES:
|
||||
return kubernetesAuthentication(this.vaultProperties);
|
||||
|
||||
case TOKEN:
|
||||
Assert.hasText(this.vaultProperties.getToken(),
|
||||
"Token (spring.cloud.vault.token) must not be empty");
|
||||
return new TokenAuthentication(this.vaultProperties.getToken());
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(
|
||||
String.format("Client authentication %s not supported",
|
||||
this.vaultProperties.getAuthentication()));
|
||||
}
|
||||
|
||||
private ClientAuthentication appIdAuthentication(VaultProperties vaultProperties) {
|
||||
|
||||
VaultProperties.AppIdProperties appId = vaultProperties.getAppId();
|
||||
Assert.hasText(appId.getUserId(),
|
||||
"UserId (spring.cloud.vault.app-id.user-id) must not be empty");
|
||||
|
||||
AppIdAuthenticationOptions authenticationOptions = AppIdAuthenticationOptions
|
||||
.builder().appId(vaultProperties.getApplicationName()) //
|
||||
.path(appId.getAppIdPath()) //
|
||||
.userIdMechanism(getClientAuthentication(appId)).build();
|
||||
|
||||
return new AppIdAuthentication(authenticationOptions, this.restOperations);
|
||||
}
|
||||
|
||||
private AppIdUserIdMechanism getClientAuthentication(
|
||||
VaultProperties.AppIdProperties appId) {
|
||||
|
||||
try {
|
||||
Class<?> userIdClass = ClassUtils.forName(appId.getUserId(), null);
|
||||
return (AppIdUserIdMechanism) BeanUtils.instantiateClass(userIdClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
|
||||
switch (appId.getUserId().toUpperCase()) {
|
||||
|
||||
case VaultProperties.AppIdProperties.IP_ADDRESS:
|
||||
return new IpAddressUserId();
|
||||
|
||||
case VaultProperties.AppIdProperties.MAC_ADDRESS:
|
||||
|
||||
if (StringUtils.hasText(appId.getNetworkInterface())) {
|
||||
try {
|
||||
return new MacAddressUserId(
|
||||
Integer.parseInt(appId.getNetworkInterface()));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return new MacAddressUserId(appId.getNetworkInterface());
|
||||
}
|
||||
}
|
||||
|
||||
return new MacAddressUserId();
|
||||
default:
|
||||
return new StaticUserId(appId.getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClientAuthentication appRoleAuthentication(VaultProperties vaultProperties) {
|
||||
|
||||
AppRoleAuthenticationOptions options = getAppRoleAuthenticationOptions(
|
||||
@@ -377,12 +382,7 @@ class ClientAuthenticationFactory {
|
||||
|
||||
GcpIamAuthenticationOptions options = builder.build();
|
||||
|
||||
try {
|
||||
return new GcpIamAuthentication(options, this.restOperations);
|
||||
}
|
||||
catch (IOException | GeneralSecurityException e) {
|
||||
throw new IllegalStateException("Cannot create GcpIamAuthentication", e);
|
||||
}
|
||||
return new GcpIamAuthentication(options, this.restOperations);
|
||||
}
|
||||
|
||||
private GoogleCredential getGoogleCredential(GcpIamProperties gcp)
|
||||
@@ -421,6 +421,33 @@ class ClientAuthenticationFactory {
|
||||
return new KubernetesAuthentication(options, this.restOperations);
|
||||
}
|
||||
|
||||
private ClientAuthentication pcfAuthentication(VaultProperties vaultProperties) {
|
||||
|
||||
VaultProperties.PcfProperties pcfProperties = vaultProperties.getPcf();
|
||||
|
||||
Assert.isTrue(
|
||||
ClassUtils.isPresent("org.bouncycastle.crypto.signers.PSSSigner",
|
||||
getClass().getClassLoader()),
|
||||
"BouncyCastle (bcpkix-jdk15on) must be on the classpath");
|
||||
Assert.hasText(pcfProperties.getRole(),
|
||||
"Role (spring.cloud.vault.pcf.role) must not be empty");
|
||||
|
||||
PcfAuthenticationOptions.PcfAuthenticationOptionsBuilder builder = PcfAuthenticationOptions
|
||||
.builder().role(pcfProperties.getRole()).path(pcfProperties.getPcfPath());
|
||||
|
||||
if (pcfProperties.getInstanceCertificate() != null) {
|
||||
builder.instanceCertificate(new ResourceCredentialSupplier(
|
||||
pcfProperties.getInstanceCertificate()));
|
||||
}
|
||||
|
||||
if (pcfProperties.getInstanceKey() != null) {
|
||||
builder.instanceKey(
|
||||
new ResourceCredentialSupplier(pcfProperties.getInstanceKey()));
|
||||
}
|
||||
|
||||
return new PcfAuthentication(builder.build(), this.restOperations);
|
||||
}
|
||||
|
||||
private static class AwsCredentialProvider {
|
||||
|
||||
private static AWSCredentialsProvider getAwsCredentialsProvider() {
|
||||
|
||||
@@ -111,6 +111,8 @@ public class VaultProperties implements EnvironmentAware {
|
||||
|
||||
private KubernetesProperties kubernetes = new KubernetesProperties();
|
||||
|
||||
private PcfProperties pcf = new PcfProperties();
|
||||
|
||||
private Ssl ssl = new Ssl();
|
||||
|
||||
private Config config = new Config();
|
||||
@@ -204,6 +206,10 @@ public class VaultProperties implements EnvironmentAware {
|
||||
return this.kubernetes;
|
||||
}
|
||||
|
||||
public PcfProperties getPcf() {
|
||||
return this.pcf;
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
return this.ssl;
|
||||
}
|
||||
@@ -292,6 +298,10 @@ public class VaultProperties implements EnvironmentAware {
|
||||
this.kubernetes = kubernetes;
|
||||
}
|
||||
|
||||
public void setPcf(PcfProperties pcf) {
|
||||
this.pcf = pcf;
|
||||
}
|
||||
|
||||
public void setSsl(Ssl ssl) {
|
||||
this.ssl = ssl;
|
||||
}
|
||||
@@ -313,7 +323,7 @@ public class VaultProperties implements EnvironmentAware {
|
||||
*/
|
||||
public enum AuthenticationMethod {
|
||||
|
||||
TOKEN, APPID, APPROLE, AWS_EC2, AWS_IAM, AZURE_MSI, CERT, CUBBYHOLE, GCP_GCE, GCP_IAM, KUBERNETES
|
||||
TOKEN, APPID, APPROLE, AWS_EC2, AWS_IAM, AZURE_MSI, CERT, CUBBYHOLE, GCP_GCE, GCP_IAM, KUBERNETES, PCF;
|
||||
|
||||
}
|
||||
|
||||
@@ -853,6 +863,68 @@ public class VaultProperties implements EnvironmentAware {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* PCF properties.
|
||||
*/
|
||||
public static class PcfProperties {
|
||||
|
||||
/**
|
||||
* Mount path of the Kubernetes authentication backend.
|
||||
*/
|
||||
@NotEmpty
|
||||
private String pcfPath = "pcf";
|
||||
|
||||
/**
|
||||
* Name of the role against which the login is being attempted.
|
||||
*/
|
||||
private String role = "";
|
||||
|
||||
/**
|
||||
* Path to the instance certificate (PEM). Defaults to {@code CF_INSTANCE_CERT}
|
||||
* env variable.
|
||||
*/
|
||||
private Resource instanceCertificate;
|
||||
|
||||
/**
|
||||
* Path to the instance key (PEM). Defaults to {@code CF_INSTANCE_KEY} env
|
||||
* variable.
|
||||
*/
|
||||
private Resource instanceKey;
|
||||
|
||||
public String getPcfPath() {
|
||||
return this.pcfPath;
|
||||
}
|
||||
|
||||
public void setPcfPath(String pcfPath) {
|
||||
this.pcfPath = pcfPath;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return this.role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public Resource getInstanceCertificate() {
|
||||
return this.instanceCertificate;
|
||||
}
|
||||
|
||||
public void setInstanceCertificate(Resource instanceCertificate) {
|
||||
this.instanceCertificate = instanceCertificate;
|
||||
}
|
||||
|
||||
public Resource getInstanceKey() {
|
||||
return this.instanceKey;
|
||||
}
|
||||
|
||||
public void setInstanceKey(Resource instanceKey) {
|
||||
this.instanceKey = instanceKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* SSL properties.
|
||||
*/
|
||||
|
||||
@@ -18,10 +18,14 @@ package org.springframework.cloud.vault.config;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions.RoleId;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions.SecretId;
|
||||
import org.springframework.vault.authentication.ClientAuthentication;
|
||||
import org.springframework.vault.authentication.PcfAuthentication;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
@@ -162,4 +166,21 @@ public class ClientAuthenticationFactoryUnitTests {
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSupportPcfAuthentication() {
|
||||
|
||||
VaultProperties properties = new VaultProperties();
|
||||
properties.setAuthentication(VaultProperties.AuthenticationMethod.PCF);
|
||||
properties.getPcf().setRole("my-role");
|
||||
properties.getPcf().setInstanceKey(new ClassPathResource("bootstrap.yml"));
|
||||
properties.getPcf()
|
||||
.setInstanceCertificate(new ClassPathResource("bootstrap.yml"));
|
||||
|
||||
ClientAuthentication clientAuthentication = new ClientAuthenticationFactory(
|
||||
properties, new RestTemplate(), new RestTemplate())
|
||||
.createClientAuthentication();
|
||||
|
||||
assertThat(clientAuthentication).isInstanceOf(PcfAuthentication.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,46 +1,160 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
###########################################################################
|
||||
# Download and Install Vault #
|
||||
# This script is prepared for caching of the download directory #
|
||||
###########################################################################
|
||||
|
||||
set -o errexit
|
||||
|
||||
VAULT_VER="${VAULT_VER:-1.2.2}"
|
||||
UNAME=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
VAULT_ZIP="vault_${VAULT_VER}_${UNAME}_amd64.zip"
|
||||
IGNORE_CERTS="${IGNORE_CERTS:-no}"
|
||||
EDITION="${EDITION:-oss}"
|
||||
VAULT_OSS="${VAULT_OSS:-1.2.2}"
|
||||
VAULT_ENT="${VAULT_ENT:-0.11.0}"
|
||||
UNAME=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
VERBOSE=false
|
||||
VAULT_DIRECTORY=vault
|
||||
DOWNLOAD_DIRECTORY=download
|
||||
readonly script_name="$(basename "${BASH_SOURCE[0]}")"
|
||||
|
||||
# cleanup
|
||||
mkdir -p vault
|
||||
mkdir -p download
|
||||
function say() {
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
if [[ ! -f "download/${VAULT_ZIP}" ]] ; then
|
||||
cd download
|
||||
function verbose() {
|
||||
if [[ ${VERBOSE} == true ]]; then
|
||||
echo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
# cleanup
|
||||
mkdir -p ${VAULT_DIRECTORY}
|
||||
mkdir -p ${DOWNLOAD_DIRECTORY}
|
||||
}
|
||||
|
||||
function usage() {
|
||||
cat <<EOF
|
||||
Usage: ${script_name} [OPTION]...
|
||||
Download and extract HashiCorp Vault
|
||||
Options:
|
||||
-h|--help Displays this help
|
||||
-v|--version Vault version number
|
||||
-e|--edition oss|enterprise Vault Edition
|
||||
EOF
|
||||
}
|
||||
|
||||
function parse_options() {
|
||||
local option
|
||||
while [[ $# -gt 0 ]]; do
|
||||
option="$1"
|
||||
shift
|
||||
case ${option} in
|
||||
-h | -H | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=true
|
||||
;;
|
||||
-v | --version)
|
||||
VAULT_VER="$1"
|
||||
verbose "VAULT_VER=${VAULT_VER}"
|
||||
shift
|
||||
;;
|
||||
-e | --edition)
|
||||
EDITION="$1"
|
||||
verbose "EDITION=${EDITION}"
|
||||
shift
|
||||
;;
|
||||
|
||||
*)
|
||||
script_exit "Invalid argument was provided: ${option}" 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
function unpack() {
|
||||
|
||||
cd ${VAULT_DIRECTORY}
|
||||
|
||||
if [[ -f vault ]]; then
|
||||
rm vault
|
||||
fi
|
||||
|
||||
say "Unzipping ${VAULT_FILE}..."
|
||||
verbose " unzip ../${DOWNLOAD_DIRECTORY}/${VAULT_FILE}"
|
||||
if [[ ${VERBOSE} == true ]]; then
|
||||
unzip "../${DOWNLOAD_DIRECTORY}/${VAULT_FILE}"
|
||||
else
|
||||
unzip -q "../${DOWNLOAD_DIRECTORY}/${VAULT_FILE}"
|
||||
fi
|
||||
|
||||
chmod a+x vault
|
||||
|
||||
# check
|
||||
./vault --version
|
||||
cd ..
|
||||
}
|
||||
|
||||
function download() {
|
||||
|
||||
if [[ ! -f "${DOWNLOAD_DIRECTORY}/${VAULT_FILE}" ]]; then
|
||||
cd ${DOWNLOAD_DIRECTORY}
|
||||
# install Vault
|
||||
if [[ "${IGNORE_CERTS}" == "no" ]] ; then
|
||||
echo "Downloading Vault with certs verification"
|
||||
wget "https://releases.hashicorp.com/vault/${VAULT_VER}/${VAULT_ZIP}"
|
||||
say "Downloading Vault from ${VAULT_URL}"
|
||||
|
||||
verbose "wget ${VAULT_URL} -O ${VAULT_FILE}"
|
||||
|
||||
if [[ ${VERBOSE} == true ]]; then
|
||||
wget "${VAULT_URL}" -O "${VAULT_FILE}"
|
||||
else
|
||||
echo "WARNING... Downloading Vault WITHOUT certs verification"
|
||||
wget "https://releases.hashicorp.com/vault/${VAULT_VER}/${VAULT_ZIP}" --no-check-certificate
|
||||
wget "${VAULT_URL}" -q -O "${VAULT_FILE}"
|
||||
fi
|
||||
|
||||
if [[ $? != 0 ]] ; then
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Cannot download Vault"
|
||||
exit 1
|
||||
fi
|
||||
cd ..
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
cd vault
|
||||
function download_oss() {
|
||||
|
||||
if [[ -f vault ]] ; then
|
||||
rm vault
|
||||
fi
|
||||
VAULT_VER="${VAULT_VER:-${VAULT_OSS}}"
|
||||
VAULT_ZIP="vault_${VAULT_VER}_${UNAME}_amd64.zip"
|
||||
VAULT_FILE=${VAULT_ZIP}
|
||||
VAULT_URL="https://releases.hashicorp.com/vault/${VAULT_VER}/${VAULT_ZIP}"
|
||||
|
||||
unzip ../download/${VAULT_ZIP}
|
||||
chmod a+x vault
|
||||
download
|
||||
unpack
|
||||
}
|
||||
|
||||
# check
|
||||
./vault --version
|
||||
function download_enterprise() {
|
||||
|
||||
VAULT_VER="${VAULT_VER:-${VAULT_ENT}}"
|
||||
VAULT_ZIP="vault-enterprise_${VAULT_VER}%2Bent_${UNAME}_amd64.zip"
|
||||
VAULT_FILE="vault-enterprise_${VAULT_VER}+ent_${UNAME}_amd64.zip"
|
||||
VAULT_URL="http://hc-enterprise-binaries.s3.amazonaws.com/vault/ent/${VAULT_VER}/${VAULT_ZIP}"
|
||||
|
||||
download
|
||||
unpack
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
||||
initialize
|
||||
parse_options "$@"
|
||||
|
||||
if [[ ${EDITION} == 'oss' ]]; then
|
||||
download_oss
|
||||
elif [[ ${EDITION} == 'enterprise' ]]; then
|
||||
download_enterprise
|
||||
else
|
||||
say "Ignoring edition option: ${EDITION} - oss and enterprise supported only"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user