»Standalone Server with TLS

This example can be used to set up a single server Vault cluster using TLS.

  1. Create key & certificate using Kubernetes CA
  2. Store key & cert into Kubernetes secrets store
  3. Configure helm chart to use Kubernetes secret from step 2

»1. Create key & certificate using Kubernetes CA

There are three variables that will be used in this example.

# SERVICE is the name of the Vault service in Kubernetes.
# It does not have to match the actual running service, though it may help for consistency.
SERVICE=vault-server-tls

# NAMESPACE where the Vault service is running.
NAMESPACE=vault-namespace

# SECRET_NAME to create in the Kubernetes secrets store.
SECRET_NAME=vault-server-tls

# TMPDIR is a temporary working directory.
TMPDIR=/tmp
# SERVICE is the name of the Vault service in Kubernetes.# It does not have to match the actual running service, though it may help for consistency.SERVICE=vault-server-tls
# NAMESPACE where the Vault service is running.NAMESPACE=vault-namespace
# SECRET_NAME to create in the Kubernetes secrets store.SECRET_NAME=vault-server-tls
# TMPDIR is a temporary working directory.TMPDIR=/tmp
  1. Create a key for Kubernetes to sign.

    openssl genrsa -out ${TMPDIR}/vault.key 2048
    
    openssl genrsa -out ${TMPDIR}/vault.key 2048
  2. Create a Certificate Signing Request (CSR).

    1. Create a file ${TMPDIR}/csr.conf with the following contents:

      $ cat <<EOF >${TMPDIR}/csr.conf
      [req]
      req_extensions = v3_req
      distinguished_name = req_distinguished_name
      [req_distinguished_name]
      [ v3_req ]
      basicConstraints = CA:FALSE
      keyUsage = nonRepudiation, digitalSignature, keyEncipherment
      extendedKeyUsage = serverAuth
      subjectAltName = @alt_names
      [alt_names]
      DNS.1 = ${SERVICE}
      DNS.2 = ${SERVICE}.${NAMESPACE}
      DNS.3 = ${SERVICE}.${NAMESPACE}.svc
      DNS.4 = ${SERVICE}.${NAMESPACE}.svc.cluster.local
      IP.1 = 127.0.0.1
      EOF
      
      $ cat <<EOF >${TMPDIR}/csr.conf[req]req_extensions = v3_reqdistinguished_name = req_distinguished_name[req_distinguished_name][ v3_req ]basicConstraints = CA:FALSEkeyUsage = nonRepudiation, digitalSignature, keyEnciphermentextendedKeyUsage = serverAuthsubjectAltName = @alt_names[alt_names]DNS.1 = ${SERVICE}DNS.2 = ${SERVICE}.${NAMESPACE}DNS.3 = ${SERVICE}.${NAMESPACE}.svcDNS.4 = ${SERVICE}.${NAMESPACE}.svc.cluster.localIP.1 = 127.0.0.1EOF
    2. Create a CSR.

      openssl req -new -key ${TMPDIR}/vault.key -subj "/CN=${SERVICE}.${NAMESPACE}.svc" -out ${TMPDIR}/server.csr -config ${TMPDIR}/csr.conf
      
      openssl req -new -key ${TMPDIR}/vault.key -subj "/CN=${SERVICE}.${NAMESPACE}.svc" -out ${TMPDIR}/server.csr -config ${TMPDIR}/csr.conf
  3. Create the certificate

    1. Create a file ${TMPDIR}/csr.yaml with the following contents:

      $ export CSR_NAME=vault-csr
      $ cat <<EOF >${TMPDIR}/csr.yaml
      apiVersion: certificates.k8s.io/v1beta1
      kind: CertificateSigningRequest
      metadata:
        name: ${CSR_NAME}
      spec:
        groups:
        - system:authenticated
        request: $(cat ${TMPDIR}/server.csr | base64 | tr -d '\n')
        usages:
        - digital signature
        - key encipherment
        - server auth
      EOF
      
      $ export CSR_NAME=vault-csr$ cat <<EOF >${TMPDIR}/csr.yamlapiVersion: certificates.k8s.io/v1beta1kind: CertificateSigningRequestmetadata:  name: ${CSR_NAME}spec:  groups:  - system:authenticated  request: $(cat ${TMPDIR}/server.csr | base64 | tr -d '\n')  usages:  - digital signature  - key encipherment  - server authEOF
    2. Send the CSR to Kubernetes.

      kubectl create -f ${TMPDIR}/csr.yaml
      
      kubectl create -f ${TMPDIR}/csr.yaml
    3. Approve the CSR in Kubernetes.

      kubectl certificate approve ${CSR_NAME}
      
      kubectl certificate approve ${CSR_NAME}

»2. Store key, cert, and Kubernetes CA into Kubernetes secrets store

  1. Retrieve the certificate.

    serverCert=$(kubectl get csr ${CSR_NAME} -o jsonpath='{.status.certificate}')
    
    serverCert=$(kubectl get csr ${CSR_NAME} -o jsonpath='{.status.certificate}')
  2. Write the certificate out to a file.

    echo "${serverCert}" | openssl base64 -d -A -out ${TMPDIR}/vault.crt
    
    echo "${serverCert}" | openssl base64 -d -A -out ${TMPDIR}/vault.crt
  3. Retrieve Kubernetes CA.

    kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d > ${TMPDIR}/vault.ca
    
    kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d > ${TMPDIR}/vault.ca
  4. Store the key, cert, and Kubernetes CA into Kubernetes secrets.

    kubectl create secret generic ${SECRET_NAME} \
            --namespace ${NAMESPACE} \
            --from-file=vault.key=${TMPDIR}/vault.key \
            --from-file=vault.crt=${TMPDIR}/vault.crt \
            --from-file=vault.ca=${TMPDIR}/vault.ca
    
    kubectl create secret generic ${SECRET_NAME} \        --namespace ${NAMESPACE} \        --from-file=vault.key=${TMPDIR}/vault.key \        --from-file=vault.crt=${TMPDIR}/vault.crt \        --from-file=vault.ca=${TMPDIR}/vault.ca

»3. Helm Configuration

The below custom-values.yaml can be used to set up a single server Vault cluster using TLS. This assumes that a Kubernetes secret exists with the server certificate, key and certificate authority:

global:
  enabled: true
  tlsDisable: false

server:
  extraEnvironmentVars:
    VAULT_CACERT: /vault/userconfig/vault-server-tls/vault.ca

  extraVolumes:
    - type: secret
      name: vault-server-tls # Matches the ${SECRET_NAME} from above

  standalone:
    enabled: true
    config: |
      listener "tcp" {
        address = "[::]:8200"
        cluster_address = "[::]:8201"
        tls_cert_file = "/vault/userconfig/vault-server-tls/vault.crt"
        tls_key_file  = "/vault/userconfig/vault-server-tls/vault.key"
        tls_client_ca_file = "/vault/userconfig/vault-server-tls/vault.ca"
      }

      storage "file" {
        path = "/vault/data"
      }
global:  enabled: true  tlsDisable: false
server:  extraEnvironmentVars:    VAULT_CACERT: /vault/userconfig/vault-server-tls/vault.ca
  extraVolumes:    - type: secret      name: vault-server-tls # Matches the ${SECRET_NAME} from above
  standalone:    enabled: true    config: |      listener "tcp" {        address = "[::]:8200"        cluster_address = "[::]:8201"        tls_cert_file = "/vault/userconfig/vault-server-tls/vault.crt"        tls_key_file  = "/vault/userconfig/vault-server-tls/vault.key"        tls_client_ca_file = "/vault/userconfig/vault-server-tls/vault.ca"      }
      storage "file" {        path = "/vault/data"      }