Initial commit: Bitwarden export to PDF renderer
Adds the render.py WeasyPrint renderer, the pod-based bitwarden-print.sh wrapper, a Containerfile, a sample export (JSON + PDF), README and LICENSE.
This commit is contained in:
commit
41385b35e6
8 files changed
+1041
No files matched your search
Executable
+109
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env bash
|
||||
# Render a Bitwarden JSON export to PDF inside a dedicated Podman pod.
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
IMAGE=${IMAGE:-localhost/bitwarden-print:latest}
|
||||
POD=${POD:-bitwarden-print-pod}
|
||||
CONTAINER=${CONTAINER:-bitwarden-print-run}
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: ./bitwarden-print.sh EXPORT.json [-o OUT.pdf] [options]
|
||||
|
||||
Creates a PDF with every value from a Bitwarden JSON export, densely typeset.
|
||||
|
||||
Options:
|
||||
-o, --output FILE output PDF (default: next to the export, same basename)
|
||||
--sort MODE folder (default), name, type or as-is
|
||||
--title TEXT document title
|
||||
--paper SIZE a4 (default) or letter
|
||||
--mask-secrets mask passwords, TOTP, card numbers/codes, SSN, keys
|
||||
-h, --help show this help
|
||||
|
||||
Environment:
|
||||
IMAGE, POD, CONTAINER override image/pod/container names
|
||||
EOF
|
||||
}
|
||||
|
||||
INPUT=""
|
||||
OUTPUT=""
|
||||
render_args=()
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-o|--output)
|
||||
[ $# -ge 2 ] || { echo "error: $1 needs a value" >&2; exit 2; }
|
||||
OUTPUT=$2; shift 2 ;;
|
||||
--sort)
|
||||
[ $# -ge 2 ] || { echo "error: $1 needs a value" >&2; exit 2; }
|
||||
render_args+=(--sort "$2"); shift 2 ;;
|
||||
--paper)
|
||||
[ $# -ge 2 ] || { echo "error: $1 needs a value" >&2; exit 2; }
|
||||
render_args+=(--paper "$2"); shift 2 ;;
|
||||
--title)
|
||||
[ $# -ge 2 ] || { echo "error: $1 needs a value" >&2; exit 2; }
|
||||
render_args+=(--title "$2"); shift 2 ;;
|
||||
--mask-secrets)
|
||||
render_args+=(--mask-secrets); shift ;;
|
||||
-h|--help)
|
||||
usage; exit 0 ;;
|
||||
-*)
|
||||
echo "error: unknown option: $1" >&2; usage >&2; exit 2 ;;
|
||||
*)
|
||||
[ -z "$INPUT" ] || { echo "error: only one export file can be given" >&2; exit 2; }
|
||||
INPUT=$1; shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -n "$INPUT" ] || { usage >&2; exit 2; }
|
||||
[ -f "$INPUT" ] || { echo "error: no such file: $INPUT" >&2; exit 1; }
|
||||
|
||||
in_dir=$(cd -- "$(dirname -- "$INPUT")" && pwd)
|
||||
in_name=$(basename -- "$INPUT")
|
||||
|
||||
if [ -z "$OUTPUT" ]; then
|
||||
OUTPUT="$in_dir/${in_name%.json}.pdf"
|
||||
fi
|
||||
out_dir=$(dirname -- "$OUTPUT")
|
||||
mkdir -p -- "$out_dir"
|
||||
out_dir=$(cd -- "$out_dir" && pwd)
|
||||
out_name=$(basename -- "$OUTPUT")
|
||||
|
||||
cleanup() {
|
||||
podman rm -f "$CONTAINER" >/dev/null 2>&1 || true
|
||||
podman pod exists "$POD" >/dev/null 2>&1 && podman pod rm -f "$POD" >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "==> building image $IMAGE"
|
||||
podman build -q -t "$IMAGE" "$SCRIPT_DIR"
|
||||
|
||||
echo "==> creating pod $POD"
|
||||
podman pod rm -f "$POD" >/dev/null 2>&1 || true
|
||||
podman pod create --name "$POD" >/dev/null
|
||||
|
||||
# Copy the export in instead of bind-mounting it: works for any host path,
|
||||
# including paths the Podman machine does not share (e.g. /tmp) and hosts
|
||||
# where SELinux relabelling is not allowed.
|
||||
echo "==> rendering $in_name"
|
||||
podman create --pod "$POD" --name "$CONTAINER" \
|
||||
"$IMAGE" "/export.json" -o "/output.pdf" \
|
||||
${render_args[@]+"${render_args[@]}"} >/dev/null
|
||||
podman cp "$INPUT" "$CONTAINER:/export.json"
|
||||
|
||||
status=0
|
||||
podman start -a "$CONTAINER" || status=$?
|
||||
if [ "$status" -ne 0 ]; then
|
||||
echo "error: rendering failed (exit $status)" >&2
|
||||
exit "$status"
|
||||
fi
|
||||
|
||||
tmp_pdf=$(mktemp "${TMPDIR:-/tmp}/bitwarden-print.XXXXXX.pdf")
|
||||
if ! podman cp "$CONTAINER:/output.pdf" "$tmp_pdf"; then
|
||||
echo "error: container produced no PDF at /output.pdf" >&2
|
||||
exit 1
|
||||
fi
|
||||
mv -f "$tmp_pdf" "$out_dir/$out_name"
|
||||
|
||||
echo "==> PDF: $out_dir/$out_name"
|
||||
Reference in new issue
Block a user