# Speeding up my secrets

tags: bash  macOS  secrets

In Putting environment values in the keychain, I showed how I use the macOS keychain to store passwords and then read those into my shell’s environment. It worked, but it’s also a bit annoying; every time I start a new interactive shell, I have to wait five seconds for it all to happen. Now I’ve fixed that.

The problem was that every time I started the shell I made many calls to the bash function get_secret:

This means that I’m likely fetching the same data over and over even though it hasn’t changed. These values are often API keys, constants, and other things that probably haven’t changed in months. Still, I reload them several times an hour as I open new terminals.

I decided that I’d precompute everything I need and have it ready to go. That’s easy enough. I basically do what I was doing before, but I write everything to a file that will stick around. My .bash_profile then sources this text:

What’s the point of the secrets store if it’s just sitting there as text? Now comes the fun part. I’ll encrypt that string with GPG and save that. I store the destination file and target key in the secrets too, but mostly as a coordination point for all the scripts that might use this. GPG gets its plaintext directly from standard input:

On the other side, in .bash_profile, I go backward. There’s a nested if here. I don’t want to run this if I’m running a program through BBEdit. No big whoop:

The inner if is where the magic happens. I use find to compare the file modification time against what I put in day. The --mtime -1 fails if the file is over a day old. In that case, I want to regenerate the secrets file.

Once I have the secrets file, either reusing a fresh one or recreating it, I decrypt that in place. The password comes in from the keychain too and gets to gpg through standard input. The gpg output ends up in plain without touching the disk.

With the plaintext in a variable, I source that string. This little trick requires bash 4 on macOS because bash 3 had a bug that prevented this feature from working.