# Vault ## Prereqs ```bash brew tap hashicorp/tap brew install hashicorp/tap/vault brew install jq ``` ## Install (Standalone) ```bash kubectl apply -f k8s/certificate.yaml helm repo add hashicorp https://helm.releases.hashicorp.com helm search repo hashicorp/vault helm upgrade --install vault hashicorp/vault --values helm/values.yaml mkdir ~/.vault-keys kubectl exec -ti vault-0 -- vault operator init -key-shares=5 -key-threshold=3 -format=json > ~/.vault-keys/cluster-keys.json kubectl exec -ti vault-0 -- vault operator unseal ``` ## Install (Cluster) This assumes you have an unseal vault available! See ha-test for manual unseal. ```bash kubectl apply -f k8s/certificate.yaml helm repo add hashicorp https://helm.releases.hashicorp.com helm search repo hashicorp/vault helm upgrade --install vault hashicorp/vault --values helm/ha.yaml mkdir ~/.vault-keys kubectl exec -ti vault-0 -- vault operator init -format=json > ~/.vault-keys/vault-cluster-keys.json # Only run the unseal if not autounsealing # kubectl exec -ti vault-0 -- vault operator unseal kubectl exec -ti vault-1 -- vault operator raft join http://vault-0.vault-internal:8200 # kubectl exec -ti vault-1 -- vault operator unseal kubectl exec -ti vault-2 -- vault operator raft join http://vault-0.vault-internal:8200 # kubectl exec -ti vault-2 -- vault operator unseal ``` ## Add/Update policy ```bash vault policy write ducoterra policies/ducoterra.hcl ``` ## Add user ```bash vault auth enable userpass vault write auth/userpass/users/ducoterra \ policies=ducoterra \ password='' ``` ## Enable KV Secrets ```bash vault secrets enable -path=secret kv-v2 vault kv put secret/okta username='static-user' password='static-password' vault kv get secret/okta ``` ## TOTP ```bash vault secrets enable totp vault write totp/keys/okta \ url='otpauth://totp/Vault:reese.wells@nimbisservices.com?secret=SECRET&issuer=Okta' vault read totp/code/okta ``` Policy: ```bash path "totp/keys/*" { capabilities = ["update"] } path "totp/code/*" { capabilities = ["read"] } ``` ## Kubernetes Secrets ```bash kubectl exec -it vault-0 -- /bin/sh vault login -method=token vault auth enable kubernetes vault write auth/kubernetes/config \ token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \ kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt vault policy write internal-app - < ### Create a CA ```bash export ROOT_PATH=dnet # Note: 19800h is Apple's limit vault secrets enable -path=$ROOT_PATH pki vault secrets tune -max-lease-ttl=19800h $ROOT_PATH # Create a root CA vault write $ROOT_PATH/root/generate/internal \ common_name="Ducoterra Root CA" \ ttl=19800h # Create a CA URL vault write $ROOT_PATH/config/urls \ issuing_certificates="https://vault.ducoterra.net/v1/$ROOT_PATH/ca" \ crl_distribution_points="https://vault.ducoterra.net/v1/$ROOT_PATH/crl" ``` Navigate to and download the CA. Import to your devices. ### Create an intermediate CA ```bash export ROOT_PATH=dnet export PKI_PATH=dnet_inter vault secrets enable -path=$PKI_PATH pki vault secrets tune -max-lease-ttl=8760h $PKI_PATH # Create CSR to sign with root CA vault write -format=json $PKI_PATH/intermediate/generate/internal \ common_name="Ducoterra Intermediate CA" \ | jq -r '.data.csr' > certs/$PKI_PATH.csr # Sign the CSR with the root CA vault write -format=json $ROOT_PATH/root/sign-intermediate \ csr=@certs/$PKI_PATH.csr format=pem_bundle ttl=8760h \ | jq -r '.data.certificate' > certs/$PKI_PATH.cert.pem # Save the signed cert to vault vault write $PKI_PATH/intermediate/set-signed certificate=@certs/$PKI_PATH.cert.pem # Create a CA URL vault write $PKI_PATH/config/urls \ issuing_certificates="https://vault.ducoterra.net/v1/$PKI_PATH/ca" \ crl_distribution_points="https://vault.ducoterra.net/v1/$PKI_PATH/crl" ``` Navigate to and download the CA. Import to your devices. ### Allow .dnet and .hole certificates ```bash export PKI_PATH=dnet_inter # Allow .dnet subdomain vault write $PKI_PATH/roles/dnet \ allowed_domains=dnet \ allow_subdomains=true max_ttl=8760h # Allow .hole subdomain vault write $PKI_PATH/roles/pi_hole \ allowed_domains=hole \ allow_subdomains=true max_ttl=8760h ``` ### Issue a certificate ```bash export PKI_PATH=dnet_inter export CNAME=freenas.dnet # Use -format=json to dump a json file vault write $PKI_PATH/issue/dnet \ common_name=$CNAME \ max_ttl=8760h > certs/$CNAME.cert # Pihole Example vault write $PKI_PATH/issue/pi_hole \ common_name=$CNAME \ max_ttl=8760h > certs/$CNAME.cert ``` #### Adding cert to freenas Only caveat here is to paste the certificate and then the full chain cert below in the "certificate" section. iOS will infintely refresh the page if the full chain isn't provided. #### Adding cert to pihole ```bash # Paste the isser CA in here: vim /etc/ssl/certs/vault-ca.pem # Paste the certificate and private key in here: vim /etc/ssl/certs/pihole.pem # Make sure lighttpd is configured correctly vim /etc/lighttpd/external.conf # Restart the service service lighttpd restart ``` #### Adding cert to cloudkey **THIS DOESN'T WORK** ```bash service unifi stop # Remove the UNIFI_SSL_KEYSTORE=/etc/ssl/private/unifi.keystore.jks line from config cp /etc/default/unifi /etc/default/unifi.back vim /etc/default/unifi # Remove the keystore reference mv /usr/lib/unifi/data/keystore /usr/lib/unifi/data/keystore.back # Copy your primary SSL Certificate into /etc/ssl/private/cloudkey.crt cp /etc/ssl/private/cloudkey.crt /etc/ssl/private/cloudkey.crt.back vim /etc/ssl/private/cloudkey.crt # Copy your private key into /etc/ssl/private/cloudkey.key cp /etc/ssl/private/cloudkey.key /etc/ssl/private/cloudkey.key.back vim /etc/ssl/private/cloudkey.key # Add the CA to /etc/ssl/private/vault-ca.pem vim /etc/ssl/private/vault-ca.pem # Generate the key bundle openssl pkcs12 -export -in /etc/ssl/private/cloudkey.crt -inkey \ /etc/ssl/private/cloudkey.key -out /etc/ssl/private/cloudkey.p12 \ -name unifi -CAfile /etc/ssl/private/vault-ca.pem -caname vault -password pass:temppass # Import to keystore # Default password is "aircontrolenterprise" keytool -importkeystore -deststorepass aircontrolenterprise \ -destkeypass aircontrolenterprise -destkeystore /usr/lib/unifi/data/keystore \ -srckeystore /etc/ssl/private/cloudkey.p12 -srcstoretype PKCS12 -srcstorepass temppass -alias unifi -noprompt service unifi start ``` ### Revoke a certificate ```bash export PKI_PATH=dnet_inter vault write $PKI_PATH/revoke serial_number= vault write $PKI_PATH/tidy tidy_cert_store=true tidy_revoked_certs=true ``` ### Use with cert-manager ```bash export PKI_PATH=dnet_inter vault policy write $PKI_PATH - < ### Connect to external vault ```bash # On the new server (pikube - vault) helm install vault hashicorp/vault \ --set "injector.externalVaultAddr=https://vault.ducoterra.net" VAULT_HELM_SECRET_NAME=$(kubectl get secrets --output=json | jq -r '.items[].metadata | select(.name|startswith("vault-token-")).name') TOKEN_REVIEW_JWT=$(kubectl get secret $VAULT_HELM_SECRET_NAME --output='go-template={{ .data.token }}' | base64 --decode) KUBE_CA_CERT=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.certificate-authority-data}' | base64 --decode) KUBE_HOST="https://3.14.3.104:6443" ``` ```bash # On the existing vault server export PKI_PATH=dnet_inter vault auth enable -path=pikube kubernetes vault write auth/pikube/config \ token_reviewer_jwt="$TOKEN_REVIEW_JWT" \ kubernetes_host="https://3.14.3.104:6443" \ kubernetes_ca_cert="$KUBE_CA_CERT" vault write auth/pikube/role/issuer \ bound_service_account_names=issuer \ bound_service_account_namespaces=cert-manager \ policies=$PKI_PATH \ ttl=20m ``` ### Install cert-manager ```bash kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml kubectl -n cert-manager create serviceaccount issuer export ISSUER_SECRET_REF=$(kubectl -n cert-manager get serviceaccount issuer -o json | jq -r ".secrets[].name") export PKI_PATH=dnet_inter kubectl apply -f - < ### Enable transit on vault that will do the unsealing ```bash vault secrets enable transit vault write -f transit/keys/autounseal tee policies/autounseal.hcl <> /etc/ssh/sshd_config ``` Restart the SSH service ```bash service ssh restart ``` Add signing role ```bash vault write ssh-client-signer/roles/ducoterra -<<"EOH" { "allow_user_certificates": true, "allowed_users": "*", "allowed_extensions": "permit-pty,permit-port-forwarding", "default_extensions": [ { "permit-pty": "" } ], "key_type": "ca", "default_user": "ducoterra", "ttl": "30m0s" } EOH ``` ```bash vault write ssh-client-signer/roles/pi -<<"EOH" { "allow_user_certificates": true, "allowed_users": "*", "allowed_extensions": "permit-pty,permit-port-forwarding", "default_extensions": [ { "permit-pty": "" } ], "key_type": "ca", "default_user": "pi", "ttl": "30m0s" } EOH ``` ```bash vault write ssh-client-signer/roles/rancher -<<"EOH" { "allow_user_certificates": true, "allowed_users": "*", "allowed_extensions": "permit-pty,permit-port-forwarding", "default_extensions": [ { "permit-pty": "" } ], "key_type": "ca", "default_user": "rancher", "ttl": "30m0s" } EOH ``` Sign a key ```bash export SSHUSER=pi; vault write -field=signed_key ssh-client-signer/sign/$SSHUSER public_key=@$HOME/.ssh/test_rsa.pub > ~/.ssh/test_rsa-cert.pub ``` SSH using the signed key ```bash # If you saved the signed pub as key_name"-cert.pub" then you don't need to specify the signed-cert.pub part. ssh -i signed-cert.pub -i ~/.ssh/test_rsa client # or without the cert (using default client) ssh -i ~/.ssh/test_rsa client ``` #### Server Host Signing Enable secrets engine ```bash vault secrets enable -path=ssh-host-signer ssh ``` Generate keys: ```bash vault write ssh-host-signer/config/ca generate_signing_key=true ``` Extend host key's TTL ```bash vault secrets tune -max-lease-ttl=87600h ssh-host-signer ``` Create host role ```bash vault write ssh-host-signer/roles/hostrole \ key_type=ca \ ttl=87600h \ allow_host_certificates=true \ allowed_domains="localdomains,dnet,hole,ducoterra.net" \ allow_subdomains=true ``` Sign the host's public key ```bash vault write ssh-host-signer/sign/hostrole \ cert_type=host \ public_key=@$HOME/.ssh/id_rsa.pub ``` Write the signed certificate to the ssh config on the host ```bash vault write -field=signed_key ssh-host-signer/sign/hostrole \ cert_type=host \ public_key=@$HOME/.ssh/id_rsa.pub > /etc/ssh/ssh_host_rsa_key-cert.pub ``` Assign correct permissions ```bash chmod 0640 /etc/ssh/ssh_host_rsa_key-cert.pub ``` Add to sshd_config ```bash echo HostKey /etc/ssh/ssh_host_rsa_key >> /etc/ssh/sshd_config echo HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub >> /etc/ssh/sshd_config ``` Restart the ssh service ```bash service ssh restart ``` Add certificate to client ```bash echo '@cert-authority *.ducoterra.net '$(vault read -field=public_key ssh-host-signer/config/ca) >> ~/.ssh/known_hosts ```