diff --git a/bin/op b/bin/op new file mode 100755 index 0000000..0b884a3 --- /dev/null +++ b/bin/op @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +set -euo pipefail + +OP_SESSION_DIR="${XDG_RUNTIME_DIR}/op" +OP_SESSION_FILE="${OP_SESSION_DIR}/session_token" + +# With `-p` the mode setting only applies to the deepest directory. This is +# exactly what I want here. +# +# shellcheck disable=SC2174 +[ -d "${OP_SESSION_DIR}" ] || mkdir -m 700 -p "${OP_SESSION_DIR}" + +session_token() { + cat "${OP_SESSION_FILE}" +} + +# This whole script gets aliased as `op`, so make sure we don't recurse. +op() { + /bin/op "$@" +} + +validate() { + /bin/op list vaults --session="$(session_token)" >/dev/null 2>&1 +} + +signin() { + old_umask="$(umask)" + umask 177 + + token="$(/bin/op signin --output=raw)" + cat > "${OP_SESSION_FILE}" <<< "${token}" + + umask "${old_umask}" +} + +# It's easier to special-case the no-argument call like this. +[ "$#" -eq 0 ] && exec /bin/op + +cmd="$1" +if [ "${cmd}" = '_validate' ]; then + validate >/dev/null 2>&1 + exit $? +fi + +validate || signin + +if [ "${cmd}" = 'find' ]; then + url="$2" + query='.[] | select(.overview.url and (.overview.url | contains("'"${url}"'"))) | { uuid: .uuid, url: .overview.url }' + /bin/op list items --session="$(session_token)" | jq -c "${query}" + exit $? +fi + +exec /bin/op "${@}" --session="$(session_token)" diff --git a/bin/passget b/bin/passget index 747d46c..4686e2a 100755 --- a/bin/passget +++ b/bin/passget @@ -7,9 +7,45 @@ fi set -euo pipefail -contents=$(gopass show "$1") || exit 1 -echo "$contents" | grep '^user:' | cut -d' ' -f2 | xsel -b -echo 'Username clipped' -read -r _ +# This depends on having the custom `op` wrapper in this directory. +# Specifically, it depends on automatically logging the user in if a session +# token hasn't already been saved. If the wrapper can't be installed, +# uncomment this line instead: +# +# op list vaults >/dev/null 2>&1 || eval "$(op signin)" -gopass show --clip "$1" +url="$1" +mapfile -t matches < <(op list items | jq -c '.[] | select(.overview.url and (.overview.url | contains("'"${url}"'"))) | { uuid: .uuid, url: .overview.url }') + +if [ "${#matches[@]}" -eq 1 ]; then + item="${matches[0]}" + uuid="$(echo "${item}" | jq -r '.uuid')" +else + uuid="$(echo "${matches[@]}" \ + | jq -r '"\n\(.uuid)\n\(.url)"' \ + | zenity \ + --list --radiolist \ + --title 'passget' \ + --text 'Choose a match' \ + --column ' ' \ + --column 'UUID' \ + --column 'URL')" +fi + +query_username='.details.fields[] | select(.name == "username") | .value' +query_password='.details.fields[] | select(.name == "password") | .value' + +item="$(op get item "${uuid}")" +echo "${item}" | jq -r "${query_username}" | xsel -bi +echo 'Username clipped' + +read -r _ +echo "${item}" | jq -r "${query_password}" | xsel -bi +echo 'Password clipped. Clearing in 60 seconds.' + +at -M 'now + 1 minute' >/dev/null 2>&1 <