# Setting Env Vars From 1password

> Source secrets into your shell from the 1password CLI so your dotfiles can live in git with nothing sensitive on disk.

- Author: Ross Edman
- Published: 2021-10-02
- Tags: security, shell
- URL: https://rossedman.io/blog/computers/setting-env-vars-from-1password/

At some point in time, we all have to set secrets in our terminal. If you want to keep your dotfiles in git this becomes a problem. There are plenty of creative ways around that issue but I've found sourcing passwords directly from a secret manager a great way to keep your secrets up to date, your dotfiles clean and no sensitive passwords lying around on disk. In this post I will show you how I source my passwords directly from 1password. 

I'm assuming before diving in that you already have a 1password account.

## Setting Up 1password CLI

First, let's install the [1password CLI](https://support.1password.com/command-line/)

```
brew install --cask 1password-cli
```

Once you have the CLI installed, you need to know your 1password signin address. This is the url you use to signin to reach your vaults. So maybe yours is something like `doodoo.1password.com/signin`. Well your signin key for the `op` CLI is then `doodoo` and you would then login like this

```shell
op signin doodoo
```

Once you know that information you can place this in your `~/.zshrc` or `~/.bashrc` and load this on every new terminal session

```shell
eval "$(op signin doodoo)"
```

Every time you launch a terminal it will now ask for your 1password password and you will have access to your secrets

```
Enter the password for <your-email@email.com> at doodoo.1password.com:
```

## Loading Secrets

So now that you are logged in, how do you source secrets into your shell? Here is an example from one of my secrets (the content has been changed). I've removed a lot of unnecessary data from this payload just to show the structure.

```json
❯ op get item github-pat --vault Private | jq .
{
  ...
  "details": {
    "fields": [],
    "notesPlain": "",
    "password": "some-random-long-password-string",
    "passwordHistory": [],
    "sections": []
  },
  "overview": {
    "title": "github-pat",
  }
}
```

This is really useful, but even more useful is the `op` CLI provides a `--fields` flag to return just the data you need. So we can return a single piece of information using this flag like so.

```shell
❯ op get item github-pat --fields password --vault Private
some-random-long-password-string
```

Awesome, right? So now, retrieving and setting this in your environment becomes as simple as placing this in some of your dotfiles

```shell
export GITHUB_TOKEN=$(op get item github-pat --fields password --vault Work)
```

## Automatically Logging In With iTerm (Optional)

Typing in your password to login is pretty annoying. There is a way to automate this in iTerm using Triggers. Whenever a certain phrase appears, iTerm will dropdown a select to use passwords from its Vault. If you navigate to `iTerm -> Preferences -> Profiles -> Advanced` there will be a section that says `Triggers`, click `Edit`. 

![1password iTerm trigger](https://rossedman.io/images/1password-iterm.png)

When you create a new trigger you want the regular expression to trigger on to be `doodoo.1password.com` and the action you want is `Open Password Manager`. For parameters I have `1password` set with instant and enabled checked.

Now that you have that setup you need place the password in your password manager. To do this, navigate to `Windows -> Password Manager` and create an entry for `1password`. This is what the Trigger will look for when it finds a match for `doodoo.1password.com`.

Now if you create a new iTerm session you should immediately see a dropdown whenever `Enter the password for <your-email@email.com> at doodoo.1password.com:` appears!

## Going Further With direnv

The icing on the cake for me is I use all of this in conjunction with [`direnv`](https://direnv.net/). This little project loads environment variables by walking directories and looking for `.envrc` files to load. In conjunction with `1password` this means you can load environment variables from your secret manager depending on your directly location. Here is an example of my directory structure for programming:

```diff
 /Users/redman/code
 ├── work
+|   ├── .envrc
 │   └── twilio
 ├── github.com
+|   ├── .envrc
 │   ├── rossedman
 │   │   └── rossedman.github.io
```

Each of these directories requires different github secrets. The way `direnv` works is it will load the `.envrc` for all directories under the `.envrc`. Each of these directories now loads the appropriate access token when I'm working in them so I don't have to switch or think about changing it. It loads it directly from 1password so its always up to date. If I need to rotate a PAT, I replace it in 1password and open a new terminal.

Here are what each `.envrc` looks like. Notice that I name the secrets the same and place them in different Vaults as well. This gives me clean separation in 1password.

```shell
# work .envrc
export GITHUB_TOKEN=$(op get item github-pat --fields password --vault Work)

# personal .envrc
export GITHUB_TOKEN=$(op get item github-pat --fields password --vault Personal)
```

Now when you navigate to these directories it will load from 1password. Here is an example

```shell
❯ cd ~/code/work
direnv: loading ~/code/work/.envrc
direnv: export ~GITHUB_TOKEN ~GITHUB_URL
```

## Conclusion

That's it! I hope you learned something. I believe this is a very effective way to manage passwords especially for multipurpose computers where you need to switch contexts frequently and also need a secure solution to not store passwords on disk. Of note, that if you store your password in `iTerm's` Password Manager you are removing some of the security benefits of this. If someone ever accessed your laptop they would also be able to just hit `Return` and get passwords. Happy hacking!
