Add ability to pull user/account/auth-method ID from stored token (#517)
This commit is contained in:
1 parent
6ddfe407a3
commit
d851ab07d8
2 files changed
+124
-34
No files matched your search
+39
-28
@@ -192,12 +192,15 @@ func (c *Command) Client(opt ...Option) (*api.Client, error) {
|
||||
it for two subsequent calls. This then becomes a question of
|
||||
how/when to finalize the wrapper. Probably it needs to be stored in
|
||||
the base and then at the end of the command run we finalize it if it
|
||||
exists. defer func() {if err := wrapper.Finalize(c.Context); err !=
|
||||
nil {c.UI.Error(fmt.Errorf("An error was encountered finalizing the
|
||||
kms: %w", err).Error())
|
||||
}
|
||||
exists.
|
||||
|
||||
defer func() {
|
||||
if err := wrapper.Finalize(c.Context); err != nil {
|
||||
c.UI.Error(fmt.Errorf("An error was encountered finalizing the kms: %w", err).Error())
|
||||
}
|
||||
}()
|
||||
*/
|
||||
|
||||
c.client.SetRecoveryKmsWrapper(wrapper)
|
||||
|
||||
case c.FlagToken != "":
|
||||
@@ -209,30 +212,9 @@ func (c *Command) Client(opt ...Option) (*api.Client, error) {
|
||||
}
|
||||
os.Setenv(EnvTokenName, tokenName)
|
||||
if tokenName != "none" {
|
||||
token, err := keyring.Get("HashiCorp Boundary Auth Token", tokenName)
|
||||
if err != nil {
|
||||
if err == keyring.ErrNotFound {
|
||||
c.UI.Info("No saved credential found, continuing without")
|
||||
} else {
|
||||
c.UI.Error(fmt.Sprintf("Error reading auth token from system credential store: %s", err))
|
||||
}
|
||||
token = ""
|
||||
}
|
||||
if token != "" {
|
||||
tokenBytes, err := base64.RawStdEncoding.DecodeString(token)
|
||||
switch {
|
||||
case err != nil:
|
||||
c.UI.Error(fmt.Errorf("Error base64-unmarshaling stored token from system credential store: %w", err).Error())
|
||||
case len(tokenBytes) == 0:
|
||||
c.UI.Error("Zero length token after decoding stored token from system credential store")
|
||||
default:
|
||||
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)
|
||||
}
|
||||
}
|
||||
authToken := c.ReadTokenFromKeyring(tokenName)
|
||||
if authToken != nil {
|
||||
c.client.SetToken(authToken.Token)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,6 +226,35 @@ func (c *Command) Client(opt ...Option) (*api.Client, error) {
|
||||
return c.client, nil
|
||||
}
|
||||
|
||||
func (c *Command) ReadTokenFromKeyring(tokenName string) *authtokens.AuthToken {
|
||||
token, err := keyring.Get("HashiCorp Boundary Auth Token", tokenName)
|
||||
if err != nil {
|
||||
if err == keyring.ErrNotFound {
|
||||
c.UI.Info("No saved credential found, continuing without")
|
||||
} else {
|
||||
c.UI.Error(fmt.Sprintf("Error reading auth token from system credential store: %s", err))
|
||||
}
|
||||
token = ""
|
||||
}
|
||||
if token != "" {
|
||||
tokenBytes, err := base64.RawStdEncoding.DecodeString(token)
|
||||
switch {
|
||||
case err != nil:
|
||||
c.UI.Error(fmt.Errorf("Error base64-unmarshaling stored token from system credential store: %w", err).Error())
|
||||
case len(tokenBytes) == 0:
|
||||
c.UI.Error("Zero length token after decoding stored token from system credential store")
|
||||
default:
|
||||
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 {
|
||||
return &authToken
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type FlagSetBit uint
|
||||
|
||||
const (
|
||||
|
||||
@@ -2,8 +2,8 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/textproto"
|
||||
|
||||
"github.com/hashicorp/boundary/api/authtokens"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
@@ -16,10 +16,14 @@ type TokenCommand struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
flagUserId bool
|
||||
flagAccountId bool
|
||||
flagAuthMethodId bool
|
||||
}
|
||||
|
||||
func (c *TokenCommand) Synopsis() string {
|
||||
return fmt.Sprintf("%s sensitive values in Boundary's configuration file", textproto.CanonicalMIMEHeaderKey(c.Func))
|
||||
return fmt.Sprintf("Get the stored token, or its properties")
|
||||
}
|
||||
|
||||
func (c *TokenCommand) Help() string {
|
||||
@@ -57,6 +61,24 @@ func (c *TokenCommand) Flags() *base.FlagSets {
|
||||
Usage: `If specified, the given value will be used as the name when loading the token from the system credential store. This must correspond to a name used when authenticating.`,
|
||||
})
|
||||
|
||||
f.BoolVar(&base.BoolVar{
|
||||
Name: "user-id",
|
||||
Target: &c.flagUserId,
|
||||
Usage: `If specified, print out the user ID associated with the token instead of the token itself.`,
|
||||
})
|
||||
|
||||
f.BoolVar(&base.BoolVar{
|
||||
Name: "account-id",
|
||||
Target: &c.flagAccountId,
|
||||
Usage: `If specified, print out the account ID associated with the token instead of the token itself.`,
|
||||
})
|
||||
|
||||
f.BoolVar(&base.BoolVar{
|
||||
Name: "auth-method-id",
|
||||
Target: &c.flagAuthMethodId,
|
||||
Usage: `If specified, print out the auth method ID associated with the token instead of the token itself.`,
|
||||
})
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
@@ -75,13 +97,70 @@ func (c *TokenCommand) Run(args []string) (ret int) {
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
var optCount int
|
||||
if c.flagUserId {
|
||||
optCount++
|
||||
}
|
||||
if c.flagAccountId {
|
||||
optCount++
|
||||
}
|
||||
if c.flagAuthMethodId {
|
||||
optCount++
|
||||
}
|
||||
|
||||
if optCount > 1 {
|
||||
c.UI.Error("Only zero or one output option can be specified.")
|
||||
return 1
|
||||
}
|
||||
|
||||
c.UI.Output(client.Token())
|
||||
// Read from keyring first
|
||||
var authToken *authtokens.AuthToken
|
||||
tokenName := "default"
|
||||
if c.FlagTokenName != "" {
|
||||
tokenName = c.FlagTokenName
|
||||
}
|
||||
if tokenName != "none" {
|
||||
at := c.ReadTokenFromKeyring(tokenName)
|
||||
if at != nil {
|
||||
authToken = at
|
||||
}
|
||||
}
|
||||
|
||||
if authToken == nil {
|
||||
// Fallback to env/CLI
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
authToken = &authtokens.AuthToken{Token: client.Token()}
|
||||
}
|
||||
|
||||
switch {
|
||||
case c.flagUserId:
|
||||
if authToken.UserId == "" {
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(authToken.UserId)
|
||||
|
||||
case c.flagAccountId:
|
||||
if authToken.AccountId == "" {
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(authToken.AccountId)
|
||||
|
||||
case c.flagAuthMethodId:
|
||||
if authToken.AuthMethodId == "" {
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(authToken.AuthMethodId)
|
||||
|
||||
default:
|
||||
if authToken.Token == "" {
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(authToken.Token)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
Reference in new issue
Block a user