vault: deployment manifest, some docs, backup script - expected to run
on docker host
This commit is contained in:
35
docker-30/vault/backup.md
Normal file
35
docker-30/vault/backup.md
Normal file
@@ -0,0 +1,35 @@
|
||||
## vault-cli install
|
||||
|
||||
```bash
|
||||
VAULT_VERSION="1.21.2"
|
||||
wget https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip
|
||||
unzip vault_${VAULT_VERSION}_linux_amd64.zip
|
||||
sudo mv vault /usr/local/bin/
|
||||
```
|
||||
|
||||
## minio-cli
|
||||
|
||||
```bash
|
||||
wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /tmp/minio-cli
|
||||
chmod +x /tmp/minio-cli
|
||||
sudo mv /tmp/minio-cli /usr/local/bin/minio-cli
|
||||
|
||||
minio-cli alias set synology http://192.168.0.2:9000 k8s ----proper secret here----
|
||||
|
||||
```
|
||||
|
||||
|
||||
## backup token
|
||||
|
||||
```bash
|
||||
mkdir -p /etc/vault.d/
|
||||
vault policy write backup - <<EOF
|
||||
path "sys/storage/raft/snapshot" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOF
|
||||
|
||||
vault token create -policy=backup -period=8760h -orphan > /etc/vault.d/backup-token
|
||||
chmod 600 /etc/vault.d/backup-token
|
||||
|
||||
```
|
||||
20
docker-30/vault/config.json
Normal file
20
docker-30/vault/config.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"ui": true,
|
||||
"listener": {
|
||||
"tcp": {
|
||||
"address": "0.0.0.0:8200",
|
||||
"tls_disable": "1",
|
||||
"tls_cert_file": "/vault/certs/fullchain.pem",
|
||||
"tls_key_file": "/vault/certs/privkey.pem"
|
||||
}
|
||||
},
|
||||
"backend": {
|
||||
"file": {
|
||||
"path": "/vault/data/file"
|
||||
}
|
||||
},
|
||||
"default_lease_ttl": "168h",
|
||||
"max_lease_ttl": "0h",
|
||||
"api_addr": "https://vault.hrajfrisbee.cz"
|
||||
// "api_addr": "http://0.0.0.0:8200"
|
||||
}
|
||||
20
docker-30/vault/docker-compose.yaml
Normal file
20
docker-30/vault/docker-compose.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
vault:
|
||||
image: hashicorp/vault:1.21.1
|
||||
container_name: vault
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- IPC_LOCK
|
||||
ports:
|
||||
- 8200:8200
|
||||
environment:
|
||||
- VAULT_ADDR=http://0.0.0.0:8200
|
||||
- VAULT_API_ADDR=http://0.0.0.0:8200
|
||||
- VAULT_ADDRESS=http://0.0.0.0:8200
|
||||
volumes:
|
||||
- ./data:/vault/data
|
||||
- ./config:/vault/config
|
||||
- ./logs:/vault/logs
|
||||
- ./certs:/vault/certs
|
||||
entrypoint: vault
|
||||
command: server -config=/vault/config/vault.json -log-level=debug
|
||||
38
docker-30/vault/readme.md
Normal file
38
docker-30/vault/readme.md
Normal file
@@ -0,0 +1,38 @@
|
||||
## deployment notes
|
||||
|
||||
There was a problem with "production" deployment of Vault through docker container, because default `docker-entrypoint.sh` adds argument saying where dev instance is supposed to listen and then vault crashes because it tries to listen on same port twice.
|
||||
|
||||
Solution: override default entrypoint
|
||||
|
||||
```bash
|
||||
# vault helpers
|
||||
alias set-vault="export VAULT_ADDR=https://docker-30:8200"
|
||||
alias set-vault-ignore-tls="export VAULT_ADDR=https://docker-30:8200; export VAULT_SKIP_VERIFY=true"
|
||||
|
||||
|
||||
export VAULT_ADDR="https://vault.hrajfrisbee.cz"
|
||||
export VAULT_SKIP_VERIFY=true
|
||||
```
|
||||
|
||||
## backup
|
||||
|
||||
Simple file copy initiated by cron, backend storage is minio (s3) running on synology
|
||||
|
||||
```bash
|
||||
echo '30 2 * * * root /root/bin/vault-backup.sh >> /var/log/vault-backup.log 2>&1' > /etc/cron.d/vault-backup
|
||||
```
|
||||
|
||||
```bash
|
||||
# output role info
|
||||
tofu output -raw role_id
|
||||
tofu output -raw secret_id
|
||||
|
||||
```
|
||||
|
||||
## vault initialization
|
||||
|
||||
```bash
|
||||
|
||||
vault operator init -key-shares=1 -key-threshold=1
|
||||
|
||||
```
|
||||
49
docker-30/vault/terraform/main.tf
Normal file
49
docker-30/vault/terraform/main.tf
Normal file
@@ -0,0 +1,49 @@
|
||||
resource "vault_mount" "kv" {
|
||||
path = "secret"
|
||||
type = "kv-v2"
|
||||
description = "KV v2 secrets engine"
|
||||
}
|
||||
|
||||
resource "vault_policy" "eso_read" {
|
||||
name = "external-secrets-read"
|
||||
policy = <<-EOT
|
||||
path "${vault_mount.kv.path}/data/*" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "${vault_mount.kv.path}/metadata/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_auth_backend" "approle" {
|
||||
type = "approle"
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role" "eso" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = "external-secrets"
|
||||
token_policies = [vault_policy.eso_read.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 14400
|
||||
}
|
||||
|
||||
data "vault_approle_auth_backend_role_id" "eso" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = vault_approle_auth_backend_role.eso.role_name
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role_secret_id" "eso" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = vault_approle_auth_backend_role.eso.role_name
|
||||
}
|
||||
|
||||
output "role_id" {
|
||||
value = data.vault_approle_auth_backend_role_id.eso.role_id
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "secret_id" {
|
||||
value = vault_approle_auth_backend_role_secret_id.eso.secret_id
|
||||
sensitive = true
|
||||
}
|
||||
1
docker-30/vault/terraform/terraform.tfstate
Normal file
1
docker-30/vault/terraform/terraform.tfstate
Normal file
@@ -0,0 +1 @@
|
||||
{"version":4,"terraform_version":"1.11.2","serial":2,"lineage":"88d0da45-267c-24b8-34e1-c9a1c58ab70f","outputs":{"role_id":{"value":"864e352d-2064-2bf9-2c73-dbd676a95368","type":"string","sensitive":true},"secret_id":{"value":"8dd0e675-f4dc-50ba-6665-3db5ae423702","type":"string","sensitive":true}},"resources":[{"mode":"data","type":"vault_approle_auth_backend_role_id","name":"eso","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"backend":"approle","id":"auth/approle/role/external-secrets/role-id","namespace":null,"role_id":"864e352d-2064-2bf9-2c73-dbd676a95368","role_name":"external-secrets"},"sensitive_attributes":[]}]},{"mode":"managed","type":"vault_approle_auth_backend_role","name":"eso","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"backend":"approle","bind_secret_id":true,"id":"auth/approle/role/external-secrets","namespace":null,"role_id":"864e352d-2064-2bf9-2c73-dbd676a95368","role_name":"external-secrets","secret_id_bound_cidrs":null,"secret_id_num_uses":0,"secret_id_ttl":0,"token_bound_cidrs":null,"token_explicit_max_ttl":0,"token_max_ttl":14400,"token_no_default_policy":false,"token_num_uses":0,"token_period":0,"token_policies":["external-secrets-read"],"token_ttl":3600,"token_type":"default"},"sensitive_attributes":[],"private":"bnVsbA==","dependencies":["vault_auth_backend.approle","vault_mount.kv","vault_policy.eso_read"]}]},{"mode":"managed","type":"vault_approle_auth_backend_role_secret_id","name":"eso","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"accessor":"f20ef8a0-f21f-8c9b-fc38-887a005af763","backend":"approle","cidr_list":null,"id":"backend=approle::role=external-secrets::accessor=f20ef8a0-f21f-8c9b-fc38-887a005af763","metadata":"{}","namespace":null,"num_uses":0,"role_name":"external-secrets","secret_id":"8dd0e675-f4dc-50ba-6665-3db5ae423702","ttl":0,"with_wrapped_accessor":null,"wrapping_accessor":null,"wrapping_token":null,"wrapping_ttl":null},"sensitive_attributes":[[{"type":"get_attr","value":"secret_id"}],[{"type":"get_attr","value":"wrapping_token"}]],"private":"bnVsbA==","dependencies":["vault_approle_auth_backend_role.eso","vault_auth_backend.approle","vault_mount.kv","vault_policy.eso_read"]}]},{"mode":"managed","type":"vault_auth_backend","name":"approle","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":1,"attributes":{"accessor":"auth_approle_409190cb","description":"","disable_remount":false,"id":"approle","identity_token_key":null,"local":false,"namespace":null,"path":"approle","tune":[],"type":"approle"},"sensitive_attributes":[],"private":"eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ=="}]},{"mode":"managed","type":"vault_mount","name":"kv","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"accessor":"kv_d207dd40","allowed_managed_keys":null,"allowed_response_headers":null,"audit_non_hmac_request_keys":[],"audit_non_hmac_response_keys":[],"default_lease_ttl_seconds":0,"delegated_auth_accessors":null,"description":"KV v2 secrets engine","external_entropy_access":false,"id":"secret","identity_token_key":"","listing_visibility":"","local":false,"max_lease_ttl_seconds":0,"namespace":null,"options":null,"passthrough_request_headers":null,"path":"secret","plugin_version":null,"seal_wrap":false,"type":"kv-v2"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"vault_policy","name":"eso_read","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"id":"external-secrets-read","name":"external-secrets-read","namespace":null,"policy":"path \"secret/data/*\" {\n capabilities = [\"read\"]\n}\npath \"secret/metadata/*\" {\n capabilities = [\"read\", \"list\"]\n}\n"},"sensitive_attributes":[],"private":"bnVsbA==","dependencies":["vault_mount.kv"]}]}],"check_results":null}
|
||||
1
docker-30/vault/terraform/terraform.tfstate.backup
Normal file
1
docker-30/vault/terraform/terraform.tfstate.backup
Normal file
@@ -0,0 +1 @@
|
||||
{"version":4,"terraform_version":"1.11.2","serial":1,"lineage":"88d0da45-267c-24b8-34e1-c9a1c58ab70f","outputs":{"role_id":{"value":"8833d0f8-d35d-d7ea-658b-c27837d121ab","type":"string","sensitive":true},"secret_id":{"value":"1791bfd9-5dc6-406a-3960-ba8fcad4a5a9","type":"string","sensitive":true}},"resources":[{"mode":"data","type":"vault_approle_auth_backend_role_id","name":"eso","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"backend":"approle","id":"auth/approle/role/external-secrets/role-id","namespace":null,"role_id":"8833d0f8-d35d-d7ea-658b-c27837d121ab","role_name":"external-secrets"},"sensitive_attributes":[]}]},{"mode":"managed","type":"vault_approle_auth_backend_role","name":"eso","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"backend":"approle","bind_secret_id":true,"id":"auth/approle/role/external-secrets","namespace":null,"role_id":"8833d0f8-d35d-d7ea-658b-c27837d121ab","role_name":"external-secrets","secret_id_bound_cidrs":null,"secret_id_num_uses":0,"secret_id_ttl":0,"token_bound_cidrs":null,"token_explicit_max_ttl":0,"token_max_ttl":14400,"token_no_default_policy":false,"token_num_uses":0,"token_period":0,"token_policies":["external-secrets-read"],"token_ttl":3600,"token_type":"default"},"sensitive_attributes":[],"private":"bnVsbA==","dependencies":["vault_auth_backend.approle","vault_mount.kv","vault_policy.eso_read"]}]},{"mode":"managed","type":"vault_approle_auth_backend_role_secret_id","name":"eso","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"accessor":"bcc08746-6bea-8df2-02da-f6a697bceb59","backend":"approle","cidr_list":null,"id":"backend=approle::role=external-secrets::accessor=bcc08746-6bea-8df2-02da-f6a697bceb59","metadata":"{}","namespace":null,"num_uses":0,"role_name":"external-secrets","secret_id":"1791bfd9-5dc6-406a-3960-ba8fcad4a5a9","ttl":0,"with_wrapped_accessor":null,"wrapping_accessor":null,"wrapping_token":null,"wrapping_ttl":null},"sensitive_attributes":[[{"type":"get_attr","value":"secret_id"}],[{"type":"get_attr","value":"wrapping_token"}]],"private":"bnVsbA==","dependencies":["vault_approle_auth_backend_role.eso","vault_auth_backend.approle","vault_mount.kv","vault_policy.eso_read"]}]},{"mode":"managed","type":"vault_auth_backend","name":"approle","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":1,"attributes":{"accessor":"auth_approle_c6cd7bc1","description":"","disable_remount":false,"id":"approle","identity_token_key":null,"local":false,"namespace":null,"path":"approle","tune":[],"type":"approle"},"sensitive_attributes":[],"private":"eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ=="}]},{"mode":"managed","type":"vault_mount","name":"kv","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"accessor":"kv_8285fbfc","allowed_managed_keys":null,"allowed_response_headers":null,"audit_non_hmac_request_keys":[],"audit_non_hmac_response_keys":[],"default_lease_ttl_seconds":0,"delegated_auth_accessors":null,"description":"KV v2 secrets engine","external_entropy_access":false,"id":"secret","identity_token_key":"","listing_visibility":"","local":false,"max_lease_ttl_seconds":0,"namespace":null,"options":null,"passthrough_request_headers":null,"path":"secret","plugin_version":null,"seal_wrap":false,"type":"kv-v2"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"vault_policy","name":"eso_read","provider":"provider[\"registry.opentofu.org/hashicorp/vault\"]","instances":[{"schema_version":0,"attributes":{"id":"external-secrets-read","name":"external-secrets-read","namespace":null,"policy":"path \"secret/data/*\" {\n capabilities = [\"read\"]\n}\npath \"secret/metadata/*\" {\n capabilities = [\"read\", \"list\"]\n}\n"},"sensitive_attributes":[],"private":"bnVsbA==","dependencies":["vault_mount.kv"]}]}],"check_results":null}
|
||||
12
docker-30/vault/terraform/versions.tf
Normal file
12
docker-30/vault/terraform/versions.tf
Normal file
@@ -0,0 +1,12 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "vault" {
|
||||
# Uses VAULT_ADDR and VAULT_TOKEN from env
|
||||
}
|
||||
38
docker-30/vault/vault-backup.sh
Normal file
38
docker-30/vault/vault-backup.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# set -x # Enable debug output
|
||||
|
||||
# --- Configuration ---
|
||||
VAULT_DATA_DIR="${VAULT_DATA_DIR:-/srv/docker/vault/data/}"
|
||||
S3_BUCKET="${S3_BUCKET:-vault-backup}"
|
||||
MC_ALIAS="${MC_ALIAS:-synology}" # Pre-configured mc alias
|
||||
RETENTION_DAYS="${RETENTION_DAYS:-60}"
|
||||
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
BACKUP_FILE="/tmp/vault-backup-${TIMESTAMP}.tar.gz"
|
||||
|
||||
log() { echo "[$(date -Iseconds)] $*"; }
|
||||
|
||||
cleanup() {
|
||||
rm -f "${BACKUP_FILE}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# --- Create backup ---
|
||||
log "Backing up ${VAULT_DATA_DIR}..."
|
||||
tar -czf "${BACKUP_FILE}" -C "$(dirname "${VAULT_DATA_DIR}")" "$(basename "${VAULT_DATA_DIR}")"
|
||||
|
||||
BACKUP_SIZE=$(stat -c%s "${BACKUP_FILE}")
|
||||
log "Backup size: ${BACKUP_SIZE} bytes"
|
||||
|
||||
# --- Upload to MinIO ---
|
||||
log "Uploading to ${MC_ALIAS}/${S3_BUCKET}..."
|
||||
set -x
|
||||
mc cp --quiet "${BACKUP_FILE}" "${MC_ALIAS}/${S3_BUCKET}/vault-backup-${TIMESTAMP}.tar.gz"
|
||||
|
||||
# --- Prune old backups ---
|
||||
log "Pruning backups older than ${RETENTION_DAYS} days..."
|
||||
mc rm --quiet --recursive --force --older-than "${RETENTION_DAYS}d" "${MC_ALIAS}/${S3_BUCKET}/"
|
||||
|
||||
log "Backup complete: vault-backup-${TIMESTAMP}.tar.gz"
|
||||
Reference in New Issue
Block a user