Skip to content

Commit

Permalink
more docs work
Browse files Browse the repository at this point in the history
  • Loading branch information
theoephraim committed Aug 17, 2024
1 parent 1427d93 commit cd1ed0a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 17 deletions.
46 changes: 33 additions & 13 deletions packages/docs-site/src/content/docs/docs/plugins/1password.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ description: DMNO's 1Password plugin allows you to securely access your stored s
import { Steps, Icon } from '@astrojs/starlight/components';
import TabbedCode from '@/components/TabbedCode.astro';

DMNO's [1Password](https://1password.com/) plugin allows you to securely access your secrets stored in 1Password. This plugin uses their [JavaScript SDK](https://github.com/1Password/onepassword-sdk-js/) to authenticate via a [service account](https://developer.1password.com/docs/service-accounts). Additionally, for local development, you can opt-in to use your system-installed [1Password CLI](https://developer.1password.com/docs/cli/get-started/) and its [integration with the 1Password desktop app](https://developer.1password.com/docs/cli/get-started/#step-2-turn-on-the-1password-desktop-app-integration), which uses your personal account gated behind biometric unlocking of the desktop app. This plugin is compatible with any 1Password account type (personal, family, teams, business), but note that [rate limits](https://developer.1password.com/docs/service-accounts/rate-limits/) vary by account type.
DMNO's [1Password](https://1password.com/) plugin allows you to securely access your secrets stored in 1Password. This plugin uses their [JavaScript SDK](https://github.com/1Password/onepassword-sdk-js/) to authenticate using a [service account](https://developer.1password.com/docs/service-accounts). Additionally, for local development, you can opt-in to use your system-installed [1Password CLI](https://developer.1password.com/docs/cli/get-started/) and its [integration with the 1Password desktop app](https://developer.1password.com/docs/cli/get-started/#step-2-turn-on-the-1password-desktop-app-integration). This plugin is compatible with any 1Password account type (personal, family, teams, business), but note that [rate limits](https://developer.1password.com/docs/service-accounts/rate-limits/) vary by account type.

## Installation & setup

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

<TabbedCode packageName="@dmno/1password-plugin" />

Expand Down Expand Up @@ -42,7 +42,7 @@ In this case we used `1pass`, but you can imagine splitting vaults and access, a
:::

### Injecting the plugin in monorepo services
In a monorepo, you are likely managing secrets for multiple services. If you will be using the same service account(s) to access those secrets, you can initialize a plugin instance once in your root service as seen above, and then _inject_ it in the child services. Note we must use that same id we set during initialization.
In a monorepo, you are likely managing secrets for multiple services. If you will be using the same service account(s) to access those secrets, you can initialize a plugin instance once in your root service as seen above, and then _inject_ it in child services. Note we must use that same id we set during initialization.

```typescript title='apps/some-service/.dmno/config.mts'
import { OnePasswordDmnoPlugin } from '@dmno/1password-plugin';
Expand All @@ -60,9 +60,9 @@ If you already use 1password and your secrets live in a vault that holds other i

<Steps>

1. **Create a vault** in your 1Password account which will be used to hold your secrets. You can create multiple vaults to segment access to different environments, services, etc. You can use any 1password app, the web app, or the CLI. [link](https://support.1password.com/create-share-vaults/#create-a-vault)
1. **Create a vault** in your 1Password account which will be used to hold your secrets. You can create multiple vaults to segment access to different environments, services, etc. This can be done using any 1password app, the web app, or the CLI. [link](https://support.1password.com/create-share-vaults/#create-a-vault)

2. **Create a new service account** and grant access to necessary vault(s). This is a special account used for machine-to-machine communication. This is done in the 1Password web interface. Be sure to copy the new service account token or save it in another vault. [link](https://developer.1password.com/docs/service-accounts/get-started/)
2. **Create a new service account** and grant access to necessary vault(s). This is a special account used for machine-to-machine communication. This can only be done in the 1Password web interface. Be sure to copy the new service account token or save it in another vault. [link](https://developer.1password.com/docs/service-accounts/get-started/)
:::note[Vault access set during creation only]
Vault access rules cannot be edited after creation, so if your vault setup changes, you will need to create new service account(s) and update the tokens.
:::
Expand Down Expand Up @@ -105,7 +105,7 @@ During local development, you may find it convenient to skip the service account

3. **Enable the desktop app + CLI integration**. [docs](https://developer.1password.com/docs/cli/get-started/#step-2-turn-on-the-1password-desktop-app-integration)

4. **Run `op signin` to log in on the CLI**. Ensure you are logged in to the correct account. You can run `op whoami` to see which account is currently connected to the CLI.
4. **Run `op signin` to sign in on the CLI**. Ensure you are logged in to the correct account. You can run `op whoami` to see which account is currently connected to the CLI.
</Steps>

With this option enabled, if the resolved service account token is empty, we will call out to the `op` cli installed on your machine (it must be in your `$PATH`) and use the auth it provides. With the desktop app integration enabled, it will call out and may trigger biometric verification to unlock. It is secure and very convenient!
Expand All @@ -118,11 +118,11 @@ Keep in mind that this method is connecting as _YOU_ who may have more access th

## Add items to your schema

With the plugin initialized and access wired up, now we must update our config schema to know which items will be coming from 1Password and where to look. DMNO supports a few different ways to reference items in 1Password:
With the plugin initialized and access wired up, now we must update our config schema to connect specific config values to data stored in 1Password. DMNO supports a few different ways to reference items in 1Password:

### Using a `.env` blob

Managing lots of individual 1Password items and connecting them to your config can be a bit tedious. So, when getting started, 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 and look up items by their key - similar to applying a `.env.local` file as overrides, except they are secured and shared via 1Password. This also makes it easier to migrate from using local `.env` files.
Managing lots of individual 1Password items and connecting them to your config can be a bit tedious. So, when getting started, 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 and look up items by their key - similar to applying a `.env.local` file as overrides, except they are secured and shared via 1Password. This also makes it easier to migrate from passing around `.env` files.

<Steps>

Expand All @@ -141,7 +141,7 @@ Managing lots of individual 1Password items and connecting them to your config c

3. **Wire up plugin instance to the new item** using its _private link_. While viewing the item in the 1Password app, click the 3 dots in the top right and click `Copy Private Link`. As this link does not contain anything sensitive, we can use a static value as our plugin input.

4. **Update items in your config schema** to use the `.item()` value resolver for anything that will be stored in the linked 1Password item. When we resolve your config values, if an item is not found, it will result in a `ResolutionError` with helpful info about how to fix it.
4. **Update items in your config schema** to use the `.item()` value resolver for anything that will be stored in the linked 1Password item. When we resolve your config values, if a match is not found, it will result in a `ResolutionError` with helpful info about how to fix it.

</Steps>

Expand All @@ -166,6 +166,26 @@ export default defineDmnoService({
});
```

You can also override the key used to lookup the value in the `.env` blob. This can be useful if you need to save multiple values toggled by some other logic.

```typescript title=".dmno/config.mts"
export default defineDmnoService({
schema: {
SOME_API_SECRET: {
sensitive: true,
value: switchBy('APP_ENV', {
// uses the default key of "SOME_API_SECRET"
_default: OnePassBackendDev.item(),
// uses overridden key
staging: OnePassBackendDev.item('SOME_API_SECRET_STAGING'),
// uses the default key but looking in a different 1pass item
staging: OnePassBackendProduction.item(),
}),
},
},
});
```

#### Lookup convention example
Values are looked up within the linked 1Password item using a simple convention. We expect to find a _text field_ within the item with a label set to the current [service name](/docs/guides/schema/#service-names). The contents of that item are parsed as a [`.env` file](https://dotenvx.com/docs/env-file), and we look up items using the config item key. If no match is found, we will also look in an additional field with the label `_default`.

Expand All @@ -176,7 +196,7 @@ For example, in the item above, an item with the key `ONE_MORE` would fallback t

### Using specific 1Password items

If you already have lots of individual items in 1Password, or you just don't want to use the blob method, we provide several methods to wire up individual config items to specific values in 1Password. Note that while a 1Password reference (e.g., `op://vaultname/itemname/path`) is easier to use in some ways, they are based on field labels and are not stable, so the other methods are preferred.
If you already have lots of individual items in 1Password, or you just don't want to use the blob method, we provide several methods to wire up individual config items to specific values in 1Password. Note that while 1Password reference URIs (e.g., `op://vaultname/itemname/path`) are easier to use in some ways, they are based on field labels and are not stable, so the other methods are preferred.

```ts
export default defineDmnoService({
Expand Down Expand Up @@ -216,12 +236,12 @@ The secret reference for invidivual fields within an item can be found by clicki
In order to avoid rate limits and keep dev server restarts extremely fast, we heavily cache data fetched from external sources. After updating secrets in 1password, if the item has been cached, you'll need to clear the cache to see it take effect.

- Use the [`dmno clear-cache` command](/docs/reference/cli/clear-cache/) to clear the cache once
- The `dmno` cli's [`resolve`](/docs/reference/cli/resolve/) and [`run`](/docs/reference/cli/run/) commands have cache related flags:
- The [`dmno resolve`](/docs/reference/cli/resolve/) and [`dmno run`](/docs/reference/cli/run/) commands have cache related flags:
- `--skip-cache` - skips caching logic altogether
- `--clear-cache` - clears the cache once before continuing as normal

:::tip[Active config iteration]
While you are actively working on the config itself, `dmno resolve -w --skip-cache` will combine watch mode with skipping cache logic altogether.
While you are actively working on the config itself, `dmno resolve -w --skip-cache` will combine watch mode with skipping cache logic.

When you are satisfied, _clear_ the cache once more and you are good to go.
Once you are satisfied, _clear_ the cache once more and you are good to go.
:::
8 changes: 4 additions & 4 deletions packages/plugins/1password/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export class OnePasswordDmnoPlugin extends DmnoPlugin<OnePasswordDmnoPlugin> {


/**
* DMNO resolver to fetch a 1password value from a .env blob within a text field.
* resolver to fetch a 1password value from a .env blob within a text field.
*
* Plugin instance must be initialized with `envItemLink` input set to use this resolver.
*
Expand Down Expand Up @@ -287,7 +287,7 @@ export class OnePasswordDmnoPlugin extends DmnoPlugin<OnePasswordDmnoPlugin> {
}

/**
* DMNO resolver to fetch a 1password value using a "private link" and field ID
* resolver to fetch a 1password value using a "private link" and field ID
*
* To get an item's link, right click on the item and select `Copy Private Link` (or select the item and click the ellipses / more options menu)
*
Expand Down Expand Up @@ -320,7 +320,7 @@ export class OnePasswordDmnoPlugin extends DmnoPlugin<OnePasswordDmnoPlugin> {


/**
* DMNO resolver to fetch a 1password value using UUIDs and a field ID
* resolver to fetch a 1password value using UUIDs and a field ID
*
* @see https://dmno.dev/docs/plugins/1password/
*/
Expand Down Expand Up @@ -403,7 +403,7 @@ export class OnePasswordDmnoPlugin extends DmnoPlugin<OnePasswordDmnoPlugin> {


/**
* DMNO resolver to fetch a 1password value using a secret reference URI
* resolver to fetch a 1password value using a secret reference URI
*
* @see https://dmno.dev/docs/plugins/1password/
* @see https://developer.1password.com/docs/cli/secret-reference-syntax
Expand Down

0 comments on commit cd1ed0a

Please sign in to comment.