Skip to content

Commit

Permalink
feat: 1Password Secrets Automation Support
Browse files Browse the repository at this point in the history
Added a new configuration option, `onepassword.mode`, that can be set to
`account` (the default value), `connect` (for 1Password Connect), or
`service` (for 1Password Service Accounts).

When in `onepassword.mode` is:

- `account`: the presence of `OP_SERVICE_ACCOUNT_TOKEN`,
  `OP_CONNECT_HOST`, and/or `OP_CONNECT_TOKEN` will cause chezmoi to
  immediately exit; their presence changes the behaviour of the
  1Password CLI.

- `connect`: the presence of `OP_SERVICE_ACCOUNT_TOKEN` or absences of
  `OP_CONNECT_HOST` and/or `OP_CONNECT_TOKEN` will cause chezmoi to
  immediately exit.

  Additionally, the use of `onepasswordDocument` or passing an `account`
  parameter will cause immediate exits.

- `service`: the absence of `OP_SERVICE_ACCOUNT_TOKEN` or presence of
  `OP_CONNECT_HOST` and/or `OP_CONNECT_TOKEN` will cause chezmoi to
  immediately exit.

  Additionally, passing an `account` parameter will cause immediate
  exits.

In all other ways, the 1Password template functions have not changed.

I changed the format of the scripts in the `onepassword*.txtar` files so
that there is better parity between the three sets of tests *and* so
that there is better / easier to read parity between the Unix and
Windows test scripts.

Closes: #3498
  • Loading branch information
halostatue committed Feb 14, 2024
1 parent df00bf2 commit 6788c54
Show file tree
Hide file tree
Showing 13 changed files with 735 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,9 @@ sections:
type: bool
default: '`true`'
description: Prompt for sign-in when no valid session is available
mode:
default: '`account`'
description: See [1Password Secrets Automation](../../user-guide/password-managers/1password.md#secrets-automation)
pass:
command:
default: '`pass`'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ The `onepassword*` template functions return structured data from
[1Password](https://1password.com/) using the [1Password
CLI](https://developer.1password.com/docs/cli) (`op`).

!!! warning

When using the 1Password CLI with biometric authentication, account
shorthand names are not available. In order to assist with this, chezmoi
supports multiple derived values from `op account list` that can be changed
into the appropriate 1Password *account-uuid*.
!!! info

### Example
When using the 1Password CLI with biometric authentication, chezmoi derives
values from `op account list` that can resolves into the appropriate
1Password *account-uuid*.

If `op account list --format=json` returns the following structure:
As an example, if `op account list --format=json` returns the following
structure:

```json
[
Expand Down Expand Up @@ -44,3 +42,11 @@ CLI](https://developer.1password.com/docs/cli) (`op`).
`account1.1password.ca` will not be a valid lookup value, but `my@account1`,
`my@account1.1password.ca`, `your@account1`, and
`your@account1.1password.ca` would all be valid lookups.

!!! warning

Chezmoi has experimental support for [1Password secrets
automation](../../user-guide/password-managers/1password.md#secrets-automation)
modes. These modes change how the 1Password CLI works and affect all
functions. Most notably, `account` parameters are not allowed on all
1Password template functions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# `onepassword` *uuid* [*vault-uuid* [*account-name*]]
# `onepassword` *uuid* [*vault* [*account*]]

`onepassword` returns structured data from [1Password](https://1password.com/)
using the [1Password
CLI](https://support.1password.com/command-line-getting-started/) (`op`).
*uuid* is passed to `op item get $UUID --format json` and the output from `op`
is parsed as JSON. The output from `op` is cached so calling `onepassword`
multiple times with the same *uuid* will only invoke `op` once. If the optional
*vault-uuid* is supplied, it will be passed along to the `op item get` call,
which can significantly improve performance. If the optional *account-name* is
*vault* is supplied, it will be passed along to the `op item get` call,
which can significantly improve performance. If the optional *account* is
supplied, it will be passed along to the `op item get` call, which will help it
look in the right account, in case you have multiple accounts (e.g., personal
and work accounts).
Expand Down Expand Up @@ -38,13 +38,8 @@ config variable.
{{ end }}
```

!!! info
!!! warning

For 1Password CLI 1.x.

```
{{ (onepassword "$UUID").details.password }}
{{ (onepassword "$UUID" "$VAULT_UUID").details.password }}
{{ (onepassword "$UUID" "$VAULT_UUID" "$ACCOUNT_NAME").details.password }}
{{ (onepassword "$UUID" "" "$ACCOUNT_NAME").details.password }}
```
When using [1Password secrets
automation](../../user-guide/password-managers/1password.md#secrets-automation),
the *account* parameter is not allowed.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# `onepasswordDetailsFields` *uuid* [*vault-uuid* [*account-name*]]
# `onepasswordDetailsFields` *uuid* [*vault* [*account*]]

`onepasswordDetailsFields` returns structured data from
[1Password](https://1password.com/) using the [1Password
Expand All @@ -12,8 +12,8 @@ interactively prompted to sign in.

The output from `op` is cached so calling `onepasswordDetailsFields` multiple
times with the same *uuid* will only invoke `op` once. If the optional
*vault-uuid* is supplied, it will be passed along to the `op get` call, which
can significantly improve performance. If the optional _account-name_ is
*vault* is supplied, it will be passed along to the `op get` call, which
can significantly improve performance. If the optional _account_ is
supplied, it will be passed along to the `op get` call, which will help it look
in the right account, in case you have multiple accounts (e.g. personal and work
accounts).
Expand Down Expand Up @@ -71,3 +71,10 @@ accounts).
}
}
```


!!! warning

When using [1Password secrets
automation](../../user-guide/password-managers/1password.md#secrets-automation),
the *account* parameter is not allowed.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# `onepasswordDocument` *uuid* [*vault-uuid* [*account-name*]]
# `onepasswordDocument` *uuid* [*vault* [*account*]]

`onepasswordDocument` returns a document from
[1Password](https://1password.com/) using the [1Password
CLI](https://developer.1password.com/docs/cli) (`op`). *uuid* is passed to `op
get document $UUID` and the output from `op` is returned. The output from `op`
is cached so calling `onepasswordDocument` multiple times with the same *uuid*
will only invoke `op` once. If the optional *vault-uuid* is supplied, it will be
will only invoke `op` once. If the optional *vault* is supplied, it will be
passed along to the `op get` call, which can significantly improve performance.
If the optional _account-name_ is supplied, it will be passed along to the `op
If the optional _account_ is supplied, it will be passed along to the `op
get` call, which will help it look in the right account, in case you have
multiple accounts (e.g., personal and work accounts).

Expand All @@ -22,3 +22,13 @@ interactively prompted to sign in.
{{- onepasswordDocument "$UUID" "$VAULT_UUID" "$ACCOUNT_NAME" -}}
{{- onepasswordDocument "$UUID" "" "$ACCOUNT_NAME" -}}
```

!!! warning

When using [1Password Connect](../../user-guide/password-managers/1password.md#1password-connect), `onepasswordDocument` is not available.

!!! warning

When using [1Password Service
Accounts](../../user-guide/password-managers/1password.md#1password-service-accounts),
the *account* parameter is not allowed.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# `onepasswordItemFields` *uuid* [*vault-uuid* [*account-name*]]
# `onepasswordItemFields` *uuid* [*vault* [*account*]]

`onepasswordItemFields` returns structured data from
[1Password](https://1password.com/) using the [1Password
Expand Down Expand Up @@ -72,45 +72,8 @@ interactively prompted to sign in.
}
```

!!! info
!!! warning

For 1Password CLI 1.x, the output is this:

```json
{
"uuid": "$UUID",
"details": {
"sections": [
{
"name": "linked items",
"title": "Related Items"
},
{
"fields": [
{
"k": "string",
"n": "D4328E0846D2461E8E455D7A07B93397",
"t": "exampleLabel",
"v": "exampleValue"
}
],
"name": "Section_20E0BD380789477D8904F830BFE8A121",
"title": ""
}
]
},
}
```

the return value of `onepasswordItemFields` will be the map:

```json
{
"exampleLabel": {
"k": "string",
"n": "D4328E0846D2461E8E455D7A07B93397",
"t": "exampleLabel",
"v": "exampleValue"
}
}
```
When using [1Password secrets
automation](../../user-guide/password-managers/1password.md#secrets-automation),
the *account* parameter is not allowed.
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ interactively prompted to sign in.
```console
$ op read --no-newline op://vault/item/field
```

!!! warning

When using [1Password secrets
automation](../../user-guide/password-managers/1password.md#secrets-automation),
the *account* parameter is not allowed.
104 changes: 72 additions & 32 deletions assets/chezmoi.io/docs/user-guide/password-managers/1password.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ Documents can be retrieved with:
{{- onepasswordDocument "$UUID" -}}
```

The output of `op item get $UUID--format json` (`op get item $UUID`) is
available as the `onepassword` template function. chezmoi parses the JSON output
and returns it as structured data. For example, if the output is:
The output of `op item get $UUID --format json` is available as the
`onepassword` template function. chezmoi parses the JSON output and returns it
as structured data. For example, if the output is:

```json
{
Expand Down Expand Up @@ -93,25 +93,6 @@ or:
{{ end }}
```

!!! info

1Password CLI 1.x returns a simpler structure:

```json
{
"uuid": "$UUID",
"details": {
"password": "$PASSWORD"
}
}
```

This allows for the syntax:

```
{{ (onepassword "$UUID").details.password }}
```

`onepasswordDetailsFields` returns a reworked version of the structure that
allows the fields to be queried by key:

Expand Down Expand Up @@ -146,23 +127,17 @@ Additional fields may be obtained with `onepasswordItemFields`; not all objects
in 1Password have item fields. This can be tested with:

```console
$ chezmoi execute-template "{{ onepasswordItemFields \"$UUID\" | toJson }}" | jq .
$ chezmoi execute-template "{{ onepasswordItemFields \"$UUID\" | toJson }}" | \
jq .
```

!!! note

The extra `-` after the opening `{{` and before the closing `}}` instructs
the template language to remove any whitespace before and after the
substitution. This removes any trailing newline added by your editor when
saving the template.

## Sign-in prompt

chezmoi will verify the availability and validity of a session token in the
current environment. If it is missing or expired, you will be interactively
prompted to sign-in again.

In the past chezmoi used to simply exit with an error when no valid session was
In the past chezmoi used to exit with an error when no valid session was
available. If you'd like to restore this behavior, set the `onepassword.prompt`
configuration variable to `false`, for example:

Expand All @@ -173,6 +148,71 @@ configuration variable to `false`, for example:

!!! danger

Do not use prompt on shared machines. A session token verified or acquired
Do not use `prompt` on shared machines. A session token verified or acquired
interactively will be passed to the 1Password CLI through a command line
parameter, which is visible to other users of the same system.

## Secrets Automation

chezmoi has experimental support for secrets automation with [1Password
Connect](https://developer.1password.com/docs/connect/) and [1Password Service
Accounts](https://developer.1password.com/docs/service-accounts). These might be
used on restricted machines where you cannot or do not wish to install a full
1Password desktop application.

When these features are used, the behavior of the 1Password CLI changes, so
chezmoi requires explicit configuration for either connect or service account
modes using the `onepassword.mode` configuration option. The default, if not
specified, is `account`:

```toml title="~/.config/chezmoi/chezmoi.toml"
[onepassword]
mode = "account"
```

In `account` mode, chezmoi will stop with an error if the environment variable
`OP_SERVICE_ACCOUNT_TOKEN` is set, or if both environment variables
`OP_CONNECT_HOST` and `OP_CONNECT_TOKEN` are set.

!!! info

Both 1Password Connect and Service Accounts prevent the CLI from working
with multiple accounts. If you need access to secrets from more than one
1Password account, do not use these features with chezmoi.

### 1Password Connect

Once 1Password Connect is
[configured](https://developer.1password.com/docs/connect/connect-cli#requirements),
and `OP_CONNECT_HOST` and `OP_CONNECT_TOKEN` are properly set, set
`onepassword.mode` to `connect`.

```toml title="~/.config/chezmoi/chezmoi.toml"
[onepassword]
mode = "connect"
```

In `connect` mode:

- the `onepasswordDocument` template function is not available,
- `account` parameters are not allowed in 1Password template functions,
- chezmoi will stop with an error if one or both of `OP_CONNECT_HOST` and
`OP_CONNECT_TOKEN` are unset, or if `OP_SERVICE_ACCOUNT_TOKEN` is set.

### 1Password Service Accounts

Once a 1Password service account has been
[created](https://developer.1password.com/docs/service-accounts/use-with-1password-cli/#requirements)
and `OP_SERVICE_ACCOUNT_TOKEN` is properly set, set `onepassword.mode` to
`service`.

```toml title="~/.config/chezmoi/chezmoi.toml"
[onepassword]
mode = "service"
```

In `service` mode:

- `account` parameters are not allowed in 1Password template functions,
- chezmoi will stop with an error if `OP_SERVICE_ACCOUNT_TOKEN` is unset, or if
both of `OP_CONNECT_HOST` and `OP_CONNECT_TOKEN` are set.
1 change: 1 addition & 0 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2700,6 +2700,7 @@ func newConfigFile(bds *xdg.BaseDirectorySpecification) ConfigFile {
Onepassword: onepasswordConfig{
Command: "op",
Prompt: true,
Mode: onepasswordModeAccount,
},
Pass: passConfig{
Command: "pass",
Expand Down

0 comments on commit 6788c54

Please sign in to comment.