Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add support for Keeper password manager
Co-authored-by: Tag Howard <tag.howard1080@gmail.com>
- Loading branch information
1 parent
7485aea
commit e0b3ace
Showing
14 changed files
with
296 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
assets/chezmoi.io/docs/reference/templates/keeper-functions/index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Keeper functions | ||
|
||
The `keeper*` functions return data from [Keeper](https://www.keepersecurity.com/) | ||
[Commander CLI](https://docs.keeper.io/secrets-manager/commander-cli) (`keeper`). | ||
|
||
The command used can by changed by setting the `keeper.command` configuration | ||
variable, and extra arguments can be added by setting `keeper.args`. |
6 changes: 6 additions & 0 deletions
6
assets/chezmoi.io/docs/reference/templates/keeper-functions/keeper.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# `keeper` *uid* | ||
|
||
`keeper` returns structured data retreived from | ||
[Keeper](https://www.keepersecurity.com/) using the [Commander | ||
CLI](https://docs.keeper.io/secrets-manager/commander-cli). *uid* is passed to | ||
`keeper get --format=json` and the output is parsed as JSON. |
12 changes: 12 additions & 0 deletions
12
assets/chezmoi.io/docs/reference/templates/keeper-functions/keeperDataFields.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# `keeperDataFields` *uid* | ||
|
||
`keeperDataFields` returns the `.data.fields` elements of `keeper get | ||
--format=json *uid*` indexed by `type`. | ||
|
||
## Example | ||
|
||
``` | ||
url = {{ (keeperDataFields "$UID").url }} | ||
login = {{ index (keeperDataFields "$UID").login 0 }} | ||
password = {{ index (keeperDataFields "$UID").password 0 }} | ||
``` |
4 changes: 4 additions & 0 deletions
4
assets/chezmoi.io/docs/reference/templates/keeper-functions/keeperFindPassword.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# `keeperFindPassword` *query* | ||
|
||
`keeperFindPassword` returns the output of `keeper find-password query`. *query* | ||
can be a UID or a path. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
assets/chezmoi.io/docs/user-guide/password-managers/keeper.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Keeper | ||
|
||
chezmoi includes support for [Keeper](https://www.keepersecurity.com/) using the | ||
[Commander CLI](https://docs.keeper.io/secrets-manager/commander-cli) to expose | ||
data as a template function. | ||
|
||
Create a persistent login session as [described in the Command CLI | ||
documentation](https://docs.keeper.io/secrets-manager/commander-cli/using-commander/logging-in#persistent-login-sessions). | ||
|
||
Passwords can be retrieved with the `keeperFindPassword` template function, for | ||
example: | ||
|
||
``` | ||
examplePasswordFromPath = {{ keeperFindPassword "$PATH" }} | ||
examplePasswordFromUid = {{ keeperFindPassword "$UID" }} | ||
``` | ||
|
||
For retrieving more complex data, use the `keeper` template function with a UID | ||
to retrieve structured data from [`keeper | ||
get`](https://docs.keeper.io/secrets-manager/commander-cli/using-commander/command-reference/record-commands#get-command) | ||
or the `keeperDataFields` template function which restructures the output of | ||
`keeper get` in to a more convenient form, for example: | ||
|
||
``` | ||
keeperDataTitle = {{ (keeper "$UID").data.title }} | ||
examplePassword = {{ index (keeperDataFields "$UID").password 0 }} | ||
``` | ||
|
||
Extra arguments can be passed to the Keeper CLI command by setting the | ||
`keeper.args` variable in chezmoi's config file, for example: | ||
|
||
```toml title="~/.config/chezmoi/chezmoi.toml" | ||
[keeper] | ||
args = ["--config", "/path/to/config.json"] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
) | ||
|
||
type keeperConfig struct { | ||
Command string | ||
Args []string | ||
outputCache map[string][]byte | ||
} | ||
|
||
func (c *Config) keeperTemplateFunction(record string) map[string]interface{} { | ||
output, err := c.keeperOutput([]string{"get", "--format=json", record}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
var result map[string]interface{} | ||
if err := json.Unmarshal(output, &result); err != nil { | ||
panic(err) | ||
} | ||
return result | ||
} | ||
|
||
func (c *Config) keeperDataFieldsTemplateFunction(record string) map[string]interface{} { | ||
output, err := c.keeperOutput([]string{"get", "--format=json", record}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
var data struct { | ||
Data struct { | ||
Fields []struct { | ||
Type string `json:"type"` | ||
Value interface{} `json:"value"` | ||
} `json:"fields"` | ||
} `json:"data"` | ||
} | ||
if err := json.Unmarshal(output, &data); err != nil { | ||
panic(err) | ||
} | ||
result := make(map[string]interface{}) | ||
for _, field := range data.Data.Fields { | ||
result[field.Type] = field.Value | ||
} | ||
return result | ||
} | ||
|
||
func (c *Config) keeperFindPasswordTemplateFunc(record string) string { | ||
output, err := c.keeperOutput([]string{"find-password", record}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return string(bytes.TrimSpace(output)) | ||
} | ||
|
||
func (c *Config) keeperOutput(args []string) ([]byte, error) { | ||
key := strings.Join(args, "\x00") | ||
if data, ok := c.Keeper.outputCache[key]; ok { | ||
return data, nil | ||
} | ||
|
||
name := c.Keeper.Command | ||
args = append(args, c.Keeper.Args...) | ||
cmd := exec.Command(name, args...) | ||
cmd.Stdin = os.Stdin | ||
cmd.Stderr = os.Stderr | ||
output, err := c.baseSystem.IdempotentCmdOutput(cmd) | ||
if err != nil { | ||
return nil, newCmdOutputError(cmd, output, err) | ||
} | ||
|
||
if c.Keeper.outputCache == nil { | ||
c.Keeper.outputCache = make(map[string][]byte) | ||
} | ||
c.Keeper.outputCache[key] = output | ||
return output, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
[!windows] chmod 755 bin/keeper | ||
[windows] unix2dos bin/keeper.cmd | ||
|
||
# test keeper template function | ||
chezmoi execute-template '{{ (keeper "QOahgRH_dSTvSvhRBqzCzQ").record_uid }}' | ||
stdout '^QOahgRH_dSTvSvhRBqzCzQ$' | ||
|
||
# test keeperDataFields template function | ||
chezmoi execute-template '{{ index (keeperDataFields "QOahgRH_dSTvSvhRBqzCzQ").password 0 }}' | ||
stdout ^mypassword$ | ||
|
||
# test keeperFindPassword template function | ||
chezmoi execute-template '{{ keeperFindPassword "Example" }}' | ||
stdout ^mypassword$ | ||
|
||
-- bin/keeper -- | ||
#!/bin/sh | ||
|
||
case "$*" in | ||
"get --format=json QOahgRH_dSTvSvhRBqzCzQ --config /path/to/config.json") | ||
cat <<EOF | ||
{ | ||
"record_uid": "QOahgRH_dSTvSvhRBqzCzQ", | ||
"data": { | ||
"title": "Example", | ||
"type": "login", | ||
"fields": [ | ||
{ | ||
"type": "login", | ||
"value": [ | ||
"mylogin" | ||
] | ||
}, | ||
{ | ||
"type": "password", | ||
"value": [ | ||
"mypassword" | ||
] | ||
}, | ||
{ | ||
"type": "url", | ||
"value": [] | ||
}, | ||
{ | ||
"type": "fileRef", | ||
"value": [] | ||
}, | ||
{ | ||
"type": "oneTimeCode", | ||
"value": [] | ||
} | ||
], | ||
"custom": [] | ||
} | ||
} | ||
EOF | ||
;; | ||
"find-password Example --config /path/to/config.json") | ||
echo "mypassword" | ||
;; | ||
*) | ||
cat <<EOF | ||
Commands: | ||
search ... Search the vault. Can use a regular expression. | ||
|
||
Type 'command -h' to display help on command | ||
EOF | ||
esac | ||
-- bin/keeper.cmd -- | ||
@echo off | ||
IF "%*" == "get --format=json QOahgRH_dSTvSvhRBqzCzQ --config /path/to/config.json" ( | ||
echo.{ | ||
echo. "record_uid": "QOahgRH_dSTvSvhRBqzCzQ", | ||
echo. "data": { | ||
echo. "title": "Example", | ||
echo. "type": "login", | ||
echo. "fields": [ | ||
echo. { | ||
echo. "type": "login", | ||
echo. "value": [ | ||
echo. "mylogin" | ||
echo. ] | ||
echo. }, | ||
echo. { | ||
echo. "type": "password", | ||
echo. "value": [ | ||
echo. "mypassword" | ||
echo. ] | ||
echo. }, | ||
echo. { | ||
echo. "type": "url", | ||
echo. "value": [] | ||
echo. }, | ||
echo. { | ||
echo. "type": "fileRef", | ||
echo. "value": [] | ||
echo. }, | ||
echo. { | ||
echo. "type": "oneTimeCode", | ||
echo. "value": [] | ||
echo. } | ||
echo. ], | ||
echo. "custom": [] | ||
echo. } | ||
echo.} | ||
) ELSE IF "%*" == "find-password Example --config /path/to/config.json" ( | ||
echo.mypassword | ||
;; | ||
) ELSE ( | ||
echo.Commands: | ||
echo. search ... Search the vault. Can use a regular expression. | ||
echo. | ||
echo.Type 'command -h' to display help on command | ||
) | ||
-- home/user/.config/chezmoi/chezmoi.toml -- | ||
[keeper] | ||
args = ["--config", "/path/to/config.json"] |