Don't swallow errors on token functions.

This commit is contained in:
Jeff Mitchell 2017-10-07 18:41:07 -04:00 committed by Seth Vargo
parent 9f62e942bb
commit 713d5d5307
No known key found for this signature in database
GPG Key ID: C921994F9C27E0FF
5 changed files with 461 additions and 461 deletions

View File

@ -1,12 +1,12 @@
package api package api
import ( import (
"encoding/json" "fmt"
"io" "io"
"strconv"
"time" "time"
"github.com/hashicorp/vault/helper/jsonutil" "github.com/hashicorp/vault/helper/jsonutil"
"github.com/hashicorp/vault/helper/parseutil"
) )
// Secret is the structure returned for every secret within Vault. // Secret is the structure returned for every secret within Vault.
@ -38,131 +38,125 @@ type Secret struct {
} }
// TokenID returns the standardized token ID (token) for the given secret. // TokenID returns the standardized token ID (token) for the given secret.
func (s *Secret) TokenID() string { func (s *Secret) TokenID() (string, error) {
if s == nil { if s == nil {
return "" return "", nil
} }
if s.Auth != nil && len(s.Auth.ClientToken) > 0 { if s.Auth != nil && len(s.Auth.ClientToken) > 0 {
return s.Auth.ClientToken return s.Auth.ClientToken, nil
} }
if s.Data == nil || s.Data["id"] == nil { if s.Data == nil || s.Data["id"] == nil {
return "" return "", nil
} }
id, ok := s.Data["id"].(string) id, ok := s.Data["id"].(string)
if !ok { if !ok {
return "" return "", fmt.Errorf("token found but in the wrong format")
} }
return id return id, nil
} }
// TokenAccessor returns the standardized token accessor for the given secret. // TokenAccessor returns the standardized token accessor for the given secret.
// If the secret is nil or does not contain an accessor, this returns the empty // If the secret is nil or does not contain an accessor, this returns the empty
// string. // string.
func (s *Secret) TokenAccessor() string { func (s *Secret) TokenAccessor() (string, error) {
if s == nil { if s == nil {
return "" return "", nil
} }
if s.Auth != nil && len(s.Auth.Accessor) > 0 { if s.Auth != nil && len(s.Auth.Accessor) > 0 {
return s.Auth.Accessor return s.Auth.Accessor, nil
} }
if s.Data == nil || s.Data["accessor"] == nil { if s.Data == nil || s.Data["accessor"] == nil {
return "" return "", nil
} }
accessor, ok := s.Data["accessor"].(string) accessor, ok := s.Data["accessor"].(string)
if !ok { if !ok {
return "" return "", fmt.Errorf("token found but in the wrong format")
} }
return accessor return accessor, nil
} }
// TokenRemainingUses returns the standardized remaining uses for the given // TokenRemainingUses returns the standardized remaining uses for the given
// secret. If the secret is nil or does not contain the "num_uses", this returns // secret. If the secret is nil or does not contain the "num_uses", this
// 0.. // returns -1. On error, this will return -1 and a non-nil error.
func (s *Secret) TokenRemainingUses() int { func (s *Secret) TokenRemainingUses() (int, error) {
if s == nil || s.Data == nil || s.Data["num_uses"] == nil { if s == nil || s.Data == nil || s.Data["num_uses"] == nil {
return 0 return -1, nil
} }
usesStr, ok := s.Data["num_uses"].(json.Number) uses, err := parseutil.ParseInt(s.Data["num_uses"])
if !ok {
return 0
}
if string(usesStr) == "" {
return 0
}
uses, err := strconv.ParseInt(string(usesStr), 10, 64)
if err != nil { if err != nil {
return 0 return 0, err
} }
return int(uses) return int(uses), nil
} }
// TokenPolicies returns the standardized list of policies for the given secret. // TokenPolicies returns the standardized list of policies for the given secret.
// If the secret is nil or does not contain any policies, this returns nil. // If the secret is nil or does not contain any policies, this returns nil.
// Policies are usually returned as []interface{}, but this function ensures func (s *Secret) TokenPolicies() ([]string, error) {
// they are []string.
func (s *Secret) TokenPolicies() []string {
if s == nil { if s == nil {
return nil return nil, nil
} }
if s.Auth != nil && len(s.Auth.Policies) > 0 { if s.Auth != nil && len(s.Auth.Policies) > 0 {
return s.Auth.Policies return s.Auth.Policies, nil
} }
if s.Data == nil || s.Data["policies"] == nil { if s.Data == nil || s.Data["policies"] == nil {
return nil return nil, nil
}
sList, ok := s.Data["policies"].([]string)
if ok {
return sList, nil
} }
list, ok := s.Data["policies"].([]interface{}) list, ok := s.Data["policies"].([]interface{})
if !ok { if !ok {
return nil return nil, fmt.Errorf("unable to convert token policies to expected format")
} }
policies := make([]string, len(list)) policies := make([]string, len(list))
for i := range list { for i := range list {
p, ok := list[i].(string) p, ok := list[i].(string)
if !ok { if !ok {
return nil return nil, fmt.Errorf("unable to convert policy %v to string", list[i])
} }
policies[i] = p policies[i] = p
} }
return policies return policies, nil
} }
// TokenMetadata returns the map of metadata associated with this token, if any // TokenMetadata returns the map of metadata associated with this token, if any
// exists. If the secret is nil or does not contain the "metadata" key, this // exists. If the secret is nil or does not contain the "metadata" key, this
// returns nil. // returns nil.
func (s *Secret) TokenMetadata() map[string]string { func (s *Secret) TokenMetadata() (map[string]string, error) {
if s == nil { if s == nil {
return nil return nil, nil
} }
if s.Auth != nil && len(s.Auth.Metadata) > 0 { if s.Auth != nil && len(s.Auth.Metadata) > 0 {
return s.Auth.Metadata return s.Auth.Metadata, nil
} }
if s.Data == nil || (s.Data["metadata"] == nil && s.Data["meta"] == nil) { if s.Data == nil || (s.Data["metadata"] == nil && s.Data["meta"] == nil) {
return nil return nil, nil
} }
data, ok := s.Data["metadata"].(map[string]interface{}) data, ok := s.Data["metadata"].(map[string]interface{})
if !ok { if !ok {
data, ok = s.Data["meta"].(map[string]interface{}) data, ok = s.Data["meta"].(map[string]interface{})
if !ok { if !ok {
return nil return nil, fmt.Errorf("unable to convert metadata field to expected format")
} }
} }
@ -170,99 +164,59 @@ func (s *Secret) TokenMetadata() map[string]string {
for k, v := range data { for k, v := range data {
typed, ok := v.(string) typed, ok := v.(string)
if !ok { if !ok {
return nil return nil, fmt.Errorf("unable to convert metadata value %v to string", v)
} }
metadata[k] = typed metadata[k] = typed
} }
return metadata return metadata, nil
} }
// TokenIsRenewable returns the standardized token renewability for the given // TokenIsRenewable returns the standardized token renewability for the given
// secret. If the secret is nil or does not contain the "renewable" key, this // secret. If the secret is nil or does not contain the "renewable" key, this
// returns false. // returns false.
func (s *Secret) TokenIsRenewable() bool { func (s *Secret) TokenIsRenewable() (bool, error) {
if s == nil { if s == nil {
return false return false, nil
} }
if s.Auth != nil && s.Auth.Renewable { if s.Auth != nil && s.Auth.Renewable {
return s.Auth.Renewable return s.Auth.Renewable, nil
} }
if s.Data == nil || s.Data["renewable"] == nil { if s.Data == nil || s.Data["renewable"] == nil {
return false return false, nil
} }
renewable, ok := s.Data["renewable"].(bool) renewable, err := parseutil.ParseBool(s.Data["renewable"])
if !ok {
return false
}
return renewable
}
// TokenTTLInt returns the token's TTL as an integer number of seconds.
func (s *Secret) TokenTTLInt() int {
if s == nil {
return 0
}
if s.Auth != nil && s.Auth.LeaseDuration > 0 {
return s.Auth.LeaseDuration
}
if s.Data == nil || s.Data["ttl"] == nil {
return 0
}
ttlStr, ok := s.Data["ttl"].(json.Number)
if !ok {
return 0
}
if string(ttlStr) == "" {
return 0
}
i, err := strconv.ParseInt(string(ttlStr), 0, 64)
if err != nil { if err != nil {
return 0 return false, fmt.Errorf("could not convert renewable value to a boolean: %v", err)
} }
return int(i) return renewable, nil
} }
// TokenTTL returns the standardized remaining token TTL for the given secret. // TokenTTL returns the standardized remaining token TTL for the given secret.
// If the secret is nil or does not contain a TTL, this returns the 0. // If the secret is nil or does not contain a TTL, this returns 0.
func (s *Secret) TokenTTL() time.Duration { func (s *Secret) TokenTTL() (time.Duration, error) {
if s == nil { if s == nil {
return 0 return 0, nil
} }
if s.Auth != nil && s.Auth.LeaseDuration > 0 { if s.Auth != nil && s.Auth.LeaseDuration > 0 {
return time.Duration(s.Auth.LeaseDuration) * time.Second return time.Duration(s.Auth.LeaseDuration) * time.Second, nil
} }
if s.Data == nil || s.Data["ttl"] == nil { if s.Data == nil || s.Data["ttl"] == nil {
return 0 return 0, nil
} }
ttlStr, ok := s.Data["ttl"].(json.Number) ttl, err := parseutil.ParseDurationSecond(s.Data["ttl"])
if !ok {
return 0
}
if string(ttlStr) == "" {
return 0
}
ttl, err := time.ParseDuration(string(ttlStr) + "s")
if err != nil { if err != nil {
return 0 return 0, err
} }
return ttl return ttl, nil
} }
// SecretWrapInfo contains wrapping information if we have it. If what is // SecretWrapInfo contains wrapping information if we have it. If what is

File diff suppressed because it is too large Load Diff

View File

@ -95,15 +95,39 @@ func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, erro
// Return an auth struct that "looks" like the response from an auth method. // Return an auth struct that "looks" like the response from an auth method.
// lookup and lookup-self return their data in data, not auth. We try to // lookup and lookup-self return their data in data, not auth. We try to
// mirror that data here. // mirror that data here.
id, err := secret.TokenID()
if err != nil {
return nil, fmt.Errorf("Error accessing token ID: %s", err)
}
accessor, err := secret.TokenAccessor()
if err != nil {
return nil, fmt.Errorf("Error accessing token accessor: %s", err)
}
policies, err := secret.TokenPolicies()
if err != nil {
return nil, fmt.Errorf("Error accessing token policies: %s", err)
}
metadata, err := secret.TokenMetadata()
if err != nil {
return nil, fmt.Errorf("Error accessing token metadata: %s", err)
}
dur, err := secret.TokenTTL()
if err != nil {
return nil, fmt.Errorf("Error converting token TTL: %s", err)
}
renewable, err := secret.TokenIsRenewable()
if err != nil {
return nil, fmt.Errorf("Error checking if token is renewable: %s", err)
}
return &api.Secret{ return &api.Secret{
Auth: &api.SecretAuth{ Auth: &api.SecretAuth{
ClientToken: secret.TokenID(), ClientToken: id,
Accessor: secret.TokenAccessor(), Accessor: accessor,
Policies: secret.TokenPolicies(), Policies: policies,
Metadata: secret.TokenMetadata(), Metadata: metadata,
LeaseDuration: secret.TokenTTLInt(), LeaseDuration: int(dur.Seconds()),
Renewable: secret.TokenIsRenewable(), Renewable: renewable,
}, },
}, nil }, nil

View File

@ -478,7 +478,10 @@ func TestLoginCommand_Run(t *testing.T) {
// There was 1 use to start, make sure we didn't use it (verifying would // There was 1 use to start, make sure we didn't use it (verifying would
// use it). // use it).
uses := lookup.TokenRemainingUses() uses, err := lookup.TokenRemainingUses()
if err != nil {
t.Fatal(err)
}
if uses != 1 { if uses != 1 {
t.Errorf("expected %d to be %d", uses, 1) t.Errorf("expected %d to be %d", uses, 1)
} }

View File

@ -56,6 +56,43 @@ func ParseDurationSecond(in interface{}) (time.Duration, error) {
return dur, nil return dur, nil
} }
func ParseInt(in interface{}) (int64, error) {
var ret int64
jsonIn, ok := in.(json.Number)
if ok {
in = jsonIn.String()
}
switch in.(type) {
case string:
inp := in.(string)
if inp == "" {
return 0, nil
}
var err error
left, err := strconv.ParseInt(inp, 10, 64)
if err != nil {
return ret, err
}
ret = left
case int:
ret = int64(in.(int))
case int32:
ret = int64(in.(int32))
case int64:
ret = in.(int64)
case uint:
ret = int64(in.(uint))
case uint32:
ret = int64(in.(uint32))
case uint64:
ret = int64(in.(uint64))
default:
return 0, errors.New("could not parse value from input")
}
return ret, nil
}
func ParseBool(in interface{}) (bool, error) { func ParseBool(in interface{}) (bool, error) {
var result bool var result bool
if err := mapstructure.WeakDecode(in, &result); err != nil { if err := mapstructure.WeakDecode(in, &result); err != nil {