Skip to content

Commit

Permalink
feat: Add Dashlane password manager support
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Feb 26, 2023
1 parent 3073efc commit aa21a31
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ sections:
custom:
type: bool
description: Enable custom shell completions
dashlane:
args:
type: '[]string'
description: Extra args to Dashlane CLI command
command:
default: '`dcli`'
description: Dashlane CLI command
diff:
args:
type: '[]string'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# `dashlanePassword` *filter*

`dashlanePassword` returns structured data from [Dashlane](https://dashlane.com)
using the [Dashlane CLI](https://github.com/Dashlane/dashlane-cli) (`dcli`).
*filter* is passed to `dcli password --output json`, and the output from `dcli
password` is parsed as JSON.

The output from `dcli password` cached so calling `dashlanePassword` multiple
times with the same *filter* will only invoke `dcli password` once.

!!! example

```
{{ (index (dashlanePassword "filter") 0).password }}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Dashlane functions

The `dashlane*` functions return data from [Dashlane](https://dashlane.com)
using the [Dashlane CLI](https://github.com/Dashlane/dashlane-cli).
10 changes: 10 additions & 0 deletions assets/chezmoi.io/docs/user-guide/password-managers/dashlane.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Dashlane

chezmoi includes support for [Dashlane](https://dashlane.com).

Structured data can be retrieved with the `dashlanePassword` template function,
for example:

```
examplePassword = {{ (index (dashlanePassword "filter") 0).password }}
```
7 changes: 4 additions & 3 deletions assets/chezmoi.io/docs/what-does-chezmoi-do.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ in a git repo under your control. You can write the configuration file in the
format of your choice. chezmoi can retrieve secrets from
[1Password](https://1password.com/), [AWS Secrets
Manager](https://aws.amazon.com/secrets-manager/),
[Bitwarden](https://bitwarden.com/), [gopass](https://www.gopass.pw/),
[KeePassXC](https://keepassxc.org/), [Keeper](https://www.keepersecurity.com/),
[LastPass](https://lastpass.com/), [pass](https://www.passwordstore.org/),
[Bitwarden](https://bitwarden.com/), [Dashlane](https://www.dashlane.com/),
[gopass](https://www.gopass.pw/), [KeePassXC](https://keepassxc.org/),
[Keeper](https://www.keepersecurity.com/), [LastPass](https://lastpass.com/),
[pass](https://www.passwordstore.org/),
[passhole](https://github.com/Evidlo/passhole),
[Vault](https://www.vaultproject.io/), Keychain,
[Keyring](https://wiki.gnome.org/Projects/GnomeKeyring), or any command-line
Expand Down
4 changes: 4 additions & 0 deletions assets/chezmoi.io/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ nav:
- 1Password: user-guide/password-managers/1password.md
- AWS Secrets Manager: user-guide/password-managers/aws-secrets-manager.md
- Bitwarden: user-guide/password-managers/bitwarden.md
- Dashlane: user-guide/password-managers/dashlane.md
- gopass: user-guide/password-managers/gopass.md
- KeePassXC: user-guide/password-managers/keepassxc.md
- Keychain and Windows Credentials Manager: user-guide/password-managers/keychain-and-windows-credentials-manager.md
Expand Down Expand Up @@ -240,6 +241,9 @@ nav:
- reference/templates/gopass-functions/index.md
- gopass: reference/templates/gopass-functions/gopass.md
- gopassRaw: reference/templates/gopass-functions/gopassRaw.md
- Dashlane functions:
- reference/templates/dashlane-functions/index.md
- dashlanePassword: reference/templates/dashlane-functions/dashlanePassword.md
- KeePassXC functions:
- reference/templates/keepassxc-functions/index.md
- keepassxc: reference/templates/keepassxc-functions/keepassxc.md
Expand Down
5 changes: 5 additions & 0 deletions pkg/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ type ConfigFile struct {
// Password manager configurations.
AWSSecretsManager awsSecretsManagerConfig `json:"awsSecretsManager" mapstructure:"awsSecretsManager" yaml:"awsSecretsManager"` //nolint:lll
Bitwarden bitwardenConfig `json:"bitwarden" mapstructure:"bitwarden" yaml:"bitwarden"`
Dashlane dashlaneConfig `json:"dashlane" mapstructure:"dashlane" yaml:"dashlane"`
Gopass gopassConfig `json:"gopass" mapstructure:"gopass" yaml:"gopass"`
Keepassxc keepassxcConfig `json:"keepassxc" mapstructure:"keepassxc" yaml:"keepassxc"`
Keeper keeperConfig `json:"keeper" mapstructure:"keeper" yaml:"keeper"`
Expand Down Expand Up @@ -361,6 +362,7 @@ func newConfig(options ...configOption) (*Config, error) {
"bitwardenAttachmentByRef": c.bitwardenAttachmentByRefTemplateFunc,
"bitwardenFields": c.bitwardenFieldsTemplateFunc,
"comment": c.commentTemplateFunc,
"dashlanePassword": c.dashlanePasswordTemplateFunc,
"decrypt": c.decryptTemplateFunc,
"deleteValueAtPath": c.deleteValueAtPathTemplateFunc,
"encrypt": c.encryptTemplateFunc,
Expand Down Expand Up @@ -2410,6 +2412,9 @@ func newConfigFile(bds *xdg.BaseDirectorySpecification) ConfigFile {
Bitwarden: bitwardenConfig{
Command: "bw",
},
Dashlane: dashlaneConfig{
Command: "dcli",
},
Gopass: gopassConfig{
Command: "gopass",
},
Expand Down
50 changes: 50 additions & 0 deletions pkg/cmd/dashlanetemplatefuncs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cmd

import (
"encoding/json"
"os"
"os/exec"

"github.com/twpayne/chezmoi/v2/pkg/chezmoilog"
)

type dashlaneConfig struct {
Command string `json:"command" mapstructure:"command" yaml:"command"`
Args []string `json:"args" mapstructure:"args" yaml:"args"`
cache map[string]any
}

func (c *Config) dashlanePasswordTemplateFunc(filter string) any {
if data, ok := c.Dashlane.cache[filter]; ok {
return data
}

if c.Dashlane.cache == nil {
c.Dashlane.cache = make(map[string]any)
}

output, err := c.dashlaneOutput("password", "--output", "json", filter)
if err != nil {
panic(err)
}

var data any
if err := json.Unmarshal(output, &data); err != nil {
panic(err)
}

c.Dashlane.cache[filter] = data
return data
}

func (c *Config) dashlaneOutput(args ...string) ([]byte, error) {
name := c.Dashlane.Command
cmd := exec.Command(name, append(c.Dashlane.Args, args...)...)
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
output, err := chezmoilog.LogCmdOutput(cmd)
if err != nil {
return nil, err
}
return output, nil
}
70 changes: 70 additions & 0 deletions pkg/cmd/testdata/scripts/dashlane.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
[!windows] chmod 755 bin/dcli
[windows] unix2dos bin/dcli.cmd

# test dashlanePassword template function
exec chezmoi execute-template '{{ (index (dashlanePassword "filter") 0).password }}'
stdout ^<password>$

-- bin/dcli --
#!/bin/sh

case "$*" in
"password --output json filter")
cat <<EOF
[
{
"title": "<name of the entry>",
"useFixedUrl": false,
"login": "<login>",
"status": "ACCOUNT_NOT_VERIFIED",
"note": "<any note>",
"autoLogin": false,
"modificationDatetime": "<timestamp>",
"checked": false,
"id": "<id>",
"anonId": "<anonymous id>",
"localeFormat": "UNIVERSAL",
"password": "<password>",
"creationDatetime": "<timestamp>",
"userModificationDatetime": "<timestamp>",
"lastBackupTime": "<timestamp>",
"autoProtected": false,
"strength": 0,
"subdomainOnly": false
}
]
EOF
;;
*)
echo "error: unknown command '$*'"
exit 1
esac
-- bin/dcli.cmd --
@echo off
IF "%*" == "password --output json filter" (
echo.[
echo. {
echo. "title": "<name of the entry>",
echo. "useFixedUrl": false,
echo. "login": "<login>",
echo. "status": "ACCOUNT_NOT_VERIFIED",
echo. "note": "<any note>",
echo. "autoLogin": false,
echo. "modificationDatetime": "<timestamp>",
echo. "checked": false,
echo. "id": "<id>",
echo. "anonId": "<anonymous id>",
echo. "localeFormat": "UNIVERSAL",
echo. "password": "<password>",
echo. "creationDatetime": "<timestamp>",
echo. "userModificationDatetime": "<timestamp>",
echo. "lastBackupTime": "<timestamp>",
echo. "autoProtected": false,
echo. "strength": 0,
echo. "subdomainOnly": false
echo. }
echo.]
) ELSE (
echo error: unknown command '$*'
exit /b 1
)

0 comments on commit aa21a31

Please sign in to comment.