2

I am trying to enable TLS authentication in a Vault that is deployed within a Kubernetes cluster. My goal is to be able to login to the vault using cert method as follows:

vault login \
    -method=cert \
    -ca-cert=vault-ca.pem \
    -client-cert=cert.pem \
    -client-key=key.pem \
    name=web

I first deployed the vault following this page against a minikube cluster. This page creates the vault server's public key, private key and certificate. With these three files, I assume any connection to the server will be secure. The steps I followed were as follows:

Creating a standalone TLS vault server

1. Create env variables

# 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

2. Create a private key for the vault server

openssl genrsa -out ${TMPDIR}/vault.key 2048

3. Create and deploy Certificate Signing Request

  • 3.1) Create a file csr.conf
$ 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
  • 3.2) Create the Certificate Signing request using the configuration in csr.conf
openssl req -new -key ${TMPDIR}/vault.key -subj "/CN=${SERVICE}.${NAMESPACE}.svc" -out ${TMPDIR}/server.csr -config ${TMPDIR}/csr.conf
  • 3.3) Put the Certificate Signing Request in a CertificateSigningRequest yaml for Kubernetes
$ 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

and apply it in Kubernetes

kubectl create -f ${TMPDIR}/csr.yaml
  • 3.4) Approve the Certificate Signing Request
kubectl certificate approve ${CSR_NAME}

4. Get the Vault server's Certificate

serverCert=$(kubectl get csr ${CSR_NAME} -o jsonpath='{.status.certificate}')

and put it in a file

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

5. Get Certificate Authority's certificate

kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d > ${TMPDIR}/vault.ca

 

At this stage, I have the vault server's private key vault.key, its certificate vault.crt and the CA certificate vault.ca

 

6. I can put these files into a Kubernetes secret to be used by the vault server deployment.

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

7. Finally deploy the vault server with a Helm chart and the following custom values

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"
      }
$ helm repo add hashicorp https://helm.releases.hashicorp.com
$ helm install vault hashicorp/vault --values values.yml

Authenticate with Cert

I kubectl exec into the pod vault-0 and I init and unseal the vault.

Then I try to login using the files I created. I know that they are the same as the server's files. However, since they are paired and signed, I would expecte them to work. Also, I did go into the Vault's UI and added vault.ca as the certificate to be used in TLS Acess.

$ vault login -method=cert -ca-cert=/vault/userconfig/vault-server-tls/vault.ca -client-cert=/vault/userconfig/vault-server-tls/vault.cr
t -client-key=/vault/userconfig/vault-server-tls/vault.key  

However, I get this error:

Error authenticating: Error making API request.

URL: PUT https://127.0.0.1:8200/v1/auth/cert/login
Code: 500. Errors:

* failed to verify client's certificate: x509: certificate specifies an incompatible key usage

My TLS understanding is limited. Could anyone point me into the right direction?

Ana Franco
  • 21
  • 1
  • iirc kubernetes already limit the TLS Usage for non kuberentes component, you should generate the tls outside of the kuberentes itself.. – kholisrag Aug 23 '22 at 16:36

0 Answers0