some things I've done with the cli

skunkwerks
skunkwerks
Community Member

So the big one is that I imported my entire keepassx into 1P as a result of having this command-line tool now available. While I've not mastered the cli tool yet, I can finally use 1P everywhere with sync, instead of keypassx with manual sync.

The other one is to store our deploy ssh key in 1P and simply pipe the output of the key into ssh-agent: | ssh-add - . So now, instead of requiring that everybody has a copy of the private key on disk, we are now only storing it temporarily in memory while running the job, and when I logout of a build box or server, the key is one -- I'm sure it will make rolling ssh keys much easier in future.

Sadly 1P cli broke on me today so I can't give the full examples, maybe when I'm back from vacation it will be working again.


1Password Version: Not Provided
Extension Version: Not Provided
OS Version: Not Provided
Sync Type: Not Provided

Comments

  • svondutch
    svondutch
    1Password Alumni

    @skunkwerks That is awesome! Thank you for sharing that with us.

    As for piping the output of your SSH key, I'm doing something similar on Windows where I open a SSH session with credentials stored in a 1Password item named hostname:

    S=$(op login fillion rick@centrix.ca A3-XXXXXX-XXXXXX-XXXXX-XXXXX-XXXXX-XXXXX) && T=hostname && D=$(op item $S $T) && U=$(echo $D | jq '.fields[] | select(.designation=="username").value') && P=$(echo $D | jq '.fields[] | select(.designation=="password").value') && putty -ssh $T -l $U -pw $P
    

    Looking forward to your examples. Have great vacation!

  • thats super cool. Is there any chance that you could share the script you made to do the keypassx to 1Password conversion? Others might find that helpful.

    Rick

  • beyer
    beyer
    1Password Alumni
    edited March 2018

    This is my first (rough but working) attempt at creating a script similar to what @svondutch is doing but using a private key attached to an item with multiple sections (which is the default when using the server category). Currently, it will check for a section named SSH and grab the hostname, username, and create a tempory file with the private key.

    if [ -z "$1" ]; then
      echo 'No 1Password item title provided.'
      exit
    fi
    S=$(op login account-shorthand)
    I=$(mktemp ~/.ssh/op.XXXXX) && trap "rm -rf $I" EXIT
    D=$(op item $S $1)
    if [[ $D == '[ERR]'* ]]; then
      echo $D
      exit
    fi
    H=$(echo $D | jq -r '.sections[] | select(.title=="SSH").fields[] | select(.t=="hostname").v')
    U=$(echo $D | jq -r '.sections[] | select(.title=="SSH").fields[] | select(.t=="username").v')
    K=$(echo $D | jq -r '.sections[] | select(.title=="Related Items").fields[] | select(.k=="reference").v')
    op document $S $K >> $I
    chmod 400 $I
    ssh $U@$H -i $I
    

    I tailored it to use ssh on macOS.

  • jpgoldberg
    jpgoldberg
    1Password Alumni

    Hi @beyer,

    Please rely on exit status instead of the content of output.

    D=$(op item $S $1)
    if [[ $D == '[ERR]'* ]]; then
      echo $D
      exit
    fi
    

    In version 0.0.2 error messages are written to stderr instead of stdout. (I'm sorry about not getting that into the CHANGELOG)

    op exits with a non-zero exit status on such errors, so you can test that way.

    Cheers,

    -j

  • jpgoldberg
    jpgoldberg
    1Password Alumni

    Oh, and nice use of trap in that script. Now I need to fix up one of mine for more robust cleanup of my own call to mktemp.

  • jpgoldberg
    jpgoldberg
    1Password Alumni

    I needed to recover some things from a tarsnap backup recently. Of course I keep my tarsnap keyfiles in 1Password. I've tried to make this more robust than my very immediate needs. And I've removed my personal account information from this sample.

    Also thanks to @beyer's script, I was reminded about trap.

    #!/usr/bin/env bash
    
    # Fetch a tarsnap keyfile from a 1Password Document, and then do tarsnap stuff
    # with that key file.
    
    ### Your account details
    
    OP_ACCOUNT=reynholm-industries          # Your 1password domain name here
    OP_USER='maurice.moss@reynholm.co.uk'   # Your email address here
    sk_path=${HOME}/nobackup/opsk-A3-ABCDEF # file containing your secret key
    
    ### Your file and executable paths
    # Note that as we are passing secrets to various programs, either $PATH
    # needs to be highly restricted, or we should specify the exact paths for
    # these things
    
    op_cmd=$GOPATH/bin/op               # probably not where you keep it
    ts_cmd="/opt/local/bin/tarsnap"     # where is your tarsnap binary
    
    
    # Bash associative arrays require bash 4. macOS /usr/bin/bash is 3
    if ((BASH_VERSINFO[0] < 4))
    then
        echo "You need bash version 4 or greater to run this script" 1>&2
        exit 1
    fi
    declare -A op_uuids 
    
    ### Lookup for tarsnap keyfile in 1Password.
    # If for example your keyfile for host "winky" has item UUID xjfhspk7l5ez3o2fvn6djjaqba
    # you would set up 
    #   op_uuids[winky]=xjfhspk7l5ez3o2fvn6djjaqba
    
    op_uuids[server1]=3ccwq54cg5np5ocgrv6axx5x34
    op_uuids[server2]=fqyocwjhp5mtrzv3sgckqagzjm
    
    PROGNAME=$(basename $0)
    
    function usage
    {
        cat << EO_USAGE
        Usage:
        $PROGNAME ts_nickname
    
        - ts_nickname: Nickname for set of tarsnap archives to fetch from
    
    EO_USAGE
    }
    
    function cleanup
    {
        [ -z $TMPFILE ] || rm -rf $TMPFILE
        [ -z $S ] || $op_cmd logout $S
    }
    trap cleanup EXIT 
    
    function error_exit
    {
        echo "${PROGNAME}: $1" 1>&2
        exit 1
    }
    
    [ ${#@} == 1 ] || { usage ; error_exit "Bad number of arguments" ; }
    
    ## Check that things at hard coded paths exist
    [ -x $ts_cmd ] || error_exit "No executable at $ts_cmd"
    [ -x $op_cmd ] || error_exit "No executable at $op_cmd"
    [ -r $sk_path ] || error_exit "Cannot read Secret Key file $sk_path"
    
    ts_key_uuid=${op_uuids[$1]}
    
    [ -z $ts_key_uuid ] && error_exit "No uuid for $1"
    
    TMPFILE=$(mktemp) # where we will put the tarsap keyfile
    
    # Although we are only making one request to the account, it is still
    # good form to first set up a session and then "reuse" that session token
    # stored in $S if only used once. This also allows us to logout of that
    # session when we are done
    
    read sk < $sk_path
    
    ## /bin/test on macOS doesn't know about =~ So leaving this out.
    # [ $sk =~ ^A[23]-[A-Z0-9]{6}-[-A-Z0-9]{29} ] || error_exit "Malformed Secret Key"
    
    S=$($op_cmd login $OP_ACCOUNT $OP_USER $sk) || error_exit "Failed to log in"
    $op_cmd document download $S $ts_key_uuid > $TMPFILE || error_exit "Couldn't fetch tarsnap key'"
    $op_cmd logout $S ; unset S
    
    ### do_tarsnap() takes one argument, the path to a keyfile.
    ## This is where you might customize what you want do with tarsnap.
    ## There is no need for it to be a separate function for this simple example,
    ## but you may wish to create a more complex function that might appear in a 
    ## different sourced file.
    function do_tarsnap {
        $ts_cmd --keyfile $1 --list-archives 
    
        ## There is a reason I wrote this sample script in the first place
        # DEST_DIR=$HOME/Documents/Kreacher-salvage
        # $ts_cmd -r --keyfile $1 -f 20170523-030135-daily-/usr/local/etc > $DEST_DIR/usr-local-etc.tar
        # $ts_cmd -r --keyfile $1 -f 20170523-030135-daily-/var/named > $DEST_DIR/var-named.tar
    }
    
    do_tarsnap $TMPFILE
    
  • beyer
    beyer
    1Password Alumni

    Thanks for posting this @jpgoldberg! I will definitely make some changes to the scripts I'm using.

  • ashneo76
    ashneo76
    Community Member
    edited June 2017

    My Zsh completion file is:

    [~] cat ~/.oh-my-zsh/completions/_op
    #compdef op
    
    _op() {
      _arguments \
        "--help[Show help options]" \
        "--version[Print version information and exit]" \
        "1: :_op_cmds" \
        "*:: :->op_cmd_args"
    
      case $state in
        op_cmd_args)
          case $words[1] in
            help)
              ;;
          esac
          ;;
      esac
    }
    
    _op_cmds() {
      local -a commands
      commands=(
        "account:Get account attributes."
        "create:Create a new vault or item."
        "delete:Deletes an entity from your 1Password account."
        "document:Download a document."
        "documents:Get a list of documents."
        "events:Get audit events."
        "item:Get item details."
        "items:Get a list of items."
        "login:Log in to the 1Password service by optaining a session."
        "logout:Log out of 1Password by removing or invalidating a session."
        "reactivate:Re-activates a suspended user."
        "suspend:Suspends a user."
        "template:Get item template."
        "totp:Get time-based one-time password (TOTP)."
        "user:Get user attributes."
        "users:Get a list of users."
        "vault:Get vault attributes."
        "vaults:Get a list of vaults."
      )
    
      _describe 'command' commands
    }
    
    _op "$@"
    
    # vim: ft=zsh sw=2 ts=2 et
    
  • oh that's cool, @ashneo76!

  • ashneo76
    ashneo76
    Community Member

    Thank you. I will keep updating it as I learn more about the different commands and subcommands.

  • Awesome.

This discussion has been closed.