Skip to content

Commit

Permalink
Add keyring support
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Nov 27, 2018
1 parent a72847e commit 4751fcd
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 1 deletion.
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ architecture, and hostname.
with incomplete files that could lock you out, even if the update process is
interrupted.

* Secure: `chezmoi` can store and retreive secrets in your Keychain (on
macOS), GNOME Keyring (on Linux), or Windows Credentials Manager (on
Windows) using the [zalando/go-keyring](https://github.com/zalando/go-keyring)
library.

* Portable: `chezmoi`'s configuration uses only visible, regular files and
directories and so is portable across version control systems and operating
systems.
Expand Down Expand Up @@ -189,7 +194,7 @@ token](https://help.github.com/articles/creating-a-personal-access-token-for-the
There are several ways to keep these tokens secure, and to prevent them leaving
your machine.

### Using templates
### Using templates variables

Typically, `~/.chezmoi.yaml` is not checked in to version control and has
permissions 0600. You can store tokens as template values in the `data`
Expand All @@ -211,6 +216,34 @@ My `~/.chezmoi/private_dot_gitconfig.tmpl` then contains:
Note that any config files containing tokens in plain text should be private
(permissions 0600).

### Using keyring

`chezmoi` includes support for Keychain (on macOS), GNOME Keyring (on Linux),
and Windows Credentials Manager (on Windows) via the
[zalando/go-keyring](https://github.com/zalando/go-keyring) library.

Set passwords with:

$ chezmoi keyring set --service=<service> --user=<user> --password=<password>

The password can then be used in templates using the `keyring` function which
takes the service and user as arguments.

For example, save a Github access token in keyring with:

$ chezmoi keyring set --service=github --user=$GITHUB_USERNAME --password=xxxxxxxx

and then include it in your `~/.gitconfig` file with:

[github]
user = {{ .github.user }}
token = {{ keyring "github" .github.user }}

You can query the keyring from the command line:

$ chezmoi keyring get --service=github --user=$GITHUB_USERNAME


### Using encrypted config files

`chezmoi` takes a `-c` flag specifying the file to read its configuration from.
Expand Down
8 changes: 8 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ type AddCommandConfig struct {
Template bool
}

// A KeyringCommandConfig is a configuration for the keyring command.
type KeyringCommandConfig struct {
Service string
User string
Password string
}

// A Config represents a configuration.
type Config struct {
SourceDir string
Expand All @@ -35,6 +42,7 @@ type Config struct {
Data map[string]interface{}
Funcs template.FuncMap
Add AddCommandConfig
Keyring KeyringCommandConfig
}

func (c *Config) addFunc(key string, value interface{}) {
Expand Down
32 changes: 32 additions & 0 deletions cmd/keyring.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"github.com/spf13/cobra"
"github.com/zalando/go-keyring"
)

var keyringCommand = &cobra.Command{
Use: "keyring",
Args: cobra.NoArgs,
Short: "Interact with keyring",
}

func init() {
rootCommand.AddCommand(keyringCommand)

persistentFlags := keyringCommand.PersistentFlags()

persistentFlags.StringVar(&config.Keyring.Service, "service", "", "service")
keyringCommand.MarkPersistentFlagRequired("service")

persistentFlags.StringVar(&config.Keyring.User, "user", "", "user")
keyringCommand.MarkPersistentFlagRequired("user")

config.addFunc("keyring", func(service, user string) string {
password, err := keyring.Get(service, user)
if err != nil {
return err.Error()
}
return password
})
}
29 changes: 29 additions & 0 deletions cmd/keyring_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"
"github.com/twpayne/go-vfs"
"github.com/zalando/go-keyring"
)

var keyringGetCommand = &cobra.Command{
Use: "get",
Args: cobra.NoArgs,
Short: "Get a password from keyring",
RunE: makeRunE(config.runKeyringGetCommand),
}

func init() {
keyringCommand.AddCommand(keyringGetCommand)
}

func (c *Config) runKeyringGetCommand(fs vfs.FS, cmd *cobra.Command, args []string) error {
password, err := keyring.Get(c.Keyring.Service, c.Keyring.User)
if err != nil {
return err
}
fmt.Println(password)
return nil
}
26 changes: 26 additions & 0 deletions cmd/keyring_set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cmd

import (
"github.com/spf13/cobra"
"github.com/twpayne/go-vfs"
"github.com/zalando/go-keyring"
)

var keyringSetCommand = &cobra.Command{
Use: "set",
Args: cobra.NoArgs,
Short: "Set a password in keyring",
RunE: makeRunE(config.runKeyringSetCommand),
}

func init() {
keyringCommand.AddCommand(keyringSetCommand)

persistentFlags := keyringSetCommand.PersistentFlags()
persistentFlags.StringVar(&config.Keyring.Password, "password", "", "password")
keyringSetCommand.MarkPersistentFlagRequired("password")
}

func (c *Config) runKeyringSetCommand(fs vfs.FS, cmd *cobra.Command, args []string) error {
return keyring.Set(c.Keyring.Service, c.Keyring.User, c.Keyring.Password)
}
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ module github.com/twpayne/chezmoi
require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/d4l3k/messagediff v1.2.1
github.com/danieljoos/wincred v1.0.1 // indirect
github.com/davecgh/go-spew v1.1.1
github.com/godbus/dbus v4.1.0+incompatible // indirect
github.com/google/renameio v0.0.0-20181108174601-76365acd908f
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/mitchellh/go-homedir v1.0.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/cobra v0.0.3
github.com/spf13/viper v1.2.1
github.com/stretchr/objx v0.1.1 // indirect
github.com/stretchr/testify v1.2.2 // indirect
github.com/twpayne/go-vfs v0.1.1
github.com/zalando/go-keyring v0.0.0-20180221093347-6d81c293b3fb
)
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
github.com/danieljoos/wincred v1.0.1 h1:fcRTaj17zzROVqni2FiToKUVg3MmJ4NtMSGCySPIr/g=
github.com/danieljoos/wincred v1.0.1/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/google/renameio v0.0.0-20181108174601-76365acd908f h1:lhDFIjvRqIJDmEHDSeRSiWee4a0oDr0vPpvdFviPcEo=
github.com/google/renameio v0.0.0-20181108174601-76365acd908f/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
Expand Down Expand Up @@ -34,10 +38,14 @@ github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.2.1 h1:bIcUwXqLseLF3BDAZduuNfekWG87ibtFxi59Bq+oI9M=
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/twpayne/go-vfs v0.1.1 h1:5HFYyah2qxr+b2SDlF6ExZScSgjMvAzhjrnwxKLhI34=
github.com/twpayne/go-vfs v0.1.1/go.mod h1:OIXA6zWkcn7Jk46XT7ceYqBMeIkfzJ8WOBhGJM0W4y8=
github.com/zalando/go-keyring v0.0.0-20180221093347-6d81c293b3fb h1:tXbazu9ZlecQbyCczvA22mWj+lw/36Bdwxapk8v7e7s=
github.com/zalando/go-keyring v0.0.0-20180221093347-6d81c293b3fb/go.mod h1:XlXBIfkGawHNVOHlenOaBW7zlfCh8LovwjOgjamYnkQ=
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992 h1:BH3eQWeGbwRU2+wxxuuPOdFBmaiBH81O8BugSjHeTFg=
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
Expand Down

0 comments on commit 4751fcd

Please sign in to comment.