Skip to content

Instantly share code, notes, and snippets.

@avoidik
Forked from kawsark/vault-agent-pki
Created April 14, 2022 14:34
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avoidik/b45ca571e6e3491a26bdfb6894415d2b to your computer and use it in GitHub Desktop.
Save avoidik/b45ca571e6e3491a26bdfb6894415d2b to your computer and use it in GitHub Desktop.
Vault Agent with PKI certificate rendering

Configure variables

These variables will be used for this snippet. Please substitute accordingly.

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

## 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

## 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