Skip to main content

Artisanal Scripting: Keeping Secrets

Davidheadshot David Alberto

Header (20)

Photo by James Sutton on Unsplash

As mentioned in a previous post, I keep most of my configuration files and scripts in a git repository. Files that must remain secret, like ssh private keys, the .netrc file and the like should never end up there.

I use a few password manager tools, but one of my favorite is pass (can be installed via brew install pass). I like this tool because it’s command-line based, can be backed by a git repository and uses gpg to encrypt the passwords. Additionally, since multi-line passwords are allowed, you can store any file there.

I wrote two scripts to manage my secret files: unlock-secrets and lock-secrets.

The unlock-secrets script does an rsync of the gpg files to a temporary folder, then it runs gpg to decrypt the files and then creates symbolic links to the home directory. The gpg files are then deleted from the temporary directory.

The lock-secrets does the opposite: for each file in the temporary directory, the symbolic link gets deleted, then the files get gpg encrypted and they are copied over to the .password-store directory.

Placing the unencrypted secret files in a temporary directory ensures that when shutting down or restarting the computer they’ll get automatically deleted.

Here’s what the scripts look like:

 

#!/usr/bin/env bash

if [ -d /tmp/.secrets ]; then
  if [ -d ~/.password-store/.secrets ]; then
    pushd ~/.password-store/.secrets
    find . -type f -name '*.gpg' | while read i; do
      k=${i%*.gpg}
      j=${k/./~}
      if [ -h $j ]; then
        diff -q $j <(gpg --decrypt $i) || cp $(readlink $j) /tmp/.secrets/$k && rm $(readlink $j) $j
      fi
    done
    popd
  fi
  find /tmp/.secrets -type f -name '*.gpg' -delete
  find /tmp/.secrets -type f -exec gpg --yes --quiet --encrypt -r pass {} \;
  rsync --remove-source-files --prune-empty-dirs -a --include='*/' --include='*.gpg' --exclude='*' /tmp/.secrets/ ~/.password-store/.secrets/

  pushd ~/.password-store/.secrets
  git add -A
  git commit -m "$(date)"
  popd
fi

#!/usr/bin/env bash

( cd ~/.password-store/.secrets
  find . -type f -not -name '*.gpg' | while read i; do
    ln -sf ${i/./$PWD} ${i/./~}
  done
  rsync -a --exclude='.git' $PWD/ /tmp/.secrets && find /tmp/.secrets -type f -not -name '*.gpg' -delete
)
( cd /tmp/.secrets
  find . -type f -name '*.gpg' | while read i; do
    j=${i/./~}; j=${j%*.gpg}
    [ -h $j -a ! -e "$(readlink $j)" ] && rm $j
  done
  find . -type f -name '*.gpg' | while read i; do
    j=${i%*.gpg}
    tmp=/tmp/${j/./.secrets}
    gpg --yes --quiet --decrypt --output $tmp $i && rm $i
    chmod 600 $tmp
    ln -sf $tmp ~/$j
  done
)


That’s about it! Whenever I need to use my secrets I just run unlock-secrets . Then my .bash_logout script automatically calls lock-secrets to get any updates back into the password store.

 

Davidheadshot

Written by

David Alberto

David is a Lead Software Engineer at Appian.