JIT Secrets With 1Password

Ensuring scoped environment access

The norm is to keep your environment or .env files populated with secrets, but what if I could show you how to store only safe secret references and have those secrets injected at runtime?

I’m not aware of any other password manager that has this feature, but let me know if you know of one!

Almost as JIT1 secrets, you could even keep all application configuration within 1Password2 and have it available only to the application you’re running.

First Steps

I’m not going to teach you how to install 1Password, follow their documentation to do so, if you’re reading this you likely already have this covered.

Once you have that figured out, you’re going to want to grab a secret reference from your 1Password application to test that everything is setup correctly, you can right click on a single value in your 1Password application and in the dropdown you should be able to see the option.

Secret reference

I have no clue if what comes after the vault name is sensitive, so I replaced it.

This will copy a secret reference string to your clipboard, it will look like this:

op://Private/502a50c985f858297eaf3d6/tokens/token

If we’ve configured everything correctly, we should be able to run this command and see our secret printed in our shell (masked by default).

$ TOKEN="op://Private/502a50c985f858297eaf3d6/tokens/token" op run -- printenv TOKEN
<concealed by 1Password>

You can disable concealment with the --no-masking flag, op run --no-masking will show you the actual secret, this also fixes some interactive commands that misbehave when using this,for example docker compose pull doesn’t show colors and doesn’t clean the terminal as it should creating a mess, but passing the flag before executing our docker compose commands fixes it.

Basic Usage

What you just read above is the gist of it, op run [--no-masking] -- <your-command> but that of course does not do anything without secrets being referenced, so what I like to do is within my ~/.zshrc file, I export several system-wide secret references, for example $GITHUB_TOKEN.

export KAGI_API_KEY="op://Private/Kagi/API Token"
export GITHUB_TOKEN="op://Private/GitHub/tokens/token"

I also like to create some aliases to make tool usage comfortable since I don’t want to type op run -- before all my commands, for example.

This is how 1Password’s gh integration plugin actually works.
alias gh="op run -- gh"

.env File

If you need to declare a specific set of variables, and you’ve got many you can also pass an entire .env file.

$ op run --env-file .env --no-masking -- docker compose up --detach --remove-orphans
APP_NAME=My Application
APP_ENV=production
APP_KEY=...
GITHUB_TOKEN="op://Private/GitHub/tokens/token"
...

This also opens up the ability to share a secret entry with your team over 1Password and having all secrets automatically injected into their environments, and when you need to rotate one of them you can do it from within the 1Password interface and everyone will get the latest version of it.

Footnotes:


  1. Just In Time: https://en.wikipedia.org/wiki/Just-in-time_compilation ↩︎

  2. I used to like 1Password, I still do, but I used to, too. ↩︎