Hi,
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?