You are on page 1of 8

Hashicorp Vault

Instalar o Vault
$ sudo apt update && sudo apt install gpg

$ wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg


>/dev/null

$ gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint

$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs)


main" | sudo tee /etc/apt/sources.list.d/hashicorp.list

$ sudo apt update && sudo apt install vault

Para iniciar o Vault

$ vault server -config=config.hcl

config.hcl
ui = true
disable_mlock = true

storage "raft" {
path = "./vault/data"
node_id = "node1"
}

listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = "true"
}

api_addr = "http://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"

Após isso é necessário fazer

$ VAULT_ADDR=http://127.0.0.1:8200
$ VAULT_TOKEN=<token>

Requesitos

Hashicorp Vault 1
$ git clone https://github.com/square/certstrap $ cd
Certstrap
certstrap $ go build
Terraform $ sudo apt-get install terraform

jq $ sudo apt-get install jq

go $ sudo apt install gobuild-go

💡 Para utilizar o certstrap é necessário entrar dentro da pasta do certstrap e fazer ./certstrap

Create an offline Root CA

./certstrap init \
--organization "Test" \
--organizational-unit "Test Org" \
--country "US" \
--province "MD" \
--locality "Bethesda" \
--common-name "Testing Root" \
--path-length 2

Output:
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Created out/Testing_Root.key (encrypted by passphrase)
Created out/Testing_Root.crt
Created out/Testing_Root.crl

Inspect the offline Root CA certificate with openssl to ensure it has the expected subject

$ openssl x509 -in out/Testing_Root.crt -noout -subject -issuer

Output:
subject= /C=US/ST=DC/L=Bethesda/O=Test/OU=Test Org/CN=Testing Root
issuer= /C=US/ST=DC/L=Bethesda/O=Test/OU=Test Org/CN=Testing Root

Generate ICA1 in vault

Create main.tf file which defines vault provider.

$ cat << EOF > main.tf


provider "vault" {}

locals {
default_3y_in_sec = 94608000
default_1y_in_sec = 31536000
default_1hr_in_sec = 3600
}

EOF

Hashicorp Vault 2
Create test_org_ica1.tf file which enables and configures PKI secrets engine.

cat << EOF > test_org_ica1.tf


resource "vault_mount" "test_org_v1_ica1_v1" {
path = "test-org/v1/ica1/v1"
type = "pki"
description = "PKI engine hosting intermediate CA1 v1 for test org"
default_lease_ttl_seconds = local.default_1hr_in_sec
max_lease_ttl_seconds = local.default_3y_in_sec
}

resource "vault_pki_secret_backend_intermediate_cert_request" "test_org_v1_ica1_v1" {


depends_on = [vault_mount.test_org_v1_ica1_v1]
backend = vault_mount.test_org_v1_ica1_v1.path
type = "internal"
common_name = "Intermediate CA1 v1 "
key_type = "rsa"
key_bits = "2048"
ou = "test org"
organization = "test"
country = "US"
locality = "Bethesda"
province = "MD"
}
EOF

1. The test_org_ica1.tf file contains the code necessary to enable a new PKI endpoint for the ICA1 in Vault and to generate a
Certificate Signing Request (CSR). The CSR will be signed by the offline Root CA next.

2. First, initialize terraform; this downloads the necessary providers and initializes the backend.

$ terraform init

Initializing the backend...

Initializing provider plugins...


...snip...

Terraform has been successfully initialized!

Execute the apply command to configure Vault.

$ terraform apply

This displays the actions to be performed by Terraform

When prompted, enter yes to accept the plan and proceed with Vault configuration.

vault_mount.test_org_v1_ica1_v1: Creating...
vault_mount.test_org_v1_ica1_v1: Creation complete after 0s [id=test-org/v1/ica1/v1]
vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica1_v1: Creating...
vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica1_v1: Creation complete after 0s [id=test-org/v1/ica1/v1/intermediate/g

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Hashicorp Vault 3
Create a new csr folder.

$ mkdir csr

Get the ICA1 CSR from the Terraform state file and store it under a new csr folder.

$ terraform show -json | jq '.values["root_module"]["resources"][].values.csr' -r | grep -v null > csr/Test_Org_v1_ICA1_v1.csr

Sign ICA1 CSR with the offline Root CA.

./certstrap sign \
--expires "3 year" \
--csr csr/Test_Org_v1_ICA1_v1.csr \
--cert out/Intermediate_CA1_v1.crt \
--intermediate \
--CA "Testing Root" \
"Intermediate CA1 v1" \
--path-length 2

Output:
Enter passphrase for CA key (empty for no passphrase):
Building intermediate
Created out/Intermediate_CA1_v1.crt from out/Intermediate_CA1_v1.csr signed by out/Testing_Root.key

Create the cacerts folder to store the CA chain files that will be set on the PKI endpoints in Vault.

$ mkdir cacerts

Append offline Root CA at the end of ICA1 cert to create a CA chain under cacerts folder. You will use this to set the signed ICA1 in
Vault.

$ cat out/Intermediate_CA1_v1.crt out/Testing_Root.crt > cacerts/test_org_v1_ica1_v1.crt

Update the Terraform code to set the signed cert for ICA1 in Vault.

cat << EOF >> test_org_ica1.tf


resource "vault_pki_secret_backend_intermediate_set_signed" "test_org_v1_ica1_v1_signed_cert" {
depends_on = [vault_mount.test_org_v1_ica1_v1]
backend = vault_mount.test_org_v1_ica1_v1.path

certificate = file("\${path.module}/cacerts/test_org_v1_ica1_v1.crt")
}

EOF

Apply the Terraform changes to set the signed ICA1 in Vault.

Hashicorp Vault 4
$ terraform apply

Verify the ICA1 cert in Vault.

curl -s $VAULT_ADDR/v1/test-org/v1/ica1/v1/ca/pem | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -noout

Verify the ICA1 CA chain in Vault.

curl -s $VAULT_ADDR/v1/test-org/v1/ica1/v1/ca_chain | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -noout

Generate ICA2 in vault

Create a Terraform file named, "test_org_ica2.tf" to manage ICA2 resources in Vault.

cat << EOF > test_org_ica2.tf


resource "vault_mount" "test_org_v1_ica2_v1" {
path = "test-org/v1/ica2/v1"
type = "pki"
description = "PKI engine hosting intermediate CA2 v1 for test org"
default_lease_ttl_seconds = local.default_1hr_in_sec
max_lease_ttl_seconds = local.default_1y_in_sec
}

resource "vault_pki_secret_backend_intermediate_cert_request" "test_org_v1_ica2_v1" {


depends_on = [vault_mount.test_org_v1_ica2_v1]
backend = vault_mount.test_org_v1_ica2_v1.path
type = "internal"
common_name = "Intermediate CA2 v1 "
key_type = "rsa"
key_bits = "2048"
ou = "test org"
organization = "test"
country = "US"
locality = "Bethesda"
province = "MD"
}

resource "vault_pki_secret_backend_root_sign_intermediate" "test_org_v1_sign_ica2_v1_by_ica1_v1" {


depends_on = [
vault_mount.test_org_v1_ica1_v1,
vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica2_v1,
]
backend = vault_mount.test_org_v1_ica1_v1.path
csr = vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica2_v1.csr
common_name = "Intermediate CA2 v1.1"
exclude_cn_from_sans = true
ou = "test org"
organization = "test"
country = "US"
locality = "Bethesda"
province = "MD"
max_path_length = 1
ttl = local.default_1y_in_sec
}

resource "vault_pki_secret_backend_intermediate_set_signed" "test_org_v1_ica2_v1_signed_cert" {


depends_on = [vault_pki_secret_backend_root_sign_intermediate.test_org_v1_sign_ica2_v1_by_ica1_v1]
backend = vault_mount.test_org_v1_ica2_v1.path
certificate = format("%s\n%s", vault_pki_secret_backend_root_sign_intermediate.test_org_v1_sign_ica2_v1_by_ica1_v1.certificate, file("\${pa
}
EOF

Hashicorp Vault 5
Apply Terraform changes for ICA2.

$ terraform apply

Verify that the Terraform output displays the new ICA2 set
Verify the ICA2 cert in Vault.

$ curl -s $VAULT_ADDR/v1/test-org/v1/ica2/v1/ca/pem | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -noout

Verify the ICA2 CA chain in Vault.

$ curl -s $VAULT_ADDR/v1/test-org/v1/ica2/v1/ca_chain | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -noout

Run ICA2 x509 certificate constraint check.

$ curl -s $VAULT_ADDR/v1/test-org/v1/ica2/v1/ca/pem | openssl x509 -in /dev/stdin -noout -text | grep "X509v3 extensions" -A 13

Step 5: Issue a client x509 cert rooted in ICA2


Create a new PKI role rooted in ICA2 to issue client x509 certificates for test.com subdomains.

$ cat << EOF > test_org_ica2_role_test_dot_com.tf


resource "vault_pki_secret_backend_role" "role" {
backend = vault_mount.test_org_v1_ica2_v1.path
name = "test-dot-com-subdomain"
ttl = local.default_1hr_in_sec
allow_ip_sans = true
key_type = "rsa"
key_bits = 2048
key_usage = [ "DigitalSignature"]
allow_any_name = false
allow_localhost = false
allowed_domains = ["test.com"]
allow_bare_domains = false
allow_subdomains = true
server_flag = false
client_flag = true
no_store = true
country = ["US"]
locality = ["Bethesda"]
province = ["MD"]
}

EOF

Apply Terraform changes for ICA2.

$ terraform apply

Next, create a certificate rooted in ICA2 using Vault CLI.

$ vault write -format=json test-org/v1/ica2/v1/issue/test-dot-com-subdomain \ common_name=1.test.com | jq .data.certificate -r | openssl x

Output example:

Hashicorp Vault 6
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
7f:79:7f:87:92:26:81:37:1c:64:de:40:14:44:19:5d:b3:e6:64:16
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=MD, L=Bethesda, O=test, OU=test org, CN=Intermediate CA2 v1.1
Validity
Not Before: Sep 25 23:26:16 2021 GMT
Not After : Sep 26 00:26:45 2021 GMT
Subject: C=US, ST=MD, L=Bethesda, CN=1.test.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:c2:9b:7c:91:55:da:70:5e:72:5e:3c:aa:20:9f:
2d:c7:3c:ed:4f:5e:a7:cf:50:3b:0b:e4:4f:df:69:
34:1a:40:0d:bf:1a:6c:53:1f:f2:0d:3a:4a:83:3f:
47:16:8e:88:4c:a9:bc:be:20:22:04:c0:9b:76:52:
b1:96:a8:8e:0f:4e:36:b8:aa:4f:da:3b:1b:3b:64:
34:c6:c8:e5:c2:2a:da:a1:e4:3c:0d:13:f3:e5:8c:
a4:b1:d5:37:11:d0:99:70:b0:37:5a:f1:4a:e9:5a:
e3:09:ba:db:d9:ee:59:a3:94:ee:b4:97:85:3b:a4:
0a:0d:31:c9:91:09:7e:66:de:01:10:fd:1e:dd:89:
b9:65:e9:9d:c6:aa:c6:11:b8:c4:eb:06:e6:c3:ac:
6c:b4:1b:65:e9:29:bb:c7:26:84:fb:52:0e:07:bd:
da:c2:37:5d:d2:21:4c:a9:7f:51:c4:61:03:bc:06:
a8:9e:18:0c:2b:8b:7b:9a:0d:30:d0:7e:2e:14:72:
6b:0b:55:c3:68:51:6c:3b:9d:87:46:0a:3d:7b:77:
a9:48:06:96:ed:af:2d:25:f4:28:eb:5b:13:ac:61:
22:8a:c8:a7:99:eb:d1:1c:41:3d:4b:e6:2e:16:f3:
56:7e:b6:38:ac:07:b1:66:4c:5f:f2:65:2c:36:1b:
91:1d
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Subject Key Identifier:
1B:A5:58:99:2E:0E:42:48:B3:8F:C4:D4:6D:E5:91:C2:5B:48:13:57
X509v3 Authority Key Identifier:
keyid:7A:AF:49:89:C6:BC:F1:5D:F4:A9:3A:79:66:CD:CA:E4:36:7E:78:64

X509v3 Subject Alternative Name:


DNS:1.test.com
Signature Algorithm: sha256WithRSAEncryption
7a:c2:1d:47:8e:5b:92:c6:6b:5b:28:8e:a6:29:64:1a:ea:bd:
c3:0f:4b:c1:37:8c:61:78:b8:1c:d9:2a:9c:aa:33:00:40:f2:
14:3a:ae:b6:ec:9e:d3:aa:ea:9f:50:15:9b:03:0c:30:9b:6d:
f1:79:47:77:d2:1c:ff:bf:ee:8c:70:b1:c6:15:65:4c:e4:76:
d1:b8:cd:27:68:ec:e8:dd:41:b1:50:bd:0a:1a:16:ab:8e:aa:
6b:1f:8e:15:28:e6:51:ee:5d:c6:62:b0:cd:d7:87:cb:9b:18:
6c:c3:82:44:4a:71:f8:bb:fa:c2:88:39:d4:7b:08:e5:7e:8a:
47:ad:7b:d4:06:d7:e6:f3:d8:c9:79:83:22:b6:0a:db:10:44:
9d:1b:5c:19:73:90:f4:cf:0f:72:52:14:1d:e6:10:ef:29:91:
55:10:2d:17:f5:4a:d2:ed:85:be:37:6c:f1:75:b2:61:70:cd:
b2:ed:43:ec:bc:69:60:87:99:57:ca:69:2c:76:b8:8e:26:46:
c2:a2:ad:ff:a7:99:04:8a:d4:58:dd:99:53:6f:3f:10:1f:52:
24:6d:af:e0:a8:a8:eb:62:10:f8:1c:5c:99:13:43:55:d9:a1:
53:34:62:60:e6:fd:aa:49:30:58:18:5e:aa:c4:51:50:50:ac:
d6:df:4f:b1

Fim

Exemplo para cyberlab

resource "vault_mount" "cyberlab_local_v1_ica2_v1" {


path = "cyberlab-local/v1/ica2/v1"
type = "pki"

Hashicorp Vault 7
description = "PKI engine hosting intermediate CA2 v1 for cyberlab local"
default_lease_ttl_seconds = local.default_10hr_in_sec
max_lease_ttl_seconds = local.default_1y_in_sec
}

resource "vault_pki_secret_backend_intermediate_cert_request" "cyberlab_local_v1_ica2_v1" {


depends_on = [vault_mount.cyberlab_local_v1_ica2_v1]
backend = vault_mount.cyberlab_local_v1_ica2_v1.path
type = "internal"
common_name = "Intermediate CA2 v1 "
key_type = "rsa"
key_bits = "2048"
ou = "cyberlab local"
organization = "cyberlab"
country = "PT"
locality = "Lisbon"
province = "PT"
}

resource "vault_pki_secret_backend_root_sign_intermediate" "cyberlab_local_v1_sign_ica2_v1_by_ica1_v1" {


depends_on = [
vault_mount.cyberlab_local_v1_ica1_v1,
vault_pki_secret_backend_intermediate_cert_request.cyberlab_local_v1_ica2_v1,
]
backend = vault_mount.cyberlab_local_v1_ica1_v1.path
csr = vault_pki_secret_backend_intermediate_cert_request.cyberlab_local_v1_ica2_v1.csr
common_name = "Intermediate CA2 v1.1"
exclude_cn_from_sans = true
ou = "cyberlab local"
organization = "cyberlab"
country = "PT"
locality = "Lisbon"
province = "PT"
max_path_length = 1
ttl = local.default_1y_in_sec
}

resource "vault_pki_secret_backend_intermediate_set_signed" "cyberlab_local_v1_ica2_v1_signed_cert" {


depends_on = [vault_pki_secret_backend_root_sign_intermediate.cyberlab_local_v1_sign_ica2_v1_by_ica1_v1]
backend = vault_mount.cyberlab_local_v1_ica2_v1.path
certificate = format("%s\n%s", vault_pki_secret_backend_root_sign_intermediate.cyberlab_local_v1_sign_ica2_v1_by_ica1_v1.certificate, file(
}
EOF

Hashicorp Vault 8

You might also like