Skip to content
DMNO
🚧 DMNO is still in beta! Use with caution!
✨ If you've tried DMNO or looked through the docs, let us know what you think!

1Password plugin

DMNO’s 1Password plugin allows you to securely access your stored secrets in 1Password. This plugin uses the 1Password CLI by means of a Service Account. It is compatible with any account type. Note that rate limits vary by account type, you can read more about that in the 1Password Developer documentation.

Installation

Install the package in your service(s) that will use config from 1password.

Terminal window
npm add @dmno/1password-plugin

After installation, you’ll need to initialize the plugin in your dmno config and wire it up to the config path that will hold your 1password service account token. It’s ok if you have not created this service account yet - we’ll do that in the next section.

.dmno/config.mts
import { OnePasswordDmnoPlugin, OnePasswordTypes } from '@dmno/1password-plugin';
const OnePassBackend = new OnePasswordDmnoPlugin('1pass/prod', {
token: configPath('OP_TOKEN'),
});
export default defineDmnoService({
schema: {
OP_TOKEN: {
extends: OnePasswordTypes.serviceAccountToken,
// NOTE - the type itself is already marked as sensitive 🔐
},
},
});

Injecting the plugin in monorepo services

In a monorepo, if you are managing config for multiple services in a single vault, you should initialize the plugin instance once in your root service as seen above, and then inject it in the child services. Note we need that same id we set during initialization.

apps/some-service/.dmno/config.mts
import { OnePasswordDmnoPlugin } from '@dmno/1password-plugin';
// inject the already initialized plugin instead of re-initializing it
const OnePassBackend = OnePasswordDmnoPlugin.injectInstance('1pass/prod');

Setup vault & service account

  1. Create a vault in your 1Password account. This is where you’ll store your secrets. You can create multiple vaults for different environments or services. link

  2. Create a service account in your 1Password account. This is a separate account that has access to the vault(s) you created. You can create multiple service accounts for different environments or services. link

  3. Grant vault access to the service account. This is done in the 1Password web interface. You can add multiple service accounts to a single vault. link

This service account token will now serve as your “secret-zero” - which grants access to the rest of your sensitive config stored in 1password. It must be set locally and in deployed environments, and as it is sensitive, we must pass in the value as an override rather than storing it within the config. Locally this usually means storing it in your .env.local and on a deployed environment you’ll usually set it within some kind of UI, wherever you would normally pass in secrets.

.dmno/.env.local
OP_TOKEN=ops_abc123...

Note that the config path of OP_TOKEN is arbitrary and you can see how it was wired up from the config to the plugin input above. If you are using multiple vaults and service accounts, you may have something more like OP_PROD_TOKEN and OP_NON_PROD_TOKEN.


Add your items

DMNO supports a few different ways to reference items in 1Password.

Managing lots of individual 1password items and connecting them to your config can be a bit tedious, so we recommend storing multiple items together in a .env style text blob. Using this method, we’ll have a single 1password item that can have one text entry per service containing the .env blob. This would be similar to applying a .env.local file as overrides, except they are secured and shared via 1password. This also makes it incredibly easy to migrate from using local .env files.

To use this method, we need to tell the plugin which 1password item will store our .env blob(s). As this value is static and not sensitive, we can use a static value as our plugin input.

.dmno/config.mts
import { OnePasswordDmnoPlugin, OnePasswordTypes } from '@dmno/1password-plugin';
const OnePassBackend = new OnePasswordDmnoPlugin('1pass/prod', {
token: configPath('OP_TOKEN'),
envItemLink: 'https://start.1password.com/open/i?a=I3GUA2KU6BD3FBHA47QNBIVEV4&v=ut2dftalm3ugmxc6klavms6tfq&i=n4wmgfq77mydg5lebtroa3ykvm&h=dmnoinc.1password.com',
});
export default defineDmnoService({
schema: {
OP_TOKEN: {
extends: OnePasswordTypes.serviceAccountToken,
},
SOME_SECRET_ITEM: {
sensitive: true,
value: OnePassBackend.item(),
}
},
});

Using specific 1password items

If you already have lots of indivdual items in 1password, or you just don’t want to use the blob method, you can wire up invididual config items to specific 1password items. We provide several methods to do so. Note that while a 1password reference (e.g., op://vaultname/itemname/path) points all the way to a specific value, the other methods only get us to an item which usually contains multiple entries (account id, secret key, etc). In these cases you must also pass in an additional path to the specific entry. These paths use the entry labels.

export default defineDmnoService({
schema: {
// using item private link
ITEM_WITH_LINK: {
value: OnePassBackend.itemByLink(
'https://start.1password.com/open/i?a=I3GUA2KU6BD3FBHA47QNBIVEV4&v=ut2dftalm3ugmxc6klavms6tfq&i=n4wmgfq77mydg5lebtroa3ykvm&h=dmnoinc.1password.com',
'somepath',
),
},
// using vault + item UUIDs
ITEM_WITH_IDS: {
value: OnePassBackend.itemById('vaultUuid', 'itemUuid', 'somepath'),
},
// using item reference
ITEM_WITH_REFERENCE: {
value: OnePassBackend.itemByReference('op://vaultname/itemname/path'),
},
},
});