From 6a948ffb6e9bea5691b5f3115b4c4b31645d5295 Mon Sep 17 00:00:00 2001 From: Austin Ziegler Date: Sun, 11 Feb 2024 14:15:33 -0500 Subject: [PATCH] feat: 1Password Secrets Automation Support 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 --- .gitignore | 1 + .../configuration-file/variables.md.yaml | 3 + .../templates/1password-functions/index.md | 22 +- .../1password-functions/onepassword.md | 19 +- .../onepasswordDetailsFields.md | 13 +- .../onepasswordDocument.md | 16 +- .../onepasswordItemFields.md | 47 +---- .../1password-functions/onepasswordRead.md | 6 + .../user-guide/password-managers/1password.md | 104 ++++++--- internal/cmd/config.go | 1 + internal/cmd/onepasswordtemplatefuncs.go | 100 ++++++++- .../cmd/testdata/scripts/onepassword2.txtar | 115 ++++++++-- .../scripts/onepassword2connect.txtar | 189 +++++++++++++++++ .../scripts/onepassword2service.txtar | 198 ++++++++++++++++++ 14 files changed, 705 insertions(+), 129 deletions(-) create mode 100644 internal/cmd/testdata/scripts/onepassword2connect.txtar create mode 100644 internal/cmd/testdata/scripts/onepassword2service.txtar diff --git a/.gitignore b/.gitignore index 15197d1b2ea5..19631b458298 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.pdm-python /.vagrant /COMMIT /bin/actionlint diff --git a/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml b/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml index b31dcf8f5e19..183a040289db 100644 --- a/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml +++ b/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml @@ -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`' diff --git a/assets/chezmoi.io/docs/reference/templates/1password-functions/index.md b/assets/chezmoi.io/docs/reference/templates/1password-functions/index.md index 59be71b94ec5..4c6ad1d83a6d 100644 --- a/assets/chezmoi.io/docs/reference/templates/1password-functions/index.md +++ b/assets/chezmoi.io/docs/reference/templates/1password-functions/index.md @@ -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 [ @@ -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. diff --git a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepassword.md b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepassword.md index 2796a8f1e069..cd0a04fec245 100644 --- a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepassword.md +++ b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepassword.md @@ -1,4 +1,4 @@ -# `onepassword` *uuid* [*vault-uuid* [*account-name*]] +# `onepassword` *uuid* [*vault* [*account*]] `onepassword` returns structured data from [1Password](https://1password.com/) using the [1Password @@ -6,8 +6,8 @@ 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). @@ -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. diff --git a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordDetailsFields.md b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordDetailsFields.md index 795dee3bc9ce..94c21f465553 100644 --- a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordDetailsFields.md +++ b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordDetailsFields.md @@ -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 @@ -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). @@ -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. diff --git a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordDocument.md b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordDocument.md index cee23232551b..e847db98cbd9 100644 --- a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordDocument.md +++ b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordDocument.md @@ -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). @@ -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. diff --git a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordItemFields.md b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordItemFields.md index b89bf95c93e1..041795572490 100644 --- a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordItemFields.md +++ b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordItemFields.md @@ -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 @@ -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. diff --git a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordRead.md b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordRead.md index 147bdf3ded04..44fefe230d74 100644 --- a/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordRead.md +++ b/assets/chezmoi.io/docs/reference/templates/1password-functions/onepasswordRead.md @@ -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. diff --git a/assets/chezmoi.io/docs/user-guide/password-managers/1password.md b/assets/chezmoi.io/docs/user-guide/password-managers/1password.md index 42d8fe6b8186..915a6fb9fc3d 100644 --- a/assets/chezmoi.io/docs/user-guide/password-managers/1password.md +++ b/assets/chezmoi.io/docs/user-guide/password-managers/1password.md @@ -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 { @@ -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: @@ -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: @@ -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. diff --git a/internal/cmd/config.go b/internal/cmd/config.go index d5e7a486ae34..3a6db01e32ba 100644 --- a/internal/cmd/config.go +++ b/internal/cmd/config.go @@ -2700,6 +2700,7 @@ func newConfigFile(bds *xdg.BaseDirectorySpecification) ConfigFile { Onepassword: onepasswordConfig{ Command: "op", Prompt: true, + Mode: onepasswordModeAccount, }, Pass: passConfig{ Command: "pass", diff --git a/internal/cmd/onepasswordtemplatefuncs.go b/internal/cmd/onepasswordtemplatefuncs.go index bc7c22817004..d411c9c66c12 100644 --- a/internal/cmd/onepasswordtemplatefuncs.go +++ b/internal/cmd/onepasswordtemplatefuncs.go @@ -13,6 +13,14 @@ import ( "github.com/twpayne/chezmoi/v2/internal/chezmoilog" ) +type onepasswordMode string + +const ( + onepasswordModeAccount onepasswordMode = "account" + onepasswordModeConnect onepasswordMode = "connect" + onepasswordModeService onepasswordMode = "service" +) + type withSessionTokenType bool const ( @@ -34,12 +42,14 @@ type onepasswordAccount struct { } type onepasswordConfig struct { - Command string `json:"command" mapstructure:"command" yaml:"command"` - Prompt bool `json:"prompt" mapstructure:"prompt" yaml:"prompt"` + Command string `json:"command" mapstructure:"command" yaml:"command"` + Prompt bool `json:"prompt" mapstructure:"prompt" yaml:"prompt"` + Mode onepasswordMode `json:"mode" mapstructure:"mode" yaml:"mode"` outputCache map[string][]byte sessionTokens map[string]string accountMap map[string]string accountMapErr error + modeChecked bool } type onepasswordArgs struct { @@ -54,6 +64,8 @@ type onepasswordItem struct { } func (c *Config) onepasswordTemplateFunc(userArgs ...string) map[string]any { + c.onepasswordCheckMode() + args, err := c.newOnepasswordArgs([]string{"item", "get", "--format", "json"}, userArgs) if err != nil { panic(err) @@ -95,6 +107,12 @@ func (c *Config) onepasswordDetailsFieldsTemplateFunc(userArgs ...string) map[st } func (c *Config) onepasswordDocumentTemplateFunc(userArgs ...string) string { + c.onepasswordCheckMode() + + if c.Onepassword.Mode == onepasswordModeConnect { + panic(fmt.Errorf("onepasswordDocument cannot be used in %s mode", onepasswordModeConnect)) + } + args, err := c.newOnepasswordArgs([]string{"document", "get"}, userArgs) if err != nil { panic(err) @@ -202,7 +220,7 @@ func (c *Config) onepasswordOutput(args *onepasswordArgs, withSessionToken withS } commandArgs := args.args - if withSessionToken { + if c.Onepassword.Mode == onepasswordModeAccount && withSessionToken { sessionToken, err := c.onepasswordGetOrRefreshSessionToken(args) if err != nil { return nil, err @@ -229,6 +247,8 @@ func (c *Config) onepasswordOutput(args *onepasswordArgs, withSessionToken withS } func (c *Config) onepasswordReadTemplateFunc(url string, args ...string) string { + c.onepasswordCheckMode() + onepasswordArgs := &onepasswordArgs{ args: []string{"read", "--no-newline", url}, } @@ -237,10 +257,14 @@ func (c *Config) onepasswordReadTemplateFunc(url string, args ...string) string case 0: // Do nothing. case 1: + if c.Onepassword.Mode != onepasswordModeAccount { + panic(fmt.Errorf("1Password account parameters cannot be used in %s mode", c.Onepassword.Mode)) + } + onepasswordArgs.account = c.onepasswordAccount(args[0]) onepasswordArgs.args = append(onepasswordArgs.args, "--account", onepasswordArgs.account) default: - panic(fmt.Errorf("expected 1 or 2 arguments, got %d", len(args))) + panic(fmt.Errorf("expected 1 or 2 arguments, got %d", len(args)+1)) } output, err := c.onepasswordOutput(onepasswordArgs, withSessionToken) @@ -251,6 +275,11 @@ func (c *Config) onepasswordReadTemplateFunc(url string, args ...string) string } func (c *Config) onepasswordAccount(key string) string { + // This should not happen, but better to be safe + if c.Onepassword.Mode != onepasswordModeAccount { + panic(fmt.Errorf("1Password account parameters cannot be used in %s mode", c.Onepassword.Mode)) + } + accounts, err := c.onepasswordAccounts() if err != nil { panic(err) @@ -265,6 +294,11 @@ func (c *Config) onepasswordAccount(key string) string { // onepasswordAccounts returns a map of keys to unique account UUIDs. func (c *Config) onepasswordAccounts() (map[string]string, error) { + // This should not happen, but better to be safe + if c.Onepassword.Mode != onepasswordModeAccount { + panic(fmt.Errorf("1Password account parameters cannot be used in %s mode", c.Onepassword.Mode)) + } + if c.Onepassword.accountMap != nil || c.Onepassword.accountMapErr != nil { return c.Onepassword.accountMap, c.Onepassword.accountMapErr } @@ -290,8 +324,20 @@ func (c *Config) onepasswordAccounts() (map[string]string, error) { } func (c *Config) newOnepasswordArgs(baseArgs, userArgs []string) (*onepasswordArgs, error) { - if len(userArgs) < 1 || 3 < len(userArgs) { - return nil, fmt.Errorf("expected 1, 2, or 3 arguments, got %d", len(userArgs)) + maxArgs := 3 + if c.Onepassword.Mode != onepasswordModeAccount { + maxArgs = 3 + } + + // `session` and `connect` modes do not support the account parameter. Better + // to error out early. + if len(userArgs) < 1 || maxArgs < len(userArgs) { + if c.Onepassword.Mode == onepasswordModeAccount { + return nil, fmt.Errorf("expected 1, 2, or 3 arguments, got %d", len(userArgs)) + } + + return nil, fmt.Errorf("expected 1 or 2 arguments in %s mode, got %d", c.Onepassword.Mode, + len(userArgs)) } a := &onepasswordArgs{ @@ -371,3 +417,45 @@ func onepasswordUniqueSessionToken(environ []string) string { } return token } + +// Verify that things are set up correctly for the 1Password mode. +func (c *Config) onepasswordCheckMode() { + if c.Onepassword.modeChecked { + return + } + + c.Onepassword.modeChecked = true + + switch c.Onepassword.Mode { + case onepasswordModeAccount: + if os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") != "" { + panic("onepassword.mode is account, but OP_SERVICE_ACCOUNT_TOKEN is set") + } + + if os.Getenv("OP_CONNECT_HOST") != "" && os.Getenv("OP_CONNECT_TOKEN") != "" { + panic("onepassword.mode is account, but OP_CONNECT_HOST and OP_CONNECT_TOKEN are set") + } + + case onepasswordModeConnect: + if os.Getenv("OP_CONNECT_HOST") == "" { + panic("onepassword.mode is connect, but OP_CONNECT_HOST is not set") + } + + if os.Getenv("OP_CONNECT_TOKEN") == "" { + panic("onepassword.mode is connect, but OP_CONNECT_TOKEN is not set") + } + + if os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") != "" { + panic("onepassword.mode is connect, but OP_SERVICE_ACCOUNT_TOKEN is set") + } + + case onepasswordModeService: + if os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") == "" { + panic("onepassword.mode is service, but OP_SERVICE_ACCOUNT_TOKEN is not set") + } + + if os.Getenv("OP_CONNECT_HOST") != "" && os.Getenv("OP_CONNECT_TOKEN") != "" { + panic("onepassword.mode is service, but OP_CONNECT_HOST and OP_CONNECT_TOKEN are set") + } + } +} diff --git a/internal/cmd/testdata/scripts/onepassword2.txtar b/internal/cmd/testdata/scripts/onepassword2.txtar index 10d0dabf41ab..b0847b9ff79f 100644 --- a/internal/cmd/testdata/scripts/onepassword2.txtar +++ b/internal/cmd/testdata/scripts/onepassword2.txtar @@ -33,58 +33,127 @@ stdout exampleField exec chezmoi execute-template '{{ onepasswordRead "op://vault/item/field" "account" }}' stdout exampleAccountField +# test onepasswordDocument template function +exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" }}' +stdout 'OK-COMPUTER' + +# test onepasswordDocument template function with vault +exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" "vault" }}' +stdout 'OK-VAULT' + +# test onepasswordDocument template function with vault and account +exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" "vault" "account" }}' +stdout 'OK-VAULT-ACCOUNT' + +# test onepasswordDocument template function with account +exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" "" "account" }}' +stdout 'OK-ACCOUNT' + +# test failure with OP_SERVICE_ACCOUNT_TOKEN set +env OP_SERVICE_ACCOUNT_TOKEN=x +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stderr 'OP_SERVICE_ACCOUNT_TOKEN is set' + +# test failure with OP_CONNECT_HOST and OP_CONNECT_TOKEN set +env OP_SERVICE_ACCOUNT_TOKEN= +env OP_CONNECT_HOST=x +env OP_CONNECT_TOKEN=y +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stderr 'OP_CONNECT_HOST and OP_CONNECT_TOKEN' + -- bin/op -- #!/bin/sh -case "$*" in -"--version") +if [ "$*" = "--version" ]; then echo 2.0.0 - ;; -"item get --format json ExampleLogin" | "item get --format json ExampleLogin --vault vault --account account_uuid" | "--session thisIsAFakeSessionToken item get --format json ExampleLogin" | "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault --account account_uuid" | "--session thisIsAFakeSessionToken item get --format json ExampleLogin --account account_uuid") +elif [ "$*" = "item get --format json ExampleLogin --vault vault --account account_uuid" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "item get --format json ExampleLogin --account account_uuid" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault --account account_uuid" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --account account_uuid" ]; then echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' - ;; -"account list --format=json") +elif [ "$*" = "item get --format json ExampleLogin" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "account list --format=json" ]; then echo '[{"url":"account.1password.com","email":"chezmoi@chezmoi.org","user_uuid":"user_uuid","account_uuid":"account_uuid"}]' - ;; -"signin --raw" | "signin --account account_uuid --raw") +elif [ "$*" = "signin --account account_uuid --raw" ]; then echo 'thisIsAFakeSessionToken' - ;; -"--session thisIsAFakeSessionToken read --no-newline op://vault/item/field") +elif [ "$*" = "signin --raw" ]; then + echo 'thisIsAFakeSessionToken' +elif [ "$*" = "read --no-newline op://vault/item/field" ]; then + echo 'exampleField' +elif [ "$*" = "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field" ]; then echo 'exampleField' - ;; -"--session thisIsAFakeSessionToken read --no-newline op://vault/item/field --account account_uuid") +elif [ "$*" = "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field --account account_uuid" ]; then echo 'exampleAccountField' - ;; -*) +elif [ "$*" = "document get exampleDocument" ]; then + echo 'OK-COMPUTER' +elif [ "$*" = "document get exampleDocument --vault vault" ]; then + echo 'OK-VAULT' +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument" ]; then + echo 'OK-COMPUTER' +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --vault vault" ]; then + echo 'OK-VAULT' +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --account account_uuid" ]; then + echo 'OK-ACCOUNT' +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --vault vault --account account_uuid" ]; then + echo 'OK-VAULT-ACCOUNT' +else echo [ERROR] 2020/01/01 00:00:00 unknown command \"$*\" for \"op\" 1>&2 exit 1 -esac +fi -- bin/op.cmd -- @echo off IF "%*" == "--version" ( echo 2.0.0 -) ELSE IF "%*" == "item get --format json ExampleLogin" ( - echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} ) ELSE IF "%*" == "item get --format json ExampleLogin --vault vault --account account_uuid" ( echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} ) ELSE IF "%*" == "item get --format json ExampleLogin --account account_uuid" ( echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} -) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin" ( - echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} ) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault --account account_uuid" ( echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} ) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --account account_uuid" ( echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} +) ELSE IF "%*" == "item get --format json ExampleLogin" ( + echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} +) ELSE IF "%*" == "item get --format json ExampleLogin --vault vault" ( + echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault" ( + echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin" ( + echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} ) ELSE IF "%*" == "account list --format=json" ( echo.[{"url":"account.1password.com","email":"chezmoi@chezmoi.org","user_uuid":"user_uuid","account_uuid":"account_uuid"}] +) ELSE IF "%*" == "signin --account account_uuid --raw" ( + echo thisIsAFakeSessionToken +) ELSE IF "%*" == "signin --raw" ( + echo thisIsAFakeSessionToken +) ELSE IF "%*" == "document get exampleDocument" ( + echo.OK-COMPUTER +) ELSE IF "%*" == "document get exampleDocument --vault vault" ( + echo.OK-VAULT +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument" ( + echo.OK-COMPUTER +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --vault vault" ( + echo.OK-VAULT +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --account account_uuid" ( + echo.OK-ACCOUNT +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --vault vault --account account_uuid" ( + echo.OK-VAULT-ACCOUNT +) ELSE IF "%*" == "read --no-newline op://vault/item/field" ( + echo.exampleField ) ELSE IF "%*" == "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field" ( echo.exampleField ) ELSE IF "%*" == "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field --account account_uuid" ( echo.exampleAccountField -) ELSE IF "%*" == "signin --raw" ( - echo thisIsAFakeSessionToken -) ELSE IF "%*" == "signin --account account_uuid --raw" ( - echo thisIsAFakeSessionToken ) ELSE ( echo.[ERROR] 2020/01/01 00:00:00 unknown command "%*" for "op" 1>&2 exit /b 1 diff --git a/internal/cmd/testdata/scripts/onepassword2connect.txtar b/internal/cmd/testdata/scripts/onepassword2connect.txtar new file mode 100644 index 000000000000..b79e1388a37f --- /dev/null +++ b/internal/cmd/testdata/scripts/onepassword2connect.txtar @@ -0,0 +1,189 @@ +[unix] chmod 755 bin/op +[windows] unix2dos bin/op.cmd + +mkhomedir + +# test that mode is properly set and reported +exec chezmoi execute-template '{{ .chezmoi.config.onepassword.mode }}' +stdout '^connect$' + +# test failure without OP_CONNECT_HOST set +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stderr 'OP_CONNECT_HOST' + +env OP_CONNECT_HOST=x + +# test failure without OP_CONNECT_TOKEN set +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stderr 'OP_CONNECT_TOKEN' + +env OP_CONNECT_TOKEN=y + +# test onepassword template function +exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stdout '^wxcplh5udshnonkzg2n4qx262y$' + +# test onepassword template function with vault +exec chezmoi execute-template '{{ (onepassword "ExampleLogin" "vault").id }}' +stdout '^wxcplh5udshnonkzg2n4qx262y$' + +# test failure onepassword template function with vault and account +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin" "vault" "account").id }}' +stderr '1Password account parameters cannot be used in connect mode' + +# test onepassword template function with empty vault +exec chezmoi execute-template '{{ (onepassword "ExampleLogin" "").id }}' +stdout '^wxcplh5udshnonkzg2n4qx262y$' + +# test onepasswordDetailsFields template function +exec chezmoi execute-template '{{ (onepasswordDetailsFields "ExampleLogin").password.value }}' +stdout '^L8rm1JXJIE1b8YUDWq7h$' + +# test onepasswordItemFields template function +exec chezmoi execute-template '{{ (onepasswordItemFields "ExampleLogin").exampleLabel.value }}' +stdout exampleValue + +# test onepasswordRead template function +exec chezmoi execute-template '{{ onepasswordRead "op://vault/item/field" }}' +stdout exampleField + +# test failure onepasswordRead template function with account +! exec chezmoi execute-template '{{ onepasswordRead "op://vault/item/field" "account" }}' +stderr '1Password account parameters cannot be used in connect mode' + +# test failure onepasswordDocument template function +! exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" }}' +stderr 'onepasswordDocument cannot be used in connect mode' + +# test failure with OP_SERVICE_ACCOUNT_TOKEN set +env OP_SERVICE_ACCOUNT_TOKEN=x +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stderr 'OP_SERVICE_ACCOUNT_TOKEN is set' + +-- bin/op -- +#!/bin/sh + +if [ "$*" = "--version" ]; then + echo 2.0.0 +elif [ "$*" = "item get --format json ExampleLogin --vault vault --account account_uuid" ]; then + echo "[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "item get --format json ExampleLogin --account account_uuid" ]; then + echo "[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault --account account_uuid" ]; then + echo "[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --account account_uuid" ]; then + echo "[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "item get --format json ExampleLogin" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "item get --format json ExampleLogin --vault vault" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault" ]; then + echo "[ERROR] cannot use session tokens with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin" ]; then + echo "[ERROR] cannot use session tokens with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "account list --format=json" ]; then + echo "[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "signin --account account_uuid --raw" ]; then + echo "[ERROR] cannot sign in with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "signin --raw" ]; then + echo "[ERROR] cannot sign in with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "read --no-newline op://vault/item/field" ]; then + echo 'exampleField' +elif [ "$*" = "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field" ]; then + echo "[ERROR] cannot use session tokens with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field --account account_uuid" ]; then + echo "[ERROR] cannot use session tokens or accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "document get exampleDocument" ]; then + echo "[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument" ]; then + echo "[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --vault vault" ]; then + echo "[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --account account_uuid" ]; then + echo "[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --vault vault --account account_uuid" ]; then + echo "[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set" 1>&2 + exit 1 +else + echo "[ERROR] 2020/01/01 00:00:00 unknown command \"$*\" for \"op\"" 1>&2 + exit 1 +fi +-- bin/op.cmd -- +@echo off +IF "%*" == "--version" ( + echo 2.0.0 +) ELSE IF "%*" == "item get --format json ExampleLogin --vault vault --account account_uuid" ( + echo.[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "item get --format json ExampleLogin --account account_uuid" ( + echo.[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault --account account_uuid" ( + echo.[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --account account_uuid" ( + echo.[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "item get --format json ExampleLogin" ( + echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} +) ELSE IF "%*" == "item get --format json ExampleLogin --vault vault" ( + echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault" ( + echo.[ERROR] cannot use session tokens with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin" ( + echo.[ERROR] cannot use session tokens with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "account list --format=json" ( + echo.[ERROR] cannot use accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "signin --account account_uuid --raw" ( + echo.[ERROR] cannot sign in with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "signin --raw" ( + echo.[ERROR] cannot sign in with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 +) ELSE IF "%*" == "document get exampleDocument" ( + echo.[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument" ( + echo.[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --vault vault" ( + echo.[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --account account_uuid" ( + echo.[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --vault vault --account account_uuid" ( + echo.[ERROR] cannot use document get with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "read --no-newline op://vault/item/field" ( + echo.exampleField +) ELSE IF "%*" == "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field" ( + echo.[ERROR] cannot use session tokens with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field --account account_uuid" ( + echo.[ERROR] cannot use session tokens or accounts with OP_CONNECT_HOST and OP_CONNECT_TOKEN set 1>&2 + exit /b 1 +) ELSE ( + echo "[ERROR] 2020/01/01 00:00:00 unknown command \"%*\" for \"op\"" 1>&2 + exit /b 1 +) +-- home/user/.config/chezmoi/chezmoi.toml -- +[onepassword] +mode = "connect" diff --git a/internal/cmd/testdata/scripts/onepassword2service.txtar b/internal/cmd/testdata/scripts/onepassword2service.txtar new file mode 100644 index 000000000000..7aae04a1976f --- /dev/null +++ b/internal/cmd/testdata/scripts/onepassword2service.txtar @@ -0,0 +1,198 @@ +[unix] chmod 755 bin/op +[windows] unix2dos bin/op.cmd + +mkhomedir + +# test that mode is properly set and reported +exec chezmoi execute-template '{{ .chezmoi.config.onepassword.mode }}' +stdout '^service$' + +# test failure without OP_SERVICE_ACCOUNT_TOKEN set +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stderr 'OP_SERVICE_ACCOUNT_TOKEN is not set' + +env OP_SERVICE_ACCOUNT_TOKEN=x + +# test onepassword template function +exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stdout '^wxcplh5udshnonkzg2n4qx262y$' + +# test onepassword template function with vault +exec chezmoi execute-template '{{ (onepassword "ExampleLogin" "vault").id }}' +stdout '^wxcplh5udshnonkzg2n4qx262y$' + +# test failure onepassword template function with vault and account +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin" "vault" "account").id }}' +stderr '1Password account parameters cannot be used in service mode' + +# test onepassword template function with empty vault +exec chezmoi execute-template '{{ (onepassword "ExampleLogin" "").id }}' +stdout '^wxcplh5udshnonkzg2n4qx262y$' + +# test onepasswordDetailsFields template function +exec chezmoi execute-template '{{ (onepasswordDetailsFields "ExampleLogin").password.value }}' +stdout '^L8rm1JXJIE1b8YUDWq7h$' + +# test onepasswordItemFields template function +exec chezmoi execute-template '{{ (onepasswordItemFields "ExampleLogin").exampleLabel.value }}' +stdout exampleValue + +# test onepasswordRead template function +exec chezmoi execute-template '{{ onepasswordRead "op://vault/item/field" }}' +stdout exampleField + +# test failure onepasswordRead template function with account +! exec chezmoi execute-template '{{ onepasswordRead "op://vault/item/field" "account" }}' +stderr '1Password account parameters cannot be used in service mode' + +# test onepasswordDocument template function +exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" }}' +stdout 'OK-COMPUTER' + +# test onepasswordDocument template function with vault +exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" "vault" }}' +stdout 'OK-VAULT' + +# test onepasswordDocument template function with vault and account +! exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" "vault" "account" }}' +stderr '1Password account parameters cannot be used in service mode' + +# test onepasswordDocument template function with account +! exec chezmoi execute-template '{{ onepasswordDocument "exampleDocument" "" "account" }}' +stderr '1Password account parameters cannot be used in service mode' + +# test failure with OP_CONNECT_HOST and OP_CONNECT_TOKEN set +env OP_CONNECT_HOST=x +env OP_CONNECT_TOKEN=y +! exec chezmoi execute-template '{{ (onepassword "ExampleLogin").id }}' +stderr 'OP_CONNECT_HOST and OP_CONNECT_TOKEN' + +-- bin/op -- +#!/bin/sh + +if [ "$*" = "--version" ]; then + echo 2.0.0 +elif [ "$*" = "item get --format json ExampleLogin --vault vault --account account_uuid" ]; then + echo "[ERROR] cannot use accounts with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "item get --format json ExampleLogin --account account_uuid" ]; then + echo "[ERROR] cannot use accounts with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault --account account_uuid" ]; then + echo "[ERROR] cannot use accounts with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --account account_uuid" ]; then + echo "[ERROR] cannot use accounts with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "item get --format json ExampleLogin" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "item get --format json ExampleLogin --vault vault" ]; then + echo '{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]}' +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault" ]; then + echo "[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken item get --format json ExampleLogin" ]; then + echo "[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "account list --format=json" ]; then + echo "[ERROR] cannot use accounts with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "signin --account account_uuid --raw" ]; then + echo "[ERROR] cannot sign in with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "signin --raw" ]; then + echo "[ERROR] cannot sign in with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "document get exampleDocument" ]; then + echo 'OK-COMPUTER' +elif [ "$*" = "document get exampleDocument --vault vault" ]; then + echo 'OK-VAULT' +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument" ]; then + echo "[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --vault vault" ]; then + echo 'OK-VAULT' +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --account account_uuid" ]; then + echo "[ERROR] cannot use accounts or session tokens with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken document get exampleDocument --vault vault --account account_uuid" ]; then + echo "[ERROR] cannot use accounts or session tokens with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "read --no-newline op://vault/item/field" ]; then + echo 'exampleField' +elif [ "$*" = "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field" ]; then + echo "[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +elif [ "$*" = "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field --account account_uuid" ]; then + echo "[ERROR] cannot use session tokens or accounts with OP_SERVICE_TOKEN set" 1>&2 + exit 1 +else + echo "[ERROR] 2020/01/01 00:00:00 unknown command \"$*\" for \"op\"" 1>&2 + exit 1 +fi +-- bin/op.cmd -- +@echo off +IF "%*" == "--version" ( + echo 2.0.0 +) ELSE IF "%*" == "item get --format json ExampleLogin --vault vault --account account_uuid" ( + echo.[ERROR] cannot use accounts with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "item get --format json ExampleLogin --account account_uuid" ( + echo.[ERROR] cannot use accounts with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault --account account_uuid" ( + echo.[ERROR] cannot use accounts with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --account account_uuid" ( + echo.[ERROR] cannot use accounts with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "item get --format json ExampleLogin" ( + echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} +) ELSE IF "%*" == "item get --format json ExampleLogin --vault vault" ( + echo.{"id":"wxcplh5udshnonkzg2n4qx262y","title":"ExampleLogin","version":1,"vault":{"id":"tscpxgi6s7c662jtqn3vmw4n5a"},"category":"LOGIN","last_edited_by":"YO4UTYPAD3ZFBNZG5DVAZFBNZM","created_at":"2022-01-17T01:53:50Z","updated_at":"2022-01-17T01:55:35Z","sections":[{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"}],"fields":[{"id":"username","type":"STRING","purpose":"USERNAME","label":"username","value":"exampleuser "},{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"L8rm1JXJIE1b8YUDWq7h","password_details":{"strength":"EXCELLENT"}},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain"},{"id":"cqn7oda7wkcsar7rzcr52i2m3u","section":{"id":"Section_cdzjhg2jo7jylpyin2f5mbfnhm","label":"Related Items"},"type":"STRING","label":"exampleLabel","value":"exampleValue"}],"urls":[{"primary":true,"href":"https://www.example.com/"}]} +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin --vault vault" ( + echo.[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken item get --format json ExampleLogin" ( + echo.[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "account list --format=json" ( + echo.[ERROR] cannot use accounts with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "signin --account account_uuid --raw" ( + echo.[ERROR] cannot sign in with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "signin --raw" ( + echo.[ERROR] cannot sign in with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "document get exampleDocument" ( + echo.OK-COMPUTER +) ELSE IF "%*" == "document get exampleDocument --vault vault" ( + echo.OK-VAULT +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument" ( + echo.[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --vault vault" ( + echo.[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --account account_uuid" ( + echo.[ERROR] cannot use accounts or session tokens with OP_SERVICE_TOKEN set 1>&2 + exit 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken document get exampleDocument --vault vault --account account_uuid" ( + echo.[ERROR] cannot use accounts or session tokens with OP_SERVICE_TOKEN set 1>&2 + exit 1 +) ELSE IF "%*" == "read --no-newline op://vault/item/field" ( + echo.exampleField +) ELSE IF "%*" == "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field" ( + echo.[ERROR] cannot use session tokens with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE IF "%*" == "--session thisIsAFakeSessionToken read --no-newline op://vault/item/field --account account_uuid" ( + echo.[ERROR] cannot use session tokens or accounts with OP_SERVICE_TOKEN set 1>&2 + exit /b 1 +) ELSE ( + echo "[ERROR] 2020/01/01 00:00:00 unknown command \"%*\" for \"op\"" 1>&2 + exit /b 1 +) +-- home/user/.config/chezmoi/chezmoi.toml -- +[onepassword] +mode = "service"