Skip to content

Instantly share code, notes, and snippets.

@joejulian
Last active February 2, 2018 22:04
Show Gist options
  • Save joejulian/acf80f116a66ecedaa8c573fe7e0e2fa to your computer and use it in GitHub Desktop.
Save joejulian/acf80f116a66ecedaa8c573fe7e0e2fa to your computer and use it in GitHub Desktop.
#!/bin/bash -e
# Setup a Root CA in vault
# Generate and sign an Intermediate cert
#
# Requires:
# * A running vault server already initialzed and unsealed
# * Environment variable VAULT_TOKEN is set
# * vault cli (https://www.vaultproject.io)
# * httpie (https://github.com/jkbrzt/httpie)
# * jq (https://stedolan.github.io/jq/)
#
# Note: we use httpie + jq because vault write commands aren't able to return
# formatted json for parsing
[[ "${VAULT_TOKEN}" == "" ]] && { echo "VAULT_TOKEN is not set"; exit 1; }
ROOT_PATH=${ROOT_PATH:-root_ca}
INTR_PATH=${INTR_PATH:-intermediate_clusterops}
COMPANY="${COMPANY:-CNCT}"
DOMAIN="${DOMAIN:-clusterops}"
UNDER_DOM=${DOMAIN//\./_}
USER="${USER:-testuser}"
# check dependencies
command -v vault 2> /dev/null || { echo "Please install vault (https://www.vaultproject.io)"; exit 1; }
command -v http 2> /dev/null || { echo "Please install httpie (https://github.com/jkbrzt/httpie)"; exit 1; }
command -v jq 2> /dev/null || { echo "Please install jq (https://stedolan.github.io/jq/)"; exit 1; }
#############################################################################
# Step 0: Prepare a cluster (minikube)
#############################################################################
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_ROOT_TOKEN=$(uuidgen)
minikube start
# Start vault if START_VAULT is set
if [ -n $START_VAULT ]; then
vault server -dev -dev-root-token-id="${VAULT_ROOT_TOKEN}" > /tmp/vault.log 2>&1 &
vault auth $VAULT_ROOT_TOKEN
fi
#############################################################################
# Step 1: Admin initializes Vault to issue intermediate certificates based on the cluster CA
#############################################################################
# minikube in default mode generates a CA for the cluster and client certificate in "$HOME/.minikube" directory.
cat ~/.minikube/ca.{crt,key} > clientCA.bundle
# Register the client CA generaged by minikube.
vault mount -path="${ROOT_PATH}" pki
# Set the max TTL for the root CA to 10 years
echo "Tuning root CA"
vault mount-tune -max-lease-ttl="87600h" "${ROOT_PATH}"
# Write the CA
vault write ${ROOT_PATH}/config/ca [email protected]
#############################################################################
# Step 2: Create an intermediate CA
#############################################################################
# Intermediate CAs should be created for each organization (kubernetes group)
# for this example, that's ${DOMAIN}.
# Mount the intermediate CA for the zone
echo "Creating intermediate CA"
vault mount -path=${INTR_PATH} pki
# Set the max TTL for ${DOMAIN} certs to 1 year
echo "Tuning intermediate CA"
vault mount-tune -max-lease-ttl=8760h ${INTR_PATH}
# Generate CSR for ${DOMAIN} to be signed by the root CA, the key is stored
# internally to vault
echo "Generating intermediate CSR"
http POST ${VAULT_ADDR}/v1/${INTR_PATH}/intermediate/generate/internal X-Vault-Token:$VAULT_TOKEN common_name=${DOMAIN} | jq -r .data.csr > ${UNDER_DOM}.csr
# Generate and sign the ${DOMAIN} certificate as an intermediate CA
echo "Get intermediate cert"
http POST ${VAULT_ADDR}/v1/${ROOT_PATH}/root/sign-intermediate X-Vault-Token:$VAULT_TOKEN ttl="8760h" csr=@${UNDER_DOM}.csr | jq -r .data.certificate > ${UNDER_DOM}.crt
# Add signed ${DOMAIN} certificate to intermediate CA backend
echo "Add intermediate cert"
vault write ${INTR_PATH}/intermediate/set-signed certificate=@${UNDER_DOM}.crt
# Create role for issuing ${DOMAIN} certificates
# Max lease time is 14 days
echo "Create a role for subdomain certs"
vault write ${INTR_PATH}/roles/${UNDER_DOM} allow_any_name=true organization=${DOMAIN} generate_lease=true server_flag=false lease_max="336h"
#############################################################################
# Step 3: Issue client certificates for user
#############################################################################
# issue certificate for CN:${USER} O:${DOMAIN}
http POST ${VAULT_ADDR}/v1/${INTR_PATH}/issue/${UNDER_DOM} X-Vault-Token:$VAULT_TOKEN common_name="${USER}" ttl="168h" | jq -r .data.private_key,.data.certificate,.data.issuing_ca > ${USER}_${UNDER_DOM}.pem
#############################################################################
# Step 4: Users can add their certificates to kubeconfig
#############################################################################
# Separate bundle into cert and key
cat ${USER}_${UNDER_DOM}.pem | sed -n '/certificate/,/END CERTI/p' | sed 's/certificate[ \t]*//g' > ${USER}_${UNDER_DOM}.crt
cat ${USER}_${UNDER_DOM}.pem | sed -n '/private_key /,/END RSA/p' | sed 's/private_key[ \t]*//g' > ${USER}_${UNDER_DOM}.key
# Add user in kubeconfig
kubectl config set-credentials ${USER} --client-certificate=${USER}_${UNDER_DOM}.crt --client-key=${USER}_${UNDER_DOM}.key
#################################################################retrieve the CRL in PEM format with############
# Step 4: Check if the kubeconfig works
#############################################################################
kubectl config set-context admin-context --cluster=minikube --user=${USER}
kubectl config use-context admin-context
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# minikube Ready <none> <invalid> v1.9.0
# retrieve the CRL in PEM format
http GET ${VAULT_ADDR}/v1/root_ca/crl/pem
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment