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