From 2bbc1163c40f3daa8f88d7d8d5f7f64feddd2a7d Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Wed, 22 Jul 2020 15:02:58 -0400 Subject: [PATCH] Save the entire token, not just the ID (#211) This allows us to use the token's scope to set the default scope for an action in the client instead of relying on env vars. --- internal/cmd/base/base.go | 27 +++++++++++++++---- .../cmd/commands/authenticate/password.go | 9 ++++++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/internal/cmd/base/base.go b/internal/cmd/base/base.go index 6472a3d0c7..fc357b2d52 100644 --- a/internal/cmd/base/base.go +++ b/internal/cmd/base/base.go @@ -3,6 +3,8 @@ package base import ( "bytes" "context" + "encoding/base64" + "encoding/json" "flag" "fmt" "io" @@ -15,6 +17,7 @@ import ( "syscall" "github.com/hashicorp/watchtower/api" + "github.com/hashicorp/watchtower/api/authtokens" "github.com/mitchellh/cli" "github.com/pkg/errors" "github.com/posener/complete" @@ -118,9 +121,6 @@ func (c *Command) Client() (*api.Client, error) { if c.flagAddr != NotSetValue { c.client.SetAddr(c.flagAddr) } - if c.flagScope != NotSetValue { - c.client.SetScopeId(c.flagScope) - } // If we need custom TLS configuration, then set it var modifiedTLS bool @@ -174,13 +174,30 @@ func (c *Command) Client() (*api.Client, error) { } else { c.UI.Error(fmt.Sprintf("Error reading auth token from system credential store: %s", err)) } + token = "" } if token != "" { - c.client.SetToken(token) + tokenBytes, err := base64.RawStdEncoding.DecodeString(token) + if err != nil { + c.UI.Error(fmt.Sprintf("Error unmarshaling stored token from system credential store: %s", err)) + } else { + var authToken authtokens.AuthToken + if err := json.Unmarshal(tokenBytes, &authToken); err != nil { + c.UI.Error(fmt.Sprintf("Error unmarshaling stored token information after reading from system credential store: %s", err)) + } else { + c.client.SetToken(authToken.Token) + c.client.SetScopeId(authToken.Scope.Id) + } + } } } } + // We do this here so we override the stored token info if it's set above + if c.flagScope != NotSetValue { + c.client.SetScopeId(c.flagScope) + } + return c.client, nil } @@ -295,7 +312,7 @@ func (c *Command) FlagSet(bit FlagSetBit) *FlagSets { Name: "token-name", Target: &c.FlagTokenName, EnvVar: envTokenName, - Usage: "If specified, the given value will be used as the name when storing the token in the system credential store. This can allow switching user identities for different commands.", + Usage: `If specified, the given value will be used as the name when storing the token in the system credential store. This can allow switching user identities for different commands. Set to "none" to disable storing the token.`, }) f.BoolVar(&BoolVar{ diff --git a/internal/cmd/commands/authenticate/password.go b/internal/cmd/commands/authenticate/password.go index c8fccb6895..2de206ebba 100644 --- a/internal/cmd/commands/authenticate/password.go +++ b/internal/cmd/commands/authenticate/password.go @@ -1,6 +1,8 @@ package authenticate import ( + "encoding/base64" + "encoding/json" "fmt" "os" "strings" @@ -153,7 +155,12 @@ func (c *PasswordCommand) Run(args []string) int { tokenName = c.Command.FlagTokenName } if tokenName != "none" { - if err := keyring.Set("HashiCorp Watchtower Auth Token", tokenName, result.Token); err != nil { + marshaled, err := json.Marshal(result) + if err != nil { + c.UI.Error(fmt.Sprintf("Error marshaling auth token to save to system credential store: %s", err)) + return 1 + } + if err := keyring.Set("HashiCorp Watchtower Auth Token", tokenName, base64.RawStdEncoding.EncodeToString(marshaled)); err != nil { c.UI.Error(fmt.Sprintf("Error saving auth token to system credential store: %s", err)) return 1 }