diff --git a/1pass b/1pass index 7193f5d..12d1a85 100755 --- a/1pass +++ b/1pass @@ -21,7 +21,7 @@ set -e set -o pipefail -VERSION="1.0.1" +VERSION="1.1" if [ "$XDG_CONFIG_HOME" != "" ] && [ ! -d "${HOME}/.1pass" ]; then op_dir="${XDG_CONFIG_HOME}/1pass" @@ -127,11 +127,25 @@ With no arguments, prints a list of all Logins and Passwords in all 1Password va With a single argument, fetches the Item (Login, Password, or TOTP) matching the given name, and copies the resulting password to the clipboard. -With two arguments, fetches the specified field (e.g.) "usernmae" from the named +With two arguments, fetches the specified field (e.g.) "username" from the named item, and copies the results to the clipboard. USAGE } +sanity_check() +{ + for cmd in "op" "jq" "gpg" "expect" + do + if [ $verbose -eq 1 ]; then + echo "checking for $cmd" + fi + if [ ! -x "`which $cmd`" ]; then + echo "Cannot find the '$cmd' command. Please make sure it is installed" + exit 1 + fi + done +} + signin() { local pw=$(gpg -d -q $master) @@ -139,14 +153,30 @@ signin() if [ $verbose -eq 1 ]; then echo "signing in to ${domain} $email" fi - local token=$(echo -n "${pw}" | op signin --output=raw ${domain} $email $se || echo -n "_fail_") - if [ "$token" == "_fail_" ]; then + local script=" + spawn op signin ${domain} ${email} ${se} + expect \"${domain}:\" + send \"${pw}\n\" + expect { + \"Enter your six-digit authentication code:\" { + puts -nonewline stderr \"Enter your six-digit authentication code: \" + flush stderr + interact -o \"\r\" return + puts stderr \"\" + exp_continue + } + eof + } + " + local output0=$(expect -c "${script}") + local output=$(echo "${output0}" | grep "export" || echo -n "_fail_") + if [ "$output" == "_fail_" ]; then echo "1pass failed to signin to ${domain}" exit 1 fi + # extract token from 'export OP_SESSION_domain="asdsad"' + local token=$(expr "${output}" : '.*="\(.*\)"') echo -n "${token}" | gpg -qe --batch -r $self_key > $session - # also export it in case we use the op command in the shell: - export $OP_SESSION_NAME=$token } init_session() @@ -363,6 +393,8 @@ done shift $((OPTIND-1)) +sanity_check + if [ $# -eq 0 ]; then list_items elif [ $# -eq 1 ]; then diff --git a/README.md b/README.md index c0157b5..975f020 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,12 @@ **1pass** is a caching wrapper for the [1Password CLI](https://support.1password.com/command-line-getting-started/) `op`. +## UPGRADE NOTE + +Upgrading to version 1.1 requires installation of the +[expect](https://core.tcl.tk/expect/index) tool. `1pass` will check for this (and +other) dependencies and remind you to install them. + ## Introduction **1pass** is designed to make using your 1Password usernames and passwords quick and easy. It is @@ -34,11 +40,14 @@ Together these features enable easy use of 1Password-stored credentials. ## Installation First make sure that the `op` [1Password -CLI](https://support.1password.com/command-line-getting-started/) and the `jq` [JQ](https://stedolan.github.io/jq) are installed. If you use homebrew cask on Mac OS X, this works well: +CLI](https://support.1password.com/command-line-getting-started/) and the `jq` +[JQ](https://stedolan.github.io/jq) and +[expect](https://core.tcl.tk/expect/index) requirements are installed. If you use +homebrew cask on Mac OS X, this works well: ```sh $ brew cask install 1password-cli -$ brew install jq +$ brew install jq expect ``` Copy the 1pass executable file to a suitable location on your PATH (for example, /usr/local/bin) @@ -167,6 +176,8 @@ $ 1pass -p MyBankAccount pin **1pass** has special support for TOTP fields -- these are fetched directly via `op` rather than a local cache. (Thanks to (@ev0rtex)[https://github.com/ev0rtex]). +Note that this **is different** from using TOTP 2FA to log into your 1Password +account (that is supported too -- see below) ```sh $ 1pass -p MyBankAccount totp @@ -197,6 +208,14 @@ from the online 1Password vault. Similarly, 1Password CLI sessions last for 30 minutes from the time of last use. **1pass** will manage the session for you, and refresh it as needed. +## 2FA for 1Password + +If you have turned on two-factor authentication (2FA) support for your 1Password +account, then 1pass will prompt for you to enter a TOTP code when creating a +session. Currently, you will need to re-enter this code after every session +expiration (30 minutes of inactivity). Unfortunately this makes using 1pass in +non-interactive scripts less useful. + ## License Copyright (c) 2017, David Creemer (twitter: [@dcreemer](https://twitter.com/dcreemer)) with some