Cache password to avoid invoking password source on each API request

This commit is contained in:
Patrick Decat
2019-11-02 09:46:50 +01:00
parent 590244947b
commit 0f059a5ed1
2 changed files with 22 additions and 12 deletions
+3
View File
@@ -71,6 +71,9 @@ type GlobalOptions struct {
// location using the `pass` tool, if missing prompt the user and store in the PasswordDirectory // location using the `pass` tool, if missing prompt the user and store in the PasswordDirectory
PasswordSource figtree.StringOption `yaml:"password-source,omitempty" json:"password-source,omitempty"` PasswordSource figtree.StringOption `yaml:"password-source,omitempty" json:"password-source,omitempty"`
// Cached password to avoid invoking password source on each API request
cachedPassword string
// PasswordDirectory is only used for the "pass" PasswordSource. It is the location for the encrypted password // PasswordDirectory is only used for the "pass" PasswordSource. It is the location for the encrypted password
// files used by `pass`. Effectively this overrides the "PASSWORD_STORE_DIR" environment variable // files used by `pass`. Effectively this overrides the "PASSWORD_STORE_DIR" environment variable
PasswordDirectory figtree.StringOption `yaml:"password-directory,omitempty" json:"password-directory,omitempty"` PasswordDirectory figtree.StringOption `yaml:"password-directory,omitempty" json:"password-directory,omitempty"`
+19 -12
View File
@@ -42,15 +42,19 @@ func (o *GlobalOptions) keyName() string {
} }
func (o *GlobalOptions) GetPass() string { func (o *GlobalOptions) GetPass() string {
passwd := "" if o.cachedPassword != "" {
return o.cachedPassword
}
if o.PasswordSource.Value != "" { if o.PasswordSource.Value != "" {
if o.PasswordSource.Value == "keyring" { if o.PasswordSource.Value == "keyring" {
log.Info("Querying keyring password source.")
var err error var err error
passwd, err = keyringGet(o.keyName()) o.cachedPassword, err = keyringGet(o.keyName())
if err != nil { if err != nil {
panic(err) panic(err)
} }
} else if o.PasswordSource.Value == "gopass" { } else if o.PasswordSource.Value == "gopass" {
log.Info("Querying gopass password source.")
if o.PasswordDirectory.Value != "" { if o.PasswordDirectory.Value != "" {
orig := os.Getenv("PASSWORD_STORE_DIR") orig := os.Getenv("PASSWORD_STORE_DIR")
os.Setenv("PASSWORD_STORE_DIR", o.PasswordDirectory.Value) os.Setenv("PASSWORD_STORE_DIR", o.PasswordDirectory.Value)
@@ -62,7 +66,7 @@ func (o *GlobalOptions) GetPass() string {
cmd.Stdout = buf cmd.Stdout = buf
cmd.Stderr = buf cmd.Stderr = buf
if err := cmd.Run(); err == nil { if err := cmd.Run(); err == nil {
passwd = strings.TrimSpace(buf.String()) o.cachedPassword = strings.TrimSpace(buf.String())
} else { } else {
panic(err) panic(err)
} }
@@ -70,6 +74,7 @@ func (o *GlobalOptions) GetPass() string {
log.Warning("Gopass binary was not found! Fallback to default password behaviour!") log.Warning("Gopass binary was not found! Fallback to default password behaviour!")
} }
} else if o.PasswordSource.Value == "pass" { } else if o.PasswordSource.Value == "pass" {
log.Info("Querying pass password source.")
if o.PasswordDirectory.Value != "" { if o.PasswordDirectory.Value != "" {
orig := os.Getenv("PASSWORD_STORE_DIR") orig := os.Getenv("PASSWORD_STORE_DIR")
os.Setenv("PASSWORD_STORE_DIR", o.PasswordDirectory.Value) os.Setenv("PASSWORD_STORE_DIR", o.PasswordDirectory.Value)
@@ -81,7 +86,7 @@ func (o *GlobalOptions) GetPass() string {
cmd.Stdout = buf cmd.Stdout = buf
cmd.Stderr = buf cmd.Stderr = buf
if err := cmd.Run(); err == nil { if err := cmd.Run(); err == nil {
passwd = strings.TrimSpace(buf.String()) o.cachedPassword = strings.TrimSpace(buf.String())
} else { } else {
panic(err) panic(err)
} }
@@ -89,22 +94,24 @@ func (o *GlobalOptions) GetPass() string {
log.Warning("Pass binary was not found! Fallback to default password behaviour!") log.Warning("Pass binary was not found! Fallback to default password behaviour!")
} }
} else if o.PasswordSource.Value == "stdin" { } else if o.PasswordSource.Value == "stdin" {
log.Info("Reading password from stdin.")
allBytes, err := ioutil.ReadAll(os.Stdin) allBytes, err := ioutil.ReadAll(os.Stdin)
if err != nil { if err != nil {
panic(fmt.Sprintf("unable to read bytes from stdin: %s", err)) panic(fmt.Sprintf("unable to read bytes from stdin: %s", err))
} }
passwd = string(allBytes) o.cachedPassword = string(allBytes)
} else { } else {
log.Warningf("Unknown password-source: %s", o.PasswordSource) log.Warningf("Unknown password-source: %s", o.PasswordSource)
} }
} }
if passwd != "" { if o.cachedPassword != "" {
return passwd log.Info("Password cached.")
return o.cachedPassword
} }
if passwd = os.Getenv("JIRA_API_TOKEN"); passwd != "" && o.AuthMethod() == "api-token" { if o.cachedPassword = os.Getenv("JIRA_API_TOKEN"); o.cachedPassword != "" && o.AuthMethod() == "api-token" {
return passwd return o.cachedPassword
} }
prompt := fmt.Sprintf("Jira Password [%s]: ", o.Login) prompt := fmt.Sprintf("Jira Password [%s]: ", o.Login)
@@ -120,15 +127,15 @@ func (o *GlobalOptions) GetPass() string {
Message: prompt, Message: prompt,
Help: help, Help: help,
}, },
&passwd, &o.cachedPassword,
nil, nil,
) )
if err != nil { if err != nil {
log.Errorf("%s", err) log.Errorf("%s", err)
panic(Exit{Code: 1}) panic(Exit{Code: 1})
} }
o.SetPass(passwd) o.SetPass(o.cachedPassword)
return passwd return o.cachedPassword
} }
func (o *GlobalOptions) SetPass(passwd string) error { func (o *GlobalOptions) SetPass(passwd string) error {