Last active
December 20, 2023 12:50
-
-
Save kawsark/bb533eb25724e78b708cdcc02bc05e9e to your computer and use it in GitHub Desktop.
Vault Agent with PKI certificate rendering
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Configure variables | |
These variables will be used for this snippet. Please substitute accordingly. | |
```bash | |
export RootCAName="root_ca" | |
export InterCAName="inter_ca" | |
export CommonName="hashidemos.io" | |
export InterCommonName="inter.hashidemos.io" | |
export Root_CA_ttl="730h" | |
export Inter_CA_ttl="350h" | |
export Cert_ttl="8h" | |
``` | |
### PKI Secrets engine setup | |
```bash | |
## Go to working directory | |
mkdir -p /tmp/certs && cd /tmp/certs | |
# Mount Root CA and generate certs: | |
vault secrets disable ${RootCAName} | |
vault secrets enable -path ${RootCAName} pki | |
vault secrets tune -max-lease-ttl=${Root_CA_ttl} ${RootCAName} | |
# Generate Root key and certs | |
vault write -format=json ${RootCAName}/root/generate/internal \ | |
common_name="${CommonName}" ttl=${Inter_CA_ttl} | tee \ | |
>(jq -r .data.certificate > /tmp/certs/ca.pem) \ | |
>(jq -r .data.issuing_ca > /tmp/certs/issuing_ca.pem) | |
# Mount Intermediate CA and generate CSR: | |
vault secrets disable ${InterCAName} | |
vault secrets enable -path ${InterCAName} pki | |
vault secrets tune -max-lease-ttl=${Inter_CA_ttl} ${InterCAName} | |
vault write -format=json ${InterCAName}/intermediate/generate/internal \ | |
common_name="${CommonName}" ttl=${Inter_CA_ttl} | tee \ | |
>(jq -r .data.csr > /tmp/certs/${InterCAName}.csr) | |
vault write -format=json ${RootCAName}/root/sign-intermediate \ | |
csr=@/tmp/certs/${InterCAName}.csr \ | |
common_name="${CommonName}" ttl=${CA_ttl} | tee \ | |
>(jq -r .data.certificate > /tmp/certs/${InterCAName}.pem) \ | |
>(jq -r .data.issuing_ca > /tmp/certs/${InterCAName}_issuing_ca.pem) | |
vault write ${InterCAName}/intermediate/set-signed certificate=@/tmp/certs/${InterCAName}.pem | |
# Write URLs | |
vault write ${InterCAName}/config/urls \ | |
issuing_certificates="http://127.0.0.1:8200/v1/${InterCAName}/ca" \ | |
crl_distribution_points="http://127.0.0.1:8200/v1/${InterCAName}/crl" \ | |
ocsp_servers="http://127.0.0.1:8200/v1/${InterCAName}/ocsp" | |
# Generate certificate for dev.hashidemos.io domain: | |
role_name=app1 | |
prefix=dev | |
vault write ${InterCAName}/roles/${role_name} \ | |
allowed_domains="${prefix}.${CommonName}" \ | |
allow_subdomains="true" \ | |
max_ttl=${Cert_ttl} \ | |
generate_lease=true | |
# Verify | |
vault read ${InterCAName}/roles/${role_name} | |
## Test | |
# Generate a certificate with lease | |
vault write ${InterCAName}/issue/${role_name} common_name=app1.${prefix}.${CommonName} | |
# Generate a certificate with no lease | |
vault write ${InterCAName}/roles/${role_name}-no-lease \ | |
allowed_domains="${prefix}.${CommonName}" \ | |
allow_subdomains="true" \ | |
max_ttl=${Cert_ttl} | |
vault write ${InterCAName}/issue/${role_name}-no-lease common_name=app1.${prefix}.${CommonName} | |
``` | |
### AppRole and Vault Agent configuration | |
```bash | |
## Setup AppRole and policy | |
mkdir -p /tmp/certs | |
cat <<EOF > /tmp/certs/cert.policy | |
path "${InterCAName}/issue*" { | |
capabilities = ["create","update"] | |
} | |
path "auth/token/renew" { | |
capabilities = ["update"] | |
} | |
path "auth/token/renew-self" { | |
capabilities = ["update"] | |
} | |
EOF | |
vault policy write cert-policy /tmp/certs/cert.policy | |
vault token create -policy=cert-policy | |
vault auth enable approle | |
vault write auth/approle/role/cert-role token_policies="cert-policy" secret_id_ttl=24h token_ttl=5m token_max_ttl=4h | |
vault read -format=json auth/approle/role/cert-role/role-id > role.json | |
vault write -format=json -f auth/approle/role/cert-role/secret-id > secretid.json | |
export ROLE_ID="$(cat role.json | jq -r .data.role_id )" && echo $ROLE_ID | tee roleid | |
export SECRET_ID="$(cat secretid.json | jq -r .data.secret_id )" && echo $SECRET_ID |tee secretid | |
## Test | |
export VAULT_TOKEN=$(vault write -format=json auth/approle/login role_id=$ROLE_ID secret_id=$SECRET_ID | jq -r .auth.client_token) | |
vault write -format=json ${InterCAName}/issue/${role_name} \ | |
common_name=app1.${prefix}.${CommonName} ttl=5m | |
## Write template files | |
# https://github.com/hashicorp/vault-k8s/issues/21 | |
cat <<TPL > dynamic-cert.tpl | |
{{ with secret "${InterCAName}/issue/${role_name}" "common_name=nginx.${prefix}.${CommonName}" "ttl=5m" }} | |
{{ .Data.certificate }} | |
{{ end }} | |
TPL | |
## Vault Agent with a source and destination | |
cat <<EOF > vault-agent.hcl | |
pid_file = "./pidfile" | |
vault { | |
address = "http://127.0.0.1:8200" | |
} | |
auto_auth { | |
method { | |
type = "approle" | |
config = { | |
role_id_file_path = "/tmp/certs/roleid" | |
secret_id_file_path = "/tmp/certs/secretid" | |
} | |
} | |
sink { | |
type = "file" | |
config = { | |
path = "/tmp/certs/token" | |
} | |
} | |
} | |
template { | |
source = "/tmp/certs/dynamic-cert.tpl" | |
destination = "/tmp/certs/app-certs.txt" | |
} | |
EOF | |
vault agent -log-level debug -config=./vault-agent.hcl | |
## Vault Agent with contents | |
cat <<EOF > vault-agent-contents.hcl | |
pid_file = "./pidfile" | |
vault { | |
address = "http://127.0.0.1:8200" | |
} | |
auto_auth { | |
method { | |
type = "approle" | |
config = { | |
role_id_file_path = "/tmp/certs/roleid" | |
secret_id_file_path = "/tmp/certs/secretid" | |
} | |
} | |
sink { | |
type = "file" | |
config = { | |
path = "/tmp/certs/token" | |
} | |
} | |
} | |
# TLS SERVER CERTIFICATE | |
template { | |
contents = "{{ with secret \"${InterCAName}/issue/${role_name}\" \"common_name=nginx.${prefix}.${CommonName}\" \"ttl=1m\" }}{{ .Data.certificate }}{{ end }}" | |
destination = "/tmp/certs/nginx.${prefix}.${CommonName}.crt" | |
} | |
# TLS PRIVATE KEY | |
template { | |
contents = "{{ with secret \"${InterCAName}/issue/${role_name}\" \"common_name=nginx.${prefix}.${CommonName}\" \"ttl=1m\" }} {{ .Data.private_key }}{{ end }}" | |
destination = "/tmp/certs/nginx.${prefix}.${CommonName}.key" | |
} | |
# TLS CA CERTIFICATE | |
template { | |
contents = "{{ with secret \"${InterCAName}/issue/${role_name}\" \"common_name=nginx.${prefix}.${CommonName}\" \"ttl=1m\" }} {{ .Data.issuing_ca }}{{ end }}" | |
destination = "/tmp/certs/ca.crt" | |
} | |
EOF | |
vault agent -log-level debug -config=./vault-agent-contents.hcl |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment