Skip to content

Instantly share code, notes, and snippets.

@jjenkins70
Created January 23, 2020 19:29
Show Gist options
  • Save jjenkins70/f49bfeca41586bbe3ca23d051e041f5e to your computer and use it in GitHub Desktop.
Save jjenkins70/f49bfeca41586bbe3ca23d051e041f5e to your computer and use it in GitHub Desktop.
HashiCorp Vault TLS Certificate Auth Samples

Simple Vault TLS Certificate validation & testing

Set of scripts to deploy locally, vault and configure TLS server and user certificates for testing TLS AUTH.

credit to @reard3n (https://github.com/reard3n) and @v6 (https://github.com/v6) for the gist this grew from

Notes

This was tested using Vagrant and Ubuntu

Getting Setup

  • On the OS of your choice copy VaultCASetup.sh script locally and update any variables that would be specific to your environment and/or version of Vault you want to test against.
  • Copy vaultCAuser.sh scripts locally, also updating any variables that you want to change and run. This creates a separate user cert, signed by the initial "server" certificate created in step 1.

Start Vault

Run the following on the command line

nohup vault server -dev -config=vault.hcl > vault_verbose.log &

set up the vault CLI

export VAULT_ADDR="https://vault.testdomain.local:8500"

Save root token

TOKEN=$(grep "Root Token" vault_verbose.log | cut -c 12-)

now you can run vault login $TOKEN to login as root

Using the Certificate Authentication Methods

enable certificate authentication and upload the CA cert to vault

Enable the TLS Certificates Auth Method

vault auth enable cert

Create the "web" user certificate - simulates giving specific access to only a web app

vault write auth/cert/certs/web display_name=webcert policies=default,web [email protected] ttl=3600

Create the "app" user certificate - simulates giving specific access to only an application

vault write auth/cert/certs/app display_name=appcert policies=default,app [email protected] ttl=3600

Create Vault policies

You can either download and run create_policies.sh or copy below to create the unique policies.

Web Policy:

vault policy write web -<<EOF
path "secret/web" {
  capabilities = ["read", "create", "update"]
}
path "secret/data/web" {
  capabilities = ["read", "create", "update"]
}
EOF

App Policy:

vault policy write app -<<EOF
path "secret/app" {
  capabilities = ["read", "create", "update"]
}
path "secret/data/app" {
  capabilities = ["read", "create", "update"]
}
EOF

Confirm the policy is stored:

vault policy read web

vault policy read app

output would be similar to :

vault policy read web
path "secret/web" {
capabilities = ["read", "create", "update"]
}
path "secret/data/web" {
capabilities = ["read", "create", "update"]
}

Test and Validate

Create some secrets:

vault kv put secret/web password=webPassword

vault kv put secret/app password=appPassword

Web Auth

attempt a login using the user certificate we created above (Web)

vault login -ca-cert=certAuth.pem -method=cert -client-cert=user.crt -client-key=user.key  name=web

Investigate your token properties: vault token lookup

Try to read the web secret: vault kv get secret/web

Try to update the web secret: vault kv put secret/web password=updateWebPassword

Try to read the app secret: vault kv get secret/app (note - this should error)

Try to update the app secret: vault kv put secret/app testing=thisShouldFail

App Auth

attempt a login using the user certificate we created above (App)

vault login -ca-cert=certAuth.pem -method=cert -client-cert=user_app.crt -client-key=user_app.key name=app

Investigate your token properties: vault token lookup

Try to read the web secret: vault kv get secret/web (note - this should error)

Try to update the web secret: vault kv put secret/web password=thisShouldFail

Try to read the app secret: vault kv get secret/app

Try to update the app secret: vault kv put secret/app password=

vault login -ca-cert=certAuth.pem -method=cert -client-cert=user_app.crt -client-key=user_app.key name=app
function create_policies {
cat << EOF > web.hcl
path "secret/web" {
capabilities = ["read", "create", "update"]
}
path "secret/data/web" {
capabilities = ["read", "create", "update"]
}
EOF
cat << EOF > app.hcl
path "secret/app" {
capabilities = ["read", "create", "update"]
}
path "secret/data/app" {
capabilities = ["read", "create", "update"]
}
EOF
}
function write_policy {
vault policy write web web.hcl
vault policy write app app.hcl
}
#MAIN
create_policies
write_policy
#!/bin/bash
# Variables
#
VAULTFQDN=vault.testdomain.local
USERNAME=jjenkins
# check releases.hashicorp.com/vault/ for the OS version you need. MAC = darwin_amd64, Linux=linux_amd64, WINDOWS = windows_amd64
OSVER=linux_amd64
# Use below when +ent is top of the releases page
VAULTLATESTDIR=https://releases.hashicorp.com/vault/1.3.1/
VAULTLATESTBIN=vault_1.3.1
function download_vault {
# Pull latest version for the OS defined in OSVER
#This doesn't work when +ent is the top of the list
#####
#VAULTLATESTDIR=`curl -s https://releases.hashicorp.com/vault/ | grep href | grep -v - | grep -v "\.\." | head -n1 | awk -F"\"" '{print $2}'`
#VAULTLATESTBIN=`curl -s https://releases.hashicorp.com/vault/ | grep href | grep -v - | grep -v "\.\." | head -n1 | awk -F">" '{print $2}' | awk -F"<" '{print $1}'`
#echo "Latest version directory is $VAULTLATESTDIR"
#echo "Latest version binary is $VAULTLATESTBIN"
#FULLURL="https://releases.hashicorp.com${VAULTLATESTDIR}${VAULTLATESTBIN}_${OSVER}.zip"
#####
###
### Use below with hard coded download path
###
FULLURL="${VAULTLATESTDIR}${VAULTLATESTBIN}_${OSVER}.zip"
echo "Fetching Vault from $FULLURL"
curl ${FULLURL} > ${VAULTLATESTBIN}_${OSVER}.zip
sudo unzip -o ${VAULTLATESTBIN}_${OSVER}.zip -d /usr/local/bin
}
function create_ca_config {
# dump the contents of the Certificate Authority config file into a conf
cat << EOF > caconf.certAuth.conf
[ req ]
# Options for the req tool (man req).
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, please use SHA-2 or greater instead.
default_md = sha384
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = US
stateOrProvinceName_default = CA
localityName_default = San Francisco
0.organizationName_default = HashiCorpTesting
organizationalUnitName_default = Testing
emailAddress_default = [email protected]
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOF
# make a CA cert key and then a csr, then sign the csr
openssl genrsa -out certAuth.key 2048
openssl req -x509 -new -nodes -key certAuth.key -sha256 -days 2014 -out certAuth.pem -config caconf.certAuth.conf -extensions v3_ca -subj "/CN=JJGenericCA"
# VAULT INSTANCE CERT - generate a key and CSR
openssl req -new -newkey rsa:2048 -nodes -keyout vault.key -out vault.csr -subj "/CN=$VAULTFQDN"
cat << EOF > caconf.vault.conf
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $VAULTFQDN
EOF
# sign the vault server CSR with the CA we created above
openssl x509 -req -in vault.csr -CA certAuth.pem -CAkey certAuth.key -CAcreateserial -out vault.crt -days 365 -sha256 -extfile caconf.vault.conf
# USER IDENTIFICATION CERT - generate a key and CSR
openssl req -new -newkey rsa:2048 -nodes -keyout user.key -out user.csr -subj "/CN=$USERNAME"
cat << EOF > caconf.user.conf
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth, codeSigning, emailProtection
subjectAltName = @alt_names
[alt_names]
DNS.1 = $USERNAME
EOF
# sign the vault server CSR with the CA we created above
openssl x509 -req -in user.csr -CA certAuth.pem -CAkey certAuth.key -CAcreateserial -out user.crt -days 365 -sha256 -extfile caconf.user.conf
}
function vault_config {
cat << EOF > vault.hcl
listener "tcp" {
address = "0.0.0.0:8500"
tls_disable = false
tls_cert_file = "vault.crt"
tls_key_file = "vault.key"
tls_client_ca_file = "certAuth.pem"
tls_require_and_verify_client_cert = false
}
EOF
# Set /etc/hosts
sudo sh -c 'echo "127.0.0.1 vault.testdomain.local" >> /etc/hosts'
# Add CA to OS trusted root -- for Ubuntu
sudo mkdir /usr/local/share/ca-certificates/vault/
sudo cp vault.crt /usr/local/share/ca-certificates/vault/vault.crt
sudo update-ca-certificates
}
###
#Main
###
download_vault
create_ca_config
vault_config
#!/bin/bash
# Variables
#
VAULTFQDN=vault.testdomain.local
USERNAME=jjenkinsUser
function create_ca_config {
# USER IDENTIFICATION CERT - generate a key and CSR
openssl req -new -newkey rsa:2048 -nodes -keyout user_app.key -out user_app.csr -subj "/CN=$USERNAME"
cat << EOF > caconf.user_app.conf
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth, codeSigning, emailProtection
subjectAltName = @alt_names
[alt_names]
DNS.1 = $USERNAME
EOF
# sign the vault server CSR with the CA we created above
openssl x509 -req -in user_app.csr -CA certAuth.pem -CAkey certAuth.key -CAcreateserial -out user_app.crt -days 365 -sha256 -extfile caconf.user_app.conf
}
# MAIN
create_ca_config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment