Murakami
Murakami

Reputation: 3760

Cannot run Vault UI on HTTPS via kubectl port-forward

I'm running Vault cluster in my Kubernetes cluster (AWS EKS). It seems to be working. I've initialized and unsealed it. When I'm trying to use UI via kubectl port-forward service/vault 8200:8200 and enter it through https://localhost:8200 it says that Client sent an HTTP request to an HTTPS server. When inspecting vault pods logs I'm getting: http: TLS handshake error from 127.0.0.1:38678: remote error: tls: unknown certificate. Could you help me with that one?

My Vault config:

resource "helm_release" "vault" {
  name       = "vault"
  namespace  = kubernetes_namespace.vault.id
  chart      = "vault"
  repository = "https://helm.releases.hashicorp.com"
  version    = "0.22.0"

  values = [
    <<EOF
global:
  tlsDisable: false
ui:
  enabled: true
server:
  extraEnvironmentVars:
    VAULT_CACERT: /vault/userconfig/vault-server-tls/vault.ca
  extraVolumes:
    - type: secret
      name: vault-server-tls
  nodeSelector: |
    eks.amazonaws.com/nodegroup: "vault-${var.environment}"
  tolerations:
    - key: "nodegroup"
      operator: "Equal"
      value: "vault"
      effect: "NoSchedule"
  logLevel: "debug"
  ha:
    enabled: true
    nodes: 3
    raft:
      enabled: true
      setNodeId: true
      config: |
        ui = true

        listener "tcp" {
          tls_disable = 0
          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"
          address = "[::]:8200"
          cluster_address = "[::]:8201"
        }

        storage "raft" {
          path    = "/vault/data"
        }

        service_registration "kubernetes" {}

        seal "awskms" {
          region     = "${var.aws_region}"
          kms_key_id = "${aws_kms_key.vault.key_id}"
        }
EOF
    ,
  ]
}

The script I'm generating certs with:

#!/bin/bash -e

SERVICE=vault
SECRET_NAME=vault-server-tls
TMPDIR=/tmp
SLEEP_TIME=15
KUBECTL_INSTALLATION_URL=https://storage.googleapis.com/kubernetes-release/release/v1.23.6/bin/linux/amd64/kubectl

# Name of the CSR
echo "Name the CSR: vault-csr"
export CSR_NAME=vault-csr

# Install OpenSSL
echo "Install openssl"
yum install -y openssl 2>&1

# Install Kubernetes cli
echo "Install Kubernetes cli"
curl -o kubectl ${KUBECTL_INSTALLATION_URL}
chmod +x ./kubectl
mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin
kubectl version --short --client

# Create a private key
echo "Generate certificate Private key"
openssl genrsa -out ${TMPDIR}/vault.key 2048

# Create CSR
echo "Create CSR file"
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
DNS.5 = vault-0.vault-internal
DNS.6 = vault-1.vault-internal
DNS.7 = vault-2.vault-internal
IP.1 = 127.0.0.1
EOF

# Sign the CSR
echo "Sign the CSR"
openssl req -new -key ${TMPDIR}/vault.key -subj "/CN=${SERVICE}.${NAMESPACE}.svc" -out ${TMPDIR}/server.csr -config ${TMPDIR}/csr.conf

echo "Create a CSR Manifest file"
cat <<EOF >${TMPDIR}/csr.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: ${CSR_NAME}
spec:
  groups:
  - system:authenticated
  request: $(cat ${TMPDIR}/server.csr | base64 | tr -d '\n')
  signerName: beta.eks.amazonaws.com/app-serving
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF

echo "Create CSR from manifest file"
kubectl create -f ${TMPDIR}/csr.yaml

sleep ${SLEEP_TIME}
echo "Fetch the CSR from kubernetes"
kubectl get csr ${CSR_NAME}

# Approve Cert
echo "Approve the Certificate"
kubectl certificate approve ${CSR_NAME}

serverCert=$(kubectl get csr ${CSR_NAME} -n kubecf -o jsonpath='{.status.certificate}')
echo "${serverCert}" | openssl base64 -d -A -out ${TMPDIR}/vault.crt

echo "Fetch Kubernetes CA Certificate"
kubectl get secret -o jsonpath="{.items[?(@.type==\"kubernetes.io/service-account-token\")].data['ca\.crt']}" | base64 --decode > ${TMPDIR}/vault.ca 2>/dev/null || true

echo "Create secret containing the TLS Certificates and key"
echo 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

Upvotes: 0

Views: 1063

Answers (1)

Adiii
Adiii

Reputation: 60074

you do not really need to access with https while using port-word. As the certificate is not valid for localhost.

so you can simply access it via http://localhost:8200/ui/

Or you might need to add DNS.8 = localhost as well in the certs.

Upvotes: 1

Related Questions