1Password is an excellent password manager, and recently I began exploring the value it can provide for secrets management, and boy is it easy! If your team is using 1Password, you can use your vaults
Last updated
Prerequisites
In order to follow this tutorial, you'll need:
A . If you're using the legacy version of 1Password where you self-host your vaults, this guide likely won't work.
The 1Password CLI. You can find the .
Optional: Create a vault
While this step is optional to complete the tutorial, it's a good practice to have your secrets and credentials organized in a way that segregates access. For this example, let's pretend our project is the following:
JavaScript based SaaS Application
Engineering Team:
1 Principal Engineer
1 Senior-level Engineer
1 Junior-level Engineer
Two Environments
Non-Prod: Everyone has access
Production: Only Principal and Senior
Given this context, we'd want our Junior Engineer to be able to view/add/edit non-production secrets, but not production ones. Let's start by first creating a vault which is accessible by all engineers and call it NewApp Non-Prod:
Add secrets to vault
Next, let's populate a few different credentials in this vault. For this tutorial, I'm going to keep things simple and create two different items. For our first item, let's create NewApp (Local). This is where I would put shared secrets that are owned by the application itself. In this example, I've defined a few items like URL, admin password, postgres connection string, token salt, and JWT Secret:
Create a .env-template file
Within your project, create a new file called .env-template, which we'll use as a template for creating a .env file used by the application at runtime. Let's scaffold our template by mapping out the environment variables our application requires:
Using the 1Password CLI
Now that we have our vault details, let's list the items of our NewApp Non-Prod vault. To list items in a vault, you'll execute the command op item list --vault <vault name or guid>:
Finally, we'll tell the CLI to fetch us the details of an item in JSON format, so we can copy the reference pointer to our template. You can achieve this wit the command op item get <item name or guid> --format json
The reference pointers will be formatted as either op://<vault>/<item>/<property> or op://<vault>/<item>/<section>/<property> depending how you stored the secret in your item. The different paramaters can either be that property's label/title/name or guid.
With the reference value copied, return to your .env-template file and paste the pointer as the environment variable value. Repeat the process of fetching the reference values until your .env-template file is complete. What mine looked like after I finished:
Now that we have our .env-template fully configured, we can run the command op inject -i .env-template -o .env which will create a .env file with the secret values. In the screenshot I have below, you can compare the template against the output of the command:
Add Project Shortcut
Now that you have a process to easily generate your .env, let's make it easy for other team members to use by scripting the process. Since we're working with a JavaScript project for this tutorial, let's add a script to our package.json file so developers only have to run npm run env:generate to create their own .env files locally:
{
"name": "@mainwaring/example-project",
"version": "2022.1.0",
"description": "This is my example project!",
"main": "index.js",
"scripts": {
"env:generate": "eval $(op signin) && op inject -i .env-template -o .env",
"test": "jest"
},
"author": "Joe Mainwaring <joe@mainwaring.dev>",
"license": "MIT"
}
You'll notice in this example, my script is eval $(op signin) && op inject -i .env-template -o .env and not just op inject -i .env-template -o .env. By chaining the signin and iject commands, the developer will be be immediately presented with the signin workflow if they aren't already authenticated. This would otherwise require the developer to run 2-3 additional steps on their own if their terminal session was unauthenticated.
Creating a new Vault in 1Password
An Example of a server item in a 1Password vault
Next let's add a second item to our vault for a third-party integration. For this example, we'll use the service and define our test Account SID and Auth Token which is used by the application at startup:
An example of a third-party credential with secrets
An example of a .env-template file before 1Password reference values
Now that we have our .env-template scaffolded, let's shift our focus towards the 1Password CLI. First, start by with the command eval $(op signin). The CLI will ask you to confirm which account you're authenticating with, and you'll be prompted to provide your password.
Once you've authenticated, you'll want to first start by . To list your vaults, execute the command op vault list:
Using the 1Password CLI to list vaults
Using the 1Password CLI to list items in a vault
A comparison between the .env-template and the compiled .env files