Vault KV Secrets Deployment

Deploy HashiCorp Vault KV v2 secrets engine for enterprise secrets management, integrating with the existing dsec system for secure credential bootstrapping.

Vault KV + dsec Integration Architecture

Prerequisites

  • Vault cluster operational on vault-01.inside.domusdigitalis.dev / vault-02.inside.domusdigitalis.dev

  • dsec secrets loaded: dsource d000 dev/vault

  • SSH access to Vault nodes (password or certificate)

  • Root token available for initial setup

Document Description

PKI Strategy

Dual-PKI architecture with root/intermediate CAs

dsec to Vault Migration

8-phase migration plan from dsec to Vault KV

Vault SSH CA

Certificate-based SSH authentication

Vault PKI Cert Issuance

Issuing certificates from Vault PKI

Architecture Overview

Vault Cluster

Node IP Port Role

vault-01.inside.domusdigitalis.dev

10.50.1.60

8200

Primary (Raft leader)

vault-02.inside.domusdigitalis.dev

10.50.1.61

8200

Standby (Raft follower)

Secrets Engines

Engine Mount Path Purpose

KV v2

/kv/

Application secrets, API credentials

PKI

/pki_int/

Intermediate CA for client certificates

Transit

/transit/

Encryption as a service

SSH

/ssh/

SSH certificate authority

Phase 1: Load Bootstrap Credentials

Load Vault Environment from dsec

dsource d000 dev/vault
Expected Output
✓ Loaded d000/dev/vault (12 vars)

Verify Environment Variables

env | grep VAULT
Expected Variables
VAULT_ROOT_TOKEN=<set>
VAULT_UNSEAL_KEY_1=<set>
VAULT_UNSEAL_KEY_2=<set>
VAULT_UNSEAL_KEY_3=<set>
VAULT_PKI_INT_PATH=<set>
...

Phase 2: Connect to Vault

Set Vault Address

export VAULT_ADDR="https://vault-01.inside.domusdigitalis.dev:8200"

SSH to Vault Primary

ssh evanusmodestus@vault-01.inside.domusdigitalis.dev

Check Vault Status

vault status
Expected Output (Unsealed)
Key                      Value
---                      -----
Seal Type                shamir
Initialized              true
Sealed                   false
Total Shares             3
Threshold                2
Version                  1.15.x
Cluster Name             vault-cluster
HA Enabled               true
HA Cluster               https://vault-01:8201
HA Mode                  active

If Sealed: Unseal Vault

If Vault shows Sealed: true, unseal with 2 of 3 keys:

vault operator unseal "$VAULT_UNSEAL_KEY_1"
vault operator unseal "$VAULT_UNSEAL_KEY_2"

Authenticate with Root Token

vault login "$VAULT_ROOT_TOKEN"

Phase 3: Enable KV v2 Secrets Engine

Check Existing Mounts

vault secrets list

Enable KV Engine

vault secrets enable -path=kv -version=2 kv
Expected Output
Success! Enabled the kv secrets engine at: kv/

Verify Mount

vault secrets list | grep kv
Expected Output
kv/           kv           key/value secret storage

Phase 4: Create KV Path Structure

Infrastructure Secrets

Store API credentials for network infrastructure:

vault kv put kv/domus/infrastructure/ise \
  api_host="10.50.1.20" \
  description="ISE ERS API credentials"
vault kv put kv/domus/infrastructure/vyos \
  api_host="10.50.1.1" \
  description="VyOS router credentials"
vault kv put kv/domus/infrastructure/freeipa \
  host="freeipa-01.inside.domusdigitalis.dev" \
  bind_dn="uid=admin,cn=users,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev" \
  description="FreeIPA LDAP bind credentials"

Server Secrets

Per-server credentials:

vault kv put kv/domus/servers/ise-01 \
  hostname="ise-01.inside.domusdigitalis.dev" \
  ip="10.50.1.20" \
  description="ISE primary admin node"
vault kv put kv/domus/servers/vault-01 \
  hostname="vault-01.inside.domusdigitalis.dev" \
  ip="10.50.1.60" \
  description="Vault primary / Certificate Manager"
vault kv put kv/domus/servers/keycloak-01 \
  hostname="keycloak-01.inside.domusdigitalis.dev" \
  ip="10.50.1.80" \
  description="Keycloak IdP"

Application Secrets

Configuration for automation tools:

vault kv put kv/domus/applications/netapi \
  vault_backend="enabled" \
  description="netapi CLI configuration"

Verify Structure

vault kv list kv/domus/
Expected Output
Keys
====
applications/
infrastructure/
servers/

Phase 5: Create Access Policies

Infrastructure Read-Only Policy

vault policy write infra-readonly - <<'EOF'
path "kv/data/domus/infrastructure/*" {
  capabilities = ["read", "list"]
}

path "kv/metadata/domus/infrastructure/*" {
  capabilities = ["list"]
}
EOF

Full KV Admin Policy

vault policy write kv-admin - <<'EOF'
path "kv/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}
EOF

netapi Service Policy

vault policy write netapi-service - <<'EOF'
path "kv/data/domus/infrastructure/ise" {
  capabilities = ["read"]
}

path "kv/data/domus/infrastructure/vyos" {
  capabilities = ["read"]
}

path "transit/encrypt/netapi-key" {
  capabilities = ["update"]
}

path "transit/decrypt/netapi-key" {
  capabilities = ["update"]
}
EOF

Verify Policies

vault policy list
Expected Output
default
infra-readonly
kv-admin
netapi-service
root

Phase 6: Configure AppRole Authentication

Enable AppRole Auth Method

vault auth enable approle

Create netapi AppRole

vault write auth/approle/role/netapi \
  secret_id_ttl=720h \
  token_ttl=1h \
  token_max_ttl=4h \
  token_policies="netapi-service"

Get Role ID

vault read auth/approle/role/netapi/role-id
Example Output
Key        Value
---        -----
role_id    abc12345-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Generate Secret ID

vault write -f auth/approle/role/netapi/secret-id
Example Output
Key                   Value
---                   -----
secret_id             def67890-xxxx-xxxx-xxxx-xxxxxxxxxxxx
secret_id_accessor    xxx-xxx-xxx

Store AppRole Credentials in dsec

dsec edit d000/dev/vault

Add the following lines:

VAULT_APPROLE_ROLE_ID=<role-id-from-above>
VAULT_APPROLE_SECRET_ID=<secret-id-from-above>

Phase 7: Verify Access

Test KV Read

vault kv get kv/domus/infrastructure/ise

Test KV List

vault kv list kv/domus/infrastructure
Expected Output
Keys
====
freeipa
ise
vyos

Test AppRole Login

vault write auth/approle/login \
  role_id="$VAULT_APPROLE_ROLE_ID" \
  secret_id="$VAULT_APPROLE_SECRET_ID"
Expected Output
Key                     Value
---                     -----
token                   hvs.XXXXXXXXXXXX
token_accessor          xxx
token_duration          1h
token_renewable         true
token_policies          ["default" "netapi-service"]

dsec Integration Pattern

Bootstrap Flow

dsec Bootstrap Flow

Usage Pattern

# 1. Load Vault credentials from dsec
dsource d000 dev/vault

# 2. Set Vault address
export VAULT_ADDR="https://vault-01.inside.domusdigitalis.dev:8200"

# 3a. Admin operations (root token)
vault login "$VAULT_ROOT_TOKEN"
vault kv get kv/domus/infrastructure/ise

# 3b. Automated tools (AppRole)
VAULT_TOKEN=$(vault write -field=token auth/approle/login \
  role_id="$VAULT_APPROLE_ROLE_ID" \
  secret_id="$VAULT_APPROLE_SECRET_ID")
export VAULT_TOKEN
vault kv get kv/domus/infrastructure/ise

Phase 8: Enable Audit Logging

Enable File Audit Device

vault audit enable file file_path=/var/log/vault/audit.log

Verify Audit Device

vault audit list
Expected Output
Path     Type    Description
----     ----    -----------
file/    file    n/a

View Audit Log

sudo tail -f /var/log/vault/audit.log | jq '.request.path'

Rollback Procedure

Disable KV Engine

This permanently deletes all KV secrets. Ensure backup exists.

vault secrets disable kv

Remove Policies

vault policy delete infra-readonly
vault policy delete kv-admin
vault policy delete netapi-service

Disable AppRole

vault auth disable approle

Fallback to dsec

If Vault is unavailable, secrets remain accessible via dsec:

dsource d000 dev/network
dsource d000 dev/vault

Completion Checklist

Phase Status

Phase 1: Bootstrap

[ ] dsec loaded, environment verified

Phase 2: Connection

[ ] Vault unsealed, authenticated

Phase 3: KV Engine

[ ] KV v2 enabled at /kv/

Phase 4: Structure

[ ] infrastructure/, servers/, applications/ paths created

Phase 5: Policies

[ ] infra-readonly, kv-admin, netapi-service policies created

Phase 6: AppRole

[ ] netapi role created, credentials stored in dsec

Phase 7: Verification

[ ] KV read/list working, AppRole login successful

Phase 8: Audit

[ ] Audit logging enabled

Next Steps

  1. Configure SSH CA for certificate-based SSH access

  2. Migrate remaining dsec secrets to Vault KV

  3. Integrate netapi with Vault backend (future)

  4. Configure Kubernetes service account authentication (future)