103 lines
3.2 KiB
Go
103 lines
3.2 KiB
Go
package authenticate
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/hashicorp/boundary/api/authmethods"
|
|
"github.com/hashicorp/boundary/api/authtokens"
|
|
"github.com/hashicorp/boundary/internal/cmd/base"
|
|
nkeyring "github.com/jefferai/keyring"
|
|
zkeyring "github.com/zalando/go-keyring"
|
|
)
|
|
|
|
func saveAndOrPrintToken(c *base.Command, result *authmethods.AuthenticateResult) int {
|
|
token := new(authtokens.AuthToken)
|
|
if err := json.Unmarshal(result.GetRawAttributes(), token); err != nil {
|
|
c.PrintCliError(fmt.Errorf("Error trying to decode response as an auth token: %w", err))
|
|
return base.CommandCliError
|
|
}
|
|
|
|
switch base.Format(c.UI) {
|
|
case "table":
|
|
c.UI.Output(base.WrapForHelpText([]string{
|
|
"",
|
|
"Authentication information:",
|
|
fmt.Sprintf(" Account ID: %s", token.AccountId),
|
|
fmt.Sprintf(" Auth Method ID: %s", token.AuthMethodId),
|
|
fmt.Sprintf(" Expiration Time: %s", token.ExpirationTime.Local().Format(time.RFC1123)),
|
|
fmt.Sprintf(" User ID: %s", token.UserId),
|
|
}))
|
|
|
|
case "json":
|
|
if ok := c.PrintJsonItem(result.GetResponse()); !ok {
|
|
return base.CommandCliError
|
|
}
|
|
return base.CommandSuccess
|
|
}
|
|
|
|
var gotErr bool
|
|
keyringType, tokenName, err := c.DiscoverKeyringTokenInfo()
|
|
if err != nil {
|
|
c.UI.Error(fmt.Sprintf("Error fetching keyring information: %s", err))
|
|
gotErr = true
|
|
} else if keyringType != "none" &&
|
|
tokenName != "none" &&
|
|
keyringType != "" &&
|
|
tokenName != "" {
|
|
marshaled, err := json.Marshal(token)
|
|
if err != nil {
|
|
c.UI.Error(fmt.Sprintf("Error marshaling auth token to save to keyring: %s", err))
|
|
gotErr = true
|
|
} else {
|
|
switch keyringType {
|
|
case "wincred", "keychain":
|
|
if err := zkeyring.Set(base.StoredTokenName, tokenName, base64.RawStdEncoding.EncodeToString(marshaled)); err != nil {
|
|
c.UI.Error(fmt.Sprintf("Error saving auth token to %q keyring: %s", keyringType, err))
|
|
gotErr = true
|
|
}
|
|
|
|
default:
|
|
krConfig := nkeyring.Config{
|
|
LibSecretCollectionName: "login",
|
|
PassPrefix: "HashiCorp_Boundary",
|
|
AllowedBackends: []nkeyring.BackendType{nkeyring.BackendType(keyringType)},
|
|
}
|
|
|
|
kr, err := nkeyring.Open(krConfig)
|
|
if err != nil {
|
|
c.UI.Error(fmt.Sprintf("Error opening %q keyring: %s", keyringType, err))
|
|
gotErr = true
|
|
break
|
|
}
|
|
|
|
if err := kr.Set(nkeyring.Item{
|
|
Key: tokenName,
|
|
Data: []byte(base64.RawStdEncoding.EncodeToString(marshaled)),
|
|
}); err != nil {
|
|
c.UI.Error(fmt.Sprintf("Error storing token in %q keyring: %s", keyringType, err))
|
|
gotErr = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !gotErr {
|
|
c.UI.Output("\nThe token was successfully stored in the chosen keyring and is not displayed here.")
|
|
}
|
|
}
|
|
}
|
|
|
|
switch {
|
|
case gotErr:
|
|
c.UI.Warn(fmt.Sprintf("The token was not successfully saved to a system keyring. The token is:\n\n%s\n\nIt must be manually passed in via the BOUNDARY_TOKEN env var or -token flag. Storing the token can also be disabled via -keyring-type=none.", token.Token))
|
|
case c.FlagKeyringType == "none":
|
|
c.UI.Warn("\nStoring the token in a keyring was disabled. The token is:")
|
|
c.UI.Output(token.Token)
|
|
c.UI.Warn("Please be sure to store it safely!")
|
|
}
|
|
|
|
return base.CommandSuccess
|
|
}
|