Skip to content

Add setup for kmip (Hashicorp Vault) #400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 179 additions & 0 deletions vault-kmip-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#!/usr/bin/env bash
set -euo pipefail

# Base directory under $HOME
VAULT_BASE="${HOME}/vault"
CONFIG_DIR="${VAULT_BASE}/config"
DATA_DIR="${VAULT_BASE}/data"
LOG_DIR="${VAULT_BASE}/log"
CERTS_DIR="${VAULT_BASE}/certs"
VAULT_HCL="${CONFIG_DIR}/vault.hcl"
VAULT_LICENSE="${CONFIG_DIR}/vault.hclic"
CONTAINER_NAME="vault-enterprise"

# Create all necessary directories
mkdir -p "${CONFIG_DIR}" "${DATA_DIR}" "${LOG_DIR}" "${CERTS_DIR}"

# Ensure license file exists
if [[ ! -f "${VAULT_LICENSE}" ]]; then
echo "[ERROR] Vault license file not found at ${VAULT_LICENSE}"
exit 1
fi

create_vault_hcl() {
if [[ -f "${VAULT_HCL}" ]]; then
echo "Vault HCL config already exists at ${VAULT_HCL}"
return 0
fi

echo "Creating Vault HCL config at ${VAULT_HCL}"
cat > "${VAULT_HCL}" <<EOF
# vault.hcl autogenerated
storage "raft" {
path = "/vault/data"
node_id = "node1"
}

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

cluster_addr = "http://vault.example.com:8201"
api_addr = "http://vault.example.com:8200"
disable_mlock = true

log_level = "trace"
log_format = "json"
log_file = "/vault/log/vault.log"
EOF
}

start_vault_container() {
echo "Launching Vault container..."
docker run -d \
--name "${CONTAINER_NAME}" \
--cap-add IPC_LOCK \
-p 8200:8200 \
-p 8201:8201 \
-p 5696:5696 \
-v "${VAULT_BASE}:/vault" \
-e "VAULT_LICENSE=$(<"${VAULT_LICENSE}")" \
hashicorp/vault-enterprise:latest \
vault server -config=/vault/config/vault.hcl

echo "Vault container started"
}

initialize_vault() {
local init_file="${CERTS_DIR}/init_token.json"

if [[ -f "${init_file}" ]]; then
echo "[INFO] Vault already initialized at ${init_file}"
else
echo "[INFO] Initializing Vault..."
docker exec "${CONTAINER_NAME}" apk add --no-cache jq >/dev/null

docker exec "${CONTAINER_NAME}" sh -c '
export VAULT_ADDR="http://127.0.0.1:8200"
vault operator init -format=json > /vault/certs/init_token.json
' || {
echo "[ERROR] Vault initialization failed"
return 1
}
echo "[INFO] Vault initialized."
fi

echo "[INFO] Unsealing Vault..."

for i in {0..2}; do
local unseal_key
unseal_key=$(docker exec "${CONTAINER_NAME}" jq -r ".unseal_keys_b64[${i}]" /vault/certs/init_token.json)
docker exec "${CONTAINER_NAME}" sh -c "export VAULT_ADDR='http://127.0.0.1:8200' && vault operator unseal '${unseal_key}'" >/dev/null || {
echo "[ERROR] Failed to unseal with key ${i}"
return 1
}
done

echo "[INFO] Vault unsealed successfully"
}

configure_kmip() {
local root_token
root_token=$(docker exec "${CONTAINER_NAME}" \
jq -rM '.root_token' /vault/certs/init_token.json)

echo "Configuring KMIP secrets engine"
docker exec "${CONTAINER_NAME}" sh -c "
export VAULT_ADDR='http://127.0.0.1:8200' VAULT_TOKEN='${root_token}'
set -e

if ! vault secrets list | grep -q kmip/; then
vault secrets enable kmip
fi

vault write kmip/config \
tls_ca_key_type='rsa' \
tls_ca_key_bits=2048 \
listen_addrs='0.0.0.0:5696' \
server_hostnames='172.17.0.1'

vault read -field=ca_pem kmip/ca > /vault/certs/vault-kmip-ca.pem
vault write -f kmip/scope/my-service
vault write kmip/scope/my-service/role/admin \
operation_all=true \
tls_client_key_bits=2048 \
tls_client_key_type=rsa \
tls_client_ttl=24h

vault write -format=json kmip/scope/my-service/role/admin/credential/generate \
format=pem > /vault/certs/credential.json

jq -r '.data.certificate' /vault/certs/credential.json > /vault/certs/mysql-client-cert.pem
jq -r '.data.private_key' /vault/certs/credential.json > /vault/certs/mysql-client-key.pem
"
}

verify_kmip_connection() {
echo "Verifying KMIP connection..."
local output
output=$(docker exec "${CONTAINER_NAME}" sh -c \
"openssl s_client -connect 127.0.0.1:5696 \
-CAfile /vault/certs/vault-kmip-ca.pem \
-cert /vault/certs/mysql-client-cert.pem \
-key /vault/certs/mysql-client-key.pem < /dev/null 2>/dev/null" | head -20)

if ! grep -q "Verification: OK" <<< "${output}"; then
echo "KMIP connection verification failed"
return 1
fi
echo "KMIP connection verified successfully"
}

main() {
create_vault_hcl
start_vault_container
initialize_vault
configure_kmip
verify_kmip_connection

echo "Vault Enterprise deployment successful"

# JSON output
jq -n \
--arg server_addr "127.0.0.1" \
--arg server_port "5696" \
--arg client_ca "${CERTS_DIR}/mysql-client-cert.pem" \
--arg client_key "${CERTS_DIR}/mysql-client-key.pem" \
--arg server_ca "${CERTS_DIR}/vault-kmip-ca.pem" \
'{
server_addr: $server_addr,
server_port: $server_port,
client_ca: $client_ca,
client_key: $client_key,
server_ca: $server_ca
}' | jq '.'
}

main "$@"