Last active
December 5, 2023 15:11
-
-
Save Luzifer/2c760963dbd040e60a698d63ec71c493 to your computer and use it in GitHub Desktop.
Setup for LUKS encrypted disk using Vault transit encryption for the key and local auth-expiry
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -euo pipefail | |
function fatal() { | |
log "$@" | |
exit 1 | |
} | |
function log() { | |
echo "$@" >&2 | |
} | |
function main() { | |
[[ -n ${VAULT_ADDR:-} ]] || fatal "Missing ENV VAULT_ADDR" | |
[[ -n ${VAULT_ROLE_ID:-} ]] || fatal "Missing ENV VAULT_ROLE_ID" | |
[[ -n ${VAULT_SECRET_ID:-} ]] || fatal "Missing ENV VAULT_SECRET_ID" | |
key_file=/etc/luks-volume/key | |
mountpoint=/volume | |
open_name=volume-luks | |
transit=luks-archnas | |
volume=/dev/md127 | |
case ${1:-help} in | |
create-key) | |
[[ -e $key_file ]] && fatal "Key already exists." || true | |
log "Creating new key in ${key_file}..." | |
vault_login | |
mkdir -p $(dirname ${key_file}) | |
openssl rand 512 | base64 -w0 | vault write -field=ciphertext transit/encrypt/${transit} plaintext=- >${key_file} | |
chmod 0400 ${key_file} | |
;; | |
format) | |
cryptsetup isLuks ${volume} && fatal "${volume} is already formated as luks" || true | |
log "Formatting ${volume} with LUKS..." | |
vault_login | |
vault write -field=plaintext transit/decrypt/${transit} ciphertext=- <${key_file} | | |
base64 -d | | |
cryptsetup luksFormat --batch-mode --type luks2 --pbkdf argon2id --key-file - ${volume} | |
;; | |
mount) | |
mount | grep -q "on ${mountpoint}" && fatal "Mountpoint ${mountpoint} already mounted." || true | |
log "Mounting ${volume} on ${mountpoint}..." | |
vault_login | |
[[ -e /dev/mapper/${open_name} ]] || vault write -field=plaintext transit/decrypt/${transit} ciphertext=- <${key_file} | | |
base64 -d | | |
cryptsetup open --type luks --key-file - ${volume} ${open_name} | |
mount /dev/mapper/${open_name} ${mountpoint} | |
;; | |
umount) | |
[[ -e /dev/mapper/${open_name} ]] || fatal "Crypto mapper not available." || true | |
log "Unmounting ${volume} from ${mountpoint}..." | |
mount | grep -q "on ${mountpoint}" && umount ${mountpoint} || true | |
[[ -e /dev/mapper/${open_name} ]] && cryptsetup close /dev/mapper/${open_name} || true | |
;; | |
*) | |
echo "Usage: $(basename $0) <create-key|format|mount|umount>" | |
;; | |
esac | |
} | |
function vault_login() { | |
export VAULT_TOKEN=$(vault write -field=token auth/approle/login role_id=${VAULT_ROLE_ID} secret_id=${VAULT_SECRET_ID}) | |
[[ -n ${VAULT_TOKEN:-} ]] | |
} | |
main "$@" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Unit] | |
Description=Start/stop the LUKS-encrypted partition | |
After=local-fs.target network-online.target | |
[Service] | |
Type=oneshot | |
RemainAfterExit=yes | |
EnvironmentFile=/etc/luks-volume/vault-auth | |
ExecStart=/usr/local/bin/manage-volume mount | |
ExecStop=/usr/local/bin/manage-volume umount | |
[Install] | |
WantedBy=multi-user.target |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -euo pipefail | |
function fatal() { | |
log "$@" | |
exit 1 | |
} | |
function log() { | |
echo "$@" >&2 | |
} | |
function main() { | |
[[ -n ${VAULT_ADDR:-} ]] || fatal "Missing ENV VAULT_ADDR" | |
[[ -n ${VAULT_ROLE_ID:-} ]] || fatal "Missing ENV VAULT_ROLE_ID" | |
auth_file=/etc/luks-volume/vault-auth | |
role_name=luks-archnas | |
while :; do | |
log "Updating ${auth_file} with new credentials..." | |
export VAULT_TOKEN=$(vault write -field=token auth/approle/login role_id=${VAULT_ROLE_ID}) | |
[[ -n ${VAULT_TOKEN:-} ]] || fatal "Could not retrieve VAULT_TOKEN" | |
local role_id=$(vault read -field=role_id auth/approle/role/${role_name}/role-id) | |
[[ -n $role_id ]] || fatal "Could not retrieve VAULT_ROLE_ID" | |
local secret_json=$(vault write --format=json --force auth/approle/role/${role_name}/secret-id) | |
local secret_id=$(jq -r '.data.secret_id' <<<"${secret_json}") | |
[[ -n $secret_id ]] || fatal "Could not retrieve VAULT_SECRET_ID" | |
local expiry=$(jq -r '.data.secret_id_ttl' <<<"${secret_json}") | |
echo "VAULT_ADDR=${VAULT_ADDR}" >${auth_file}.new | |
echo "VAULT_ROLE_ID=${role_id}" >>${auth_file}.new | |
echo "VAULT_SECRET_ID=${secret_id}" >>${auth_file}.new | |
chmod 0400 ${auth_file}.new | |
mv ${auth_file}.new ${auth_file} | |
log "Credentials updated, sleeping for $((expiry / 2))s..." | |
sleep $((expiry / 2)) | |
done | |
} | |
main "$@" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Unit] | |
Description=Update the auth data for volume auto-mount | |
After=network-online.target manage-volume.service | |
Requires=manage-volume.service | |
[Service] | |
EnvironmentFile=/volume/.luks-volume-renew | |
ExecStart=/usr/local/bin/renew-volume-auth | |
Restart=always | |
RestartSec=5 | |
[Install] | |
WantedBy=multi-user.target |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment