secret (3933B)
- #!/bin/sh
- # secret: Replacement to pass(1) based on reop(1)
- # Copyright 2020 Haelwenn (lanodan) Monnier <contact+secret@hacktivis.me>
- # SPDX-License-Identifier: ISC
- basepath="$HOME/.secret-storage"
- set -e
- secret_clip() {
- head -n 1 | tr -d '\n' | xclip -i -selection clipboard
- }
- secret_init() {
- set -x
- test -f "${basepath}.pub" -a -f "${basepath}.priv" || reop -G -p "${basepath}.pub" -s "${basepath}.priv"
- chmod 0400 "${basepath}.pub" "${basepath}.priv"
- test -d "$basepath/.git" || git init "${basepath}"
- chmod 0700 "$basepath"
- }
- secret_list() {
- ( cd "$basepath" && find . -type f -name '*.reop' "$@" | sed -e 's;^./;;' -e 's;.reop$;;') | sort
- }
- secret_list_oath() {
- secret_list -name '*.oath.reop' "$@"
- }
- tree() {
- secret_list "$@" | tree --fromfile
- }
- secret_read() {
- entry="$*"
- target="${SECRET_FILE:--}"
- reop -D -p "${basepath}.pub" -s "${basepath}.priv" -m "$target" -x "${basepath}/${entry}.reop"
- }
- secret_write() {
- entry="$*"
- target="${SECRET_FILE:--}"
- reop -E -p "${basepath}.pub" -s "${basepath}.priv" -m "$target" -x "${basepath}/${entry}.reop"
- if test -f "${basepath}/.git/HEAD"
- then
- oldpwd="$PWD"
- cd "${basepath}"
- git add "${entry}.reop"
- git commit -m "${entry}: encrypt auto-update"
- if [ "$(git remote show -n)" != "" ]; then git push; fi
- cd "${oldpwd}"
- else
- echo "No git repository in ‘$basepath’, consider creating one"
- fi
- }
- secret_read_oath() {
- oathtool $(secret_read "$@")
- }
- secret_edit() {
- file="${basepath}/.secret_$RANDOM.txt"
- unset SECRET_FILE
- secret_read "$@" > "$file"
- $EDITOR "$file" || rm -f "$file"
- secret_write "$@" < "$file" ; rm -f "$file"
- }
- secret_delete() {
- entry="$*"
- (
- cd "${basepath}"
- if test -f "${basepath}/.git/HEAD"
- then
- git rm "${entry}.reop"
- git commit -m "${entry}: remove"
- if [ "$(git remote show -n)" != "" ]; then git push; fi
- else
- echo "No git repository in ‘$basepath’, consider creating one"
- rm "${entry}.reop"
- fi
- )
- }
- secret_dmenu() {
- echo | dmenu -nb '#000' -nf '#000' -p "Passphrase: "
- }
- secret_dmenu_oath() {
- entry="$(secret_list -name '*.oath.reop' | dmenu -i)"
- export SECRET_FILE="${basepath}/.secret_$RANDOM.txt"
- secret_dmenu | secret_read "$entry"
- oathtool $(cat "${SECRET_FILE}") | secret_clip
- shred -u "${SECRET_FILE}"
- }
- secret_dmenu_read() {
- entry="$(secret_list | dmenu -i)"
- export SECRET_FILE="${basepath}/.secret_$RANDOM.txt"
- secret_dmenu | secret_read "$entry"
- cat "${SECRET_FILE}" | secret_clip
- shred -u "${SECRET_FILE}"
- }
- secret_usage() {
- cat <<-EOF
- secret [command] [command-arguments...]
- Replacement to pass(1) based on reop(1)
- secret init
- Initializes secret keys and git storage repo.
- secret ls [arguments...]
- List the entries. Passes arguments to find(1).
- secret tree [arguments...]
- Same as ‘secret ls’ but outputs via tree(1).
- secret read <entry>
- Read a secret entry.
- secret write <entry>
- Write a secret entry.
- secret edit <entry>
- Wrapper around $EDITOR for easy secret edition.
- secret delete <entry>
- Delete a secret entry.
- secret dmenu
- dmenu on entries, dmenu for a passphrase, read secret, pipe to xclip(1).
- secret ls-oath [arguments...]
- Same as ‘secret ls’ but limited to oath entries(‘*.oath.reop’).
- secret read-oath <entry>
- Same as ‘secret read’ but entry content passed to oathtool(1) as arguments.
- secret dmenu-oath
- Same as ‘secret dmenu’ but ‘secret read-oath’ instead of ‘secret read’.
- EOF
- exit 1
- }
- command="$1"
- [ "$1" = "" ] && secret_usage "$@"
- shift || secret_usage "$@"
- case "$command" in
- init) secret_init "$@" ;;
- ls) secret_list "$@" ;;
- tree) secret_tree "$@" ;;
- read) secret_read "$@" ;;
- write) secret_write "$@" ;;
- edit) secret_edit "$@" ;;
- del*) secret_delete "$@" ;;
- dmenu) secret_dmenu_read "$@" ;;
- ls-oath) secret_list_oath "$@" ;;
- read-oath) secret_read_oath "$@" ;;
- dmenu-oath) secret_dmenu_oath "$@" ;;
- *) secret_usage "$@" ;;
- esac