716 lines
17 KiB
Markdown
716 lines
17 KiB
Markdown
# 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='<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 <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 - <<EOF
|
|
path "internal/data/database/config" {
|
|
capabilities = ["read"]
|
|
}
|
|
EOF
|
|
|
|
vault write auth/kubernetes/role/internal-app \
|
|
bound_service_account_names=internal-app \
|
|
bound_service_account_namespaces=gitlab \
|
|
policies=internal-app \
|
|
ttl=24h
|
|
|
|
rm /home/vault/.vault-token
|
|
```
|
|
|
|
Set your kube config to the namespace you want to use vault with
|
|
|
|
```bash
|
|
kubectl apply -f k8s/service-account-internal-app.yaml
|
|
```
|
|
|
|
Add secrets to your pod
|
|
|
|
```bash
|
|
spec:
|
|
template:
|
|
metadata:
|
|
annotations:
|
|
vault.hashicorp.com/agent-inject: "true"
|
|
vault.hashicorp.com/role: "internal-app"
|
|
vault.hashicorp.com/agent-inject-secret-database-config.txt: "internal/data/database/config"
|
|
```
|
|
|
|
## Gitlab Integration
|
|
|
|
### Enable JWT auth for Gitlab
|
|
|
|
```bash
|
|
# Enable jwt auth
|
|
vault auth enable jwt
|
|
|
|
# Create a policy
|
|
vault policy write myproject-production - <<EOF
|
|
# Policy name: myproject-production
|
|
#
|
|
# Read-only permission on 'secret/data/myproject/production/*' path
|
|
path "secret/data/myproject/production/*" {
|
|
capabilities = [ "read" ]
|
|
}
|
|
EOF
|
|
|
|
# Create a role
|
|
vault write auth/jwt/role/myproject-production - <<EOF
|
|
{
|
|
"role_type": "jwt",
|
|
"policies": ["myproject-production"],
|
|
"token_explicit_max_ttl": 60,
|
|
"user_claim": "user_email",
|
|
"bound_claims_type": "glob",
|
|
"bound_claims": {
|
|
"project_id": "127",
|
|
"ref_protected": "false",
|
|
"ref_type": "branch",
|
|
"ref": "main"
|
|
}
|
|
}
|
|
EOF
|
|
|
|
# Write the auth method
|
|
vault write auth/jwt/config \
|
|
jwks_url="https://gitlab.ducoterra.net/-/jwks" \
|
|
bound_issuer="gitlab.ducoterra.net"
|
|
```
|
|
|
|
### Pipeline syntax
|
|
|
|
```yaml
|
|
read_secrets:
|
|
script:
|
|
# Check job's ref name
|
|
- echo $CI_COMMIT_REF_NAME
|
|
# and is this ref protected
|
|
- echo $CI_COMMIT_REF_PROTECTED
|
|
# Vault's address can be provided here or as CI/CD variable
|
|
- export VAULT_ADDR=https://vault.ducoterra.net
|
|
# Authenticate and get token. Token expiry time and other properties can be configured
|
|
# when configuring JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
|
|
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-production jwt=$CI_JOB_JWT)"
|
|
# Now use the VAULT_TOKEN to read the secret and store it in environment variable
|
|
- export PASSWORD="$(vault kv get -field=password secret/myproject/production/db)"
|
|
# Use the secret
|
|
- echo $PASSWORD
|
|
```
|
|
|
|
## Certificate Management
|
|
|
|
<https://learn.hashicorp.com/tutorials/vault/pki-engine>
|
|
<https://learn.hashicorp.com/tutorials/vault/kubernetes-cert-manager>
|
|
|
|
### 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 <https://vault.ducoterra.net/v1/$ROOT_PATH/ca> 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 <https://vault.ducoterra.net/v1/$PKI_PATH/ca> 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=<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 - <<EOF
|
|
path "$PKI_PATH*" { capabilities = ["read", "list"] }
|
|
path "$PKI_PATH/roles/*" { capabilities = ["create", "update"] }
|
|
path "$PKI_PATH/sign/*" { capabilities = ["create", "update"] }
|
|
path "$PKI_PATH/issue/*" { capabilities = ["create"] }
|
|
EOF
|
|
|
|
vault write auth/kubernetes/role/issuer \
|
|
bound_service_account_names=issuer \
|
|
bound_service_account_namespaces=cert-manager \
|
|
policies=$PKI_PATH \
|
|
ttl=20m
|
|
|
|
kubectl -n cert-manager create serviceaccount issuer
|
|
ISSUER_SECRET_REF=$(kubectl -n cert-manager get serviceaccount issuer -o json | jq -r ".secrets[].name")
|
|
|
|
kubectl -n cert-manager apply -f - <<EOF
|
|
apiVersion: cert-manager.io/v1
|
|
kind: ClusterIssuer
|
|
metadata:
|
|
name: vault-issuer
|
|
spec:
|
|
vault:
|
|
server: https://vault.ducoterra.net
|
|
path: $PKI_PATH/sign/dnet
|
|
auth:
|
|
kubernetes:
|
|
mountPath: /v1/auth/kubernetes
|
|
role: issuer
|
|
secretRef:
|
|
name: $ISSUER_SECRET_REF
|
|
key: token
|
|
EOF
|
|
```
|
|
|
|
```yaml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
annotations:
|
|
# cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
kubernetes.io/ingress.class: nginx
|
|
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
|
nginx.org/client-max-body-size: "0"
|
|
name: {{ .Release.Name }}
|
|
spec:
|
|
rules:
|
|
- host: test.dnet
|
|
http:
|
|
paths:
|
|
- backend:
|
|
service:
|
|
name: {{ .Release.Name }}
|
|
port:
|
|
number: 80
|
|
path: /
|
|
pathType: Prefix
|
|
tls:
|
|
- hosts:
|
|
- test-dnet
|
|
secretName: test-dnet-cert
|
|
---
|
|
apiVersion: cert-manager.io/v1alpha2
|
|
kind: Certificate
|
|
metadata:
|
|
name: test-dnet
|
|
spec:
|
|
secretName: test-dnet-cert
|
|
issuerRef:
|
|
name: vault-issuer
|
|
kind: ClusterIssuer
|
|
commonName: test.dnet
|
|
dnsNames:
|
|
- test.dnet
|
|
```
|
|
|
|
## Kubernetes External Vault Auth
|
|
|
|
<https://learn.hashicorp.com/tutorials/vault/kubernetes-external-vault?in=vault/kubernetes>
|
|
|
|
### 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 - <<EOF
|
|
apiVersion: cert-manager.io/v1
|
|
kind: ClusterIssuer
|
|
metadata:
|
|
name: vault-issuer
|
|
spec:
|
|
vault:
|
|
server: https://vault.ducoterra.net
|
|
path: $PKI_PATH/sign/dnet
|
|
auth:
|
|
kubernetes:
|
|
mountPath: /v1/auth/pikube
|
|
role: issuer
|
|
secretRef:
|
|
name: $ISSUER_SECRET_REF
|
|
key: token
|
|
EOF
|
|
```
|
|
|
|
## Auto-unseal
|
|
|
|
<https://learn.hashicorp.com/tutorials/vault/autounseal-transit>
|
|
|
|
### Enable transit on vault that will do the unsealing
|
|
|
|
```bash
|
|
vault secrets enable transit
|
|
vault write -f transit/keys/autounseal
|
|
|
|
tee policies/autounseal.hcl <<EOF
|
|
path "transit/encrypt/autounseal" {
|
|
capabilities = [ "update" ]
|
|
}
|
|
|
|
path "transit/decrypt/autounseal" {
|
|
capabilities = [ "update" ]
|
|
}
|
|
EOF
|
|
|
|
vault policy write autounseal policies/autounseal.hcl
|
|
vault token create -policy="autounseal" -wrap-ttl=120
|
|
VAULT_TOKEN="wrapping token" vault unwrap
|
|
```
|
|
|
|
### Auto unseal
|
|
|
|
#### Create a test vault in a new namespace
|
|
|
|
```bash
|
|
kubectl apply -f k8s/certificate.yaml
|
|
|
|
# Get token from above output
|
|
kubectl create secret generic auto-unseal-token --from-literal=VAULT_TOKEN="token from output"
|
|
helm upgrade --install vault hashicorp/vault --values helm/ha.yaml
|
|
```
|
|
|
|
#### Test Auto Unseal
|
|
|
|
```bash
|
|
kubectl exec -it vault-0 -- vault operator init
|
|
kubectl exec -ti vault-1 -- vault operator raft join http://vault-0.vault-internal:8200
|
|
kubectl exec -ti vault-2 -- vault operator raft join http://vault-0.vault-internal:8200
|
|
```
|
|
|
|
### SSH
|
|
|
|
#### Client key signing
|
|
|
|
Enable secrets engine and generate a key
|
|
|
|
```bash
|
|
vault secrets enable -path=ssh-client-signer ssh
|
|
vault write ssh-client-signer/config/ca generate_signing_key=true
|
|
```
|
|
|
|
Retrieve the public CA (and add it to your /etc/ssh/trusted-user-ca-keys.pem) with
|
|
|
|
```bash
|
|
curl -o /etc/ssh/trusted-user-ca-keys.pem https://vault.ducoterra.net/v1/ssh-client-signer/public_key
|
|
```
|
|
|
|
Add it to your sshd_config
|
|
|
|
```bash
|
|
echo "TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem" >> /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
|
|
```
|