From 2a7845f4ffe2fd427c140711c0d7d46424747363 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 4 Jul 2024 02:27:47 +0200 Subject: [PATCH] feat: Add 1Password SDK template funcs --- .../configuration-file/variables.md.yaml | 5 + .../1password-sdk-functions/index.md | 15 ++ .../onepasswordSDKItemsGet.md | 17 ++ .../onepasswordSDKSecretsResolve.md | 17 ++ assets/chezmoi.io/mkdocs.yml | 4 + go.mod | 4 + go.sum | 8 + internal/cmd/config.go | 170 +++++++++--------- internal/cmd/onepasswordsdktemplatefuncs.go | 125 +++++++++++++ 9 files changed, 283 insertions(+), 82 deletions(-) create mode 100644 assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/index.md create mode 100644 assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/onepasswordSDKItemsGet.md create mode 100644 assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/onepasswordSDKSecretsResolve.md create mode 100644 internal/cmd/onepasswordsdktemplatefuncs.go 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 5c051fca792..1367817f63b 100644 --- a/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml +++ b/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml @@ -335,6 +335,11 @@ sections: mode: default: '`account`' description: See [1Password Secrets Automation](../../user-guide/password-managers/1password.md#secrets-automation) + onepasswordSDK: + token: + description: See [1Password SDK functions](../templates/1password-sdk-functions/index.md) + tokenEnvVar: + description: See [1Password SDK functions](../templates/1password-sdk-functions/index.md) pass: command: default: '`pass`' diff --git a/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/index.md b/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/index.md new file mode 100644 index 00000000000..41f54f76af8 --- /dev/null +++ b/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/index.md @@ -0,0 +1,15 @@ +# 1Password SDK functions + +!!! warning + + 1Password SDK template functions are experimental and may change. + +The `onepasswordSDK*` template functions return structured data from +[1Password](https://1password.com/) using the [1Password +SDK](https://developer.1password.com/docs/sdks/). + +By default, the 1Password service account token is taken from the +`$OP_SERVICE_ACCOUNT_TOKEN` environment variable. The name of the environment +variable can be set with `onepasswordSDK.tokenEnvVar` configuration variable, or +the token can be set explicitly by setting the `onepasswordSDK.token` +configuration variable. diff --git a/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/onepasswordSDKItemsGet.md b/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/onepasswordSDKItemsGet.md new file mode 100644 index 00000000000..baef1a744ad --- /dev/null +++ b/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/onepasswordSDKItemsGet.md @@ -0,0 +1,17 @@ +# `onepasswordSDKItemsGet` *vault-id* *item-id* + +!!! warning + + `onepasswordSDKItemsGet` is an experimental function and may change. + +`onepasswordSDKItemsGet` returns an item from [1Password](https://1password.com) +using the [1Password SDK](https://developer.1password.com/docs/sdks/). + +The output of `onepasswordSDKItemsGet` is cached so multiple calls to +`onepasswordSDKItemsGet` with the same *vault-id* and *item-id* will return the same value. + +!!! example + + ``` + {{- onepasswordSDKItemsGet "vault" "item" | toJson -}} + ``` diff --git a/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/onepasswordSDKSecretsResolve.md b/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/onepasswordSDKSecretsResolve.md new file mode 100644 index 00000000000..a6971357aa4 --- /dev/null +++ b/assets/chezmoi.io/docs/reference/templates/1password-sdk-functions/onepasswordSDKSecretsResolve.md @@ -0,0 +1,17 @@ +# `onepasswordSDKSecretsResolve` *url* + +!!! warning + + `onepasswordSDKSecretsResolve` is an experimental function and may change. + +`onepasswordSDKSecretsResolve` returns a secret from [1Password](https://1password.com) +using the [1Password SDK](https://developer.1password.com/docs/sdks/). + +The output of `onepasswordSDKSecretsResolve` is cached so multiple calls to +`onepasswordSDKSecretsResolve` with the same *url* will return the same value. + +!!! example + + ``` + {{- onepasswordSDKSecretsResolve "op://vault/item/field" -}} + ``` diff --git a/assets/chezmoi.io/mkdocs.yml b/assets/chezmoi.io/mkdocs.yml index 098df462b8d..31a9df256d9 100644 --- a/assets/chezmoi.io/mkdocs.yml +++ b/assets/chezmoi.io/mkdocs.yml @@ -249,6 +249,10 @@ nav: - onepasswordDetailsFields: reference/templates/1password-functions/onepasswordDetailsFields.md - onepasswordItemFields: reference/templates/1password-functions/onepasswordItemFields.md - onepasswordRead: reference/templates/1password-functions/onepasswordRead.md + - 1Password SDK functions: + - reference/templates/1password-sdk-functions/index.md + - onepasswordSDKItemsGet: reference/templates/1password-sdk-functions/onepasswordSDKItemsGet.md + - onepasswordSDKSecretsResolve: reference/templates/1password-sdk-functions/onepasswordSDKSecretsResolve.md - AWS Secrets Manager functions: - reference/templates/aws-secrets-manager-functions/index.md - awsSecretsManager: reference/templates/aws-secrets-manager-functions/awsSecretsManager.md diff --git a/go.mod b/go.mod index 85e6271e35f..b9f7a448a01 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ toolchain go1.22.0 require ( filippo.io/age v1.2.0 + github.com/1password/onepassword-sdk-go v0.1.0-beta.10 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.1.0 github.com/Masterminds/sprig/v3 v3.2.3 @@ -101,10 +102,12 @@ require ( github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect + github.com/extism/go-sdk v1.3.0 // indirect github.com/fatih/semgroup v1.2.0 // indirect github.com/gitleaks/go-gitdiff v0.9.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -148,6 +151,7 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/tetratelabs/wazero v1.7.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yuin/goldmark v1.7.4 // indirect diff --git a/go.sum b/go.sum index e3255bb044c..f26e10db143 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ filippo.io/age v1.2.0 h1:vRDp7pUMaAJzXNIWJVAZnEf/Dyi4Vu4wI8S1LBzufhE= filippo.io/age v1.2.0/go.mod h1:JL9ew2lTN+Pyft4RiNGguFfOpewKwSHm5ayKD/A4004= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/1password/onepassword-sdk-go v0.1.0-beta.10 h1:vYm15kP/HMWdJaScgWFUu0zxl5QeRgUAwg322VabV54= +github.com/1password/onepassword-sdk-go v0.1.0-beta.10/go.mod h1:FnJzZHo0kfR7U4M3f9xRbKIAn+sR9pn1Ssu3zGDcMpM= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= @@ -161,6 +163,8 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/extism/go-sdk v1.3.0 h1:DBd4FzDBUAL3P01MNqUD2+x8G7qyYdJ7pV96NIrfWXA= +github.com/extism/go-sdk v1.3.0/go.mod h1:tPMWfCSOThie3LSTSZKbrQjRm2oAXxUUjSE4HJWjYQM= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fatih/semgroup v1.2.0 h1:h/OLXwEM+3NNyAdZEpMiH1OzfplU09i2qXPVThGZvyg= @@ -187,6 +191,8 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -434,6 +440,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a h1:SJy1Pu0eH1C29XwJucQo73FrleVK6t4kYz4NVhp34Yw= github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8= +github.com/tetratelabs/wazero v1.7.3 h1:PBH5KVahrt3S2AHgEjKu4u+LlDbbk+nsGE3KLucy6Rw= +github.com/tetratelabs/wazero v1.7.3/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y= github.com/twpayne/go-expect v0.0.1 h1:cRJ552FIdQzs4z98Q2OLQsGLSbkB7Xpm/IU6cyQ6mUM= github.com/twpayne/go-expect v0.0.1/go.mod h1:+ffr+YtUt8ifebyvRQ3NhVTiLch/HnfxsAQqO5LeXss= github.com/twpayne/go-pinentry/v4 v4.0.0 h1:8WcNa+UDVRzz7y9OEEU/nRMX+UGFPCAvl5XsqWRxTY4= diff --git a/internal/cmd/config.go b/internal/cmd/config.go index 5cc7cbb0def..b1a512a9493 100644 --- a/internal/cmd/config.go +++ b/internal/cmd/config.go @@ -139,6 +139,7 @@ type ConfigFile struct { Keeper keeperConfig `json:"keeper" mapstructure:"keeper" yaml:"keeper"` Lastpass lastpassConfig `json:"lastpass" mapstructure:"lastpass" yaml:"lastpass"` Onepassword onepasswordConfig `json:"onepassword" mapstructure:"onepassword" yaml:"onepassword"` + OnepasswordSDK onepasswordSDKConfig `json:"onepasswordSDK" mapstructure:"onepasswordSDK" yaml:"onepasswordSDK"` //nolint:tagliatelle Pass passConfig `json:"pass" mapstructure:"pass" yaml:"pass"` Passhole passholeConfig `json:"passhole" mapstructure:"passhole" yaml:"passhole"` RBW rbwConfig `json:"rbw" mapstructure:"rbw" yaml:"rbw"` @@ -407,88 +408,90 @@ func newConfig(options ...configOption) (*Config, error) { // The completion template function is added in persistentPreRunRootE as // it needs a *cobra.Command, which we don't yet have. for key, value := range map[string]any{ - "awsSecretsManager": c.awsSecretsManagerTemplateFunc, - "awsSecretsManagerRaw": c.awsSecretsManagerRawTemplateFunc, - "azureKeyVault": c.azureKeyVaultTemplateFunc, - "bitwarden": c.bitwardenTemplateFunc, - "bitwardenAttachment": c.bitwardenAttachmentTemplateFunc, - "bitwardenAttachmentByRef": c.bitwardenAttachmentByRefTemplateFunc, - "bitwardenFields": c.bitwardenFieldsTemplateFunc, - "bitwardenSecrets": c.bitwardenSecretsTemplateFunc, - "comment": c.commentTemplateFunc, - "dashlaneNote": c.dashlaneNoteTemplateFunc, - "dashlanePassword": c.dashlanePasswordTemplateFunc, - "decrypt": c.decryptTemplateFunc, - "deleteValueAtPath": c.deleteValueAtPathTemplateFunc, - "doppler": c.dopplerTemplateFunc, - "dopplerProjectJson": c.dopplerProjectJSONTemplateFunc, - "ejsonDecrypt": c.ejsonDecryptTemplateFunc, - "ejsonDecryptWithKey": c.ejsonDecryptWithKeyTemplateFunc, - "encrypt": c.encryptTemplateFunc, - "eqFold": c.eqFoldTemplateFunc, - "findExecutable": c.findExecutableTemplateFunc, - "findOneExecutable": c.findOneExecutableTemplateFunc, - "fromIni": c.fromIniTemplateFunc, - "fromJson": c.fromJsonTemplateFunc, - "fromJsonc": c.fromJsoncTemplateFunc, - "fromToml": c.fromTomlTemplateFunc, - "fromYaml": c.fromYamlTemplateFunc, - "gitHubKeys": c.gitHubKeysTemplateFunc, - "gitHubLatestRelease": c.gitHubLatestReleaseTemplateFunc, - "gitHubLatestReleaseAssetURL": c.gitHubLatestReleaseAssetURLTemplateFunc, - "gitHubLatestTag": c.gitHubLatestTagTemplateFunc, - "gitHubReleases": c.gitHubReleasesTemplateFunc, - "gitHubTags": c.gitHubTagsTemplateFunc, - "glob": c.globTemplateFunc, - "gopass": c.gopassTemplateFunc, - "gopassRaw": c.gopassRawTemplateFunc, - "hcpVaultSecret": c.hcpVaultSecretTemplateFunc, - "hcpVaultSecretJson": c.hcpVaultSecretJSONTemplateFunc, - "hexDecode": c.hexDecodeTemplateFunc, - "hexEncode": c.hexEncodeTemplateFunc, - "include": c.includeTemplateFunc, - "includeTemplate": c.includeTemplateTemplateFunc, - "ioreg": c.ioregTemplateFunc, - "isExecutable": c.isExecutableTemplateFunc, - "joinPath": c.joinPathTemplateFunc, - "jq": c.jqTemplateFunc, - "keepassxc": c.keepassxcTemplateFunc, - "keepassxcAttachment": c.keepassxcAttachmentTemplateFunc, - "keepassxcAttribute": c.keepassxcAttributeTemplateFunc, - "keeper": c.keeperTemplateFunc, - "keeperDataFields": c.keeperDataFieldsTemplateFunc, - "keeperFindPassword": c.keeperFindPasswordTemplateFunc, - "keyring": c.keyringTemplateFunc, - "lastpass": c.lastpassTemplateFunc, - "lastpassRaw": c.lastpassRawTemplateFunc, - "lookPath": c.lookPathTemplateFunc, - "lstat": c.lstatTemplateFunc, - "mozillaInstallHash": c.mozillaInstallHashTemplateFunc, - "onepassword": c.onepasswordTemplateFunc, - "onepasswordDetailsFields": c.onepasswordDetailsFieldsTemplateFunc, - "onepasswordDocument": c.onepasswordDocumentTemplateFunc, - "onepasswordItemFields": c.onepasswordItemFieldsTemplateFunc, - "onepasswordRead": c.onepasswordReadTemplateFunc, - "output": c.outputTemplateFunc, - "pass": c.passTemplateFunc, - "passFields": c.passFieldsTemplateFunc, - "passhole": c.passholeTemplateFunc, - "passRaw": c.passRawTemplateFunc, - "pruneEmptyDicts": c.pruneEmptyDictsTemplateFunc, - "quoteList": c.quoteListTemplateFunc, - "rbw": c.rbwTemplateFunc, - "rbwFields": c.rbwFieldsTemplateFunc, - "replaceAllRegex": c.replaceAllRegexTemplateFunc, - "secret": c.secretTemplateFunc, - "secretJSON": c.secretJSONTemplateFunc, - "setValueAtPath": c.setValueAtPathTemplateFunc, - "splitList": c.splitListTemplateFunc, - "stat": c.statTemplateFunc, - "toIni": c.toIniTemplateFunc, - "toPrettyJson": c.toPrettyJsonTemplateFunc, - "toToml": c.toTomlTemplateFunc, - "toYaml": c.toYamlTemplateFunc, - "vault": c.vaultTemplateFunc, + "awsSecretsManager": c.awsSecretsManagerTemplateFunc, + "awsSecretsManagerRaw": c.awsSecretsManagerRawTemplateFunc, + "azureKeyVault": c.azureKeyVaultTemplateFunc, + "bitwarden": c.bitwardenTemplateFunc, + "bitwardenAttachment": c.bitwardenAttachmentTemplateFunc, + "bitwardenAttachmentByRef": c.bitwardenAttachmentByRefTemplateFunc, + "bitwardenFields": c.bitwardenFieldsTemplateFunc, + "bitwardenSecrets": c.bitwardenSecretsTemplateFunc, + "comment": c.commentTemplateFunc, + "dashlaneNote": c.dashlaneNoteTemplateFunc, + "dashlanePassword": c.dashlanePasswordTemplateFunc, + "decrypt": c.decryptTemplateFunc, + "deleteValueAtPath": c.deleteValueAtPathTemplateFunc, + "doppler": c.dopplerTemplateFunc, + "dopplerProjectJson": c.dopplerProjectJSONTemplateFunc, + "ejsonDecrypt": c.ejsonDecryptTemplateFunc, + "ejsonDecryptWithKey": c.ejsonDecryptWithKeyTemplateFunc, + "encrypt": c.encryptTemplateFunc, + "eqFold": c.eqFoldTemplateFunc, + "findExecutable": c.findExecutableTemplateFunc, + "findOneExecutable": c.findOneExecutableTemplateFunc, + "fromIni": c.fromIniTemplateFunc, + "fromJson": c.fromJsonTemplateFunc, + "fromJsonc": c.fromJsoncTemplateFunc, + "fromToml": c.fromTomlTemplateFunc, + "fromYaml": c.fromYamlTemplateFunc, + "gitHubKeys": c.gitHubKeysTemplateFunc, + "gitHubLatestRelease": c.gitHubLatestReleaseTemplateFunc, + "gitHubLatestReleaseAssetURL": c.gitHubLatestReleaseAssetURLTemplateFunc, + "gitHubLatestTag": c.gitHubLatestTagTemplateFunc, + "gitHubReleases": c.gitHubReleasesTemplateFunc, + "gitHubTags": c.gitHubTagsTemplateFunc, + "glob": c.globTemplateFunc, + "gopass": c.gopassTemplateFunc, + "gopassRaw": c.gopassRawTemplateFunc, + "hcpVaultSecret": c.hcpVaultSecretTemplateFunc, + "hcpVaultSecretJson": c.hcpVaultSecretJSONTemplateFunc, + "hexDecode": c.hexDecodeTemplateFunc, + "hexEncode": c.hexEncodeTemplateFunc, + "include": c.includeTemplateFunc, + "includeTemplate": c.includeTemplateTemplateFunc, + "ioreg": c.ioregTemplateFunc, + "isExecutable": c.isExecutableTemplateFunc, + "joinPath": c.joinPathTemplateFunc, + "jq": c.jqTemplateFunc, + "keepassxc": c.keepassxcTemplateFunc, + "keepassxcAttachment": c.keepassxcAttachmentTemplateFunc, + "keepassxcAttribute": c.keepassxcAttributeTemplateFunc, + "keeper": c.keeperTemplateFunc, + "keeperDataFields": c.keeperDataFieldsTemplateFunc, + "keeperFindPassword": c.keeperFindPasswordTemplateFunc, + "keyring": c.keyringTemplateFunc, + "lastpass": c.lastpassTemplateFunc, + "lastpassRaw": c.lastpassRawTemplateFunc, + "lookPath": c.lookPathTemplateFunc, + "lstat": c.lstatTemplateFunc, + "mozillaInstallHash": c.mozillaInstallHashTemplateFunc, + "onepassword": c.onepasswordTemplateFunc, + "onepasswordDetailsFields": c.onepasswordDetailsFieldsTemplateFunc, + "onepasswordDocument": c.onepasswordDocumentTemplateFunc, + "onepasswordItemFields": c.onepasswordItemFieldsTemplateFunc, + "onepasswordRead": c.onepasswordReadTemplateFunc, + "onepasswordSDKItemsGet": c.onepasswordSDKItemsGet, + "onepasswordSDKSecretsResolve": c.onepasswordSDKSecretsResolve, + "output": c.outputTemplateFunc, + "pass": c.passTemplateFunc, + "passFields": c.passFieldsTemplateFunc, + "passhole": c.passholeTemplateFunc, + "passRaw": c.passRawTemplateFunc, + "pruneEmptyDicts": c.pruneEmptyDictsTemplateFunc, + "quoteList": c.quoteListTemplateFunc, + "rbw": c.rbwTemplateFunc, + "rbwFields": c.rbwFieldsTemplateFunc, + "replaceAllRegex": c.replaceAllRegexTemplateFunc, + "secret": c.secretTemplateFunc, + "secretJSON": c.secretJSONTemplateFunc, + "setValueAtPath": c.setValueAtPathTemplateFunc, + "splitList": c.splitListTemplateFunc, + "stat": c.statTemplateFunc, + "toIni": c.toIniTemplateFunc, + "toPrettyJson": c.toPrettyJsonTemplateFunc, + "toToml": c.toTomlTemplateFunc, + "toYaml": c.toYamlTemplateFunc, + "vault": c.vaultTemplateFunc, } { c.addTemplateFunc(key, value) } @@ -2772,6 +2775,9 @@ func newConfigFile(bds *xdg.BaseDirectorySpecification) ConfigFile { Prompt: true, Mode: onepasswordModeAccount, }, + OnepasswordSDK: onepasswordSDKConfig{ + TokenEnvVar: "OP_SERVICE_ACCOUNT_TOKEN", + }, Pass: passConfig{ Command: "pass", }, diff --git a/internal/cmd/onepasswordsdktemplatefuncs.go b/internal/cmd/onepasswordsdktemplatefuncs.go new file mode 100644 index 00000000000..26abdbb0e8a --- /dev/null +++ b/internal/cmd/onepasswordsdktemplatefuncs.go @@ -0,0 +1,125 @@ +package cmd + +import ( + "context" + "os" + "strings" + + "github.com/1password/onepassword-sdk-go" +) + +type onepasswordSDKConfig struct { + Token string `json:"token" mapstructure:"token" yaml:"token"` + TokenEnvVar string `json:"tokenEnvVar" mapstructure:"tokenEnvVar" yaml:"tokenEnvVar"` + itemsGetCache map[string]onepasswordSDKItem + secretsResolveCache map[string]string + client *onepassword.Client + clientErr error +} + +type onepasswordSDKItem struct { + ID string + Title string + Category onepassword.ItemCategory + VaultID string + Fields map[string]onepassword.ItemField + Sections map[string]onepassword.ItemSection +} + +func (c *Config) onepasswordSDKItemsGet(vaultID, itemID string) onepasswordSDKItem { + key := strings.Join([]string{vaultID, itemID}, "\x00") + if result, ok := c.OnepasswordSDK.itemsGetCache[key]; ok { + return result + } + + ctx := context.TODO() + + client, err := c.onepasswordSDKClient(ctx) + if err != nil { + panic(err) + } + + item, err := client.Items.Get(ctx, vaultID, itemID) + if err != nil { + panic(err) + } + + if c.OnepasswordSDK.itemsGetCache == nil { + c.OnepasswordSDK.itemsGetCache = make(map[string]onepasswordSDKItem) + } + + fields := make(map[string]onepassword.ItemField) + for _, field := range item.Fields { + fields[field.ID] = field + } + + sections := make(map[string]onepassword.ItemSection) + for _, section := range item.Sections { + sections[section.ID] = section + } + + onepasswordSDKItem := onepasswordSDKItem{ + ID: item.ID, + Title: item.Title, + Category: item.Category, + VaultID: item.VaultID, + Fields: fields, + Sections: sections, + } + + c.OnepasswordSDK.itemsGetCache[key] = onepasswordSDKItem + + return onepasswordSDKItem +} + +func (c *Config) onepasswordSDKSecretsResolve(secretReference string) string { + if result, ok := c.OnepasswordSDK.secretsResolveCache[secretReference]; ok { + return result + } + + ctx := context.TODO() + + client, err := c.onepasswordSDKClient(ctx) + if err != nil { + panic(err) + } + + secret, err := client.Secrets.Resolve(ctx, secretReference) + if err != nil { + panic(err) + } + + if c.OnepasswordSDK.secretsResolveCache == nil { + c.OnepasswordSDK.secretsResolveCache = make(map[string]string) + } + c.OnepasswordSDK.secretsResolveCache[secretReference] = secret + + return secret +} + +func (c *Config) onepasswordSDKClient(ctx context.Context) (*onepassword.Client, error) { + if c.OnepasswordSDK.client != nil || c.OnepasswordSDK.clientErr != nil { + return c.OnepasswordSDK.client, c.OnepasswordSDK.clientErr + } + + token := c.OnepasswordSDK.Token + if token == "" { + token = os.Getenv(c.OnepasswordSDK.TokenEnvVar) + } + + version := c.versionInfo.Version + if version == "" { + version = c.versionInfo.Commit + } + if version == "" { + version = onepassword.DefaultIntegrationVersion + } + + c.OnepasswordSDK.client, c.OnepasswordSDK.clientErr = onepassword.NewClient( + ctx, + onepassword.WithIntegrationInfo("chezmoi", version), + onepassword.WithServiceAccountToken(token), + ) + + return c.OnepasswordSDK.client, c.OnepasswordSDK.clientErr +}