open-vault/api/secret.go

267 lines
6.1 KiB
Go
Raw Normal View History

2015-03-12 00:46:25 +00:00
package api
import (
2017-09-02 22:48:48 +00:00
"encoding/json"
2015-03-12 00:46:25 +00:00
"io"
2017-09-02 22:48:48 +00:00
"strconv"
"time"
"github.com/hashicorp/vault/helper/jsonutil"
2015-03-12 00:46:25 +00:00
)
// Secret is the structure returned for every secret within Vault.
type Secret struct {
2016-07-27 13:25:04 +00:00
// The request ID that generated this response
RequestID string `json:"request_id"`
2015-04-14 00:40:05 +00:00
LeaseID string `json:"lease_id"`
LeaseDuration int `json:"lease_duration"`
Renewable bool `json:"renewable"`
// Data is the actual contents of the secret. The format of the data
// is arbitrary and up to the secret backend.
Data map[string]interface{} `json:"data"`
// Warnings contains any warnings related to the operation. These
// are not issues that caused the command to fail, but that the
// client should be aware of.
Warnings []string `json:"warnings"`
2015-04-14 00:40:05 +00:00
// Auth, if non-nil, means that there was authentication information
// attached to this response.
Auth *SecretAuth `json:"auth,omitempty"`
2016-05-02 05:58:58 +00:00
// WrapInfo, if non-nil, means that the initial response was wrapped in the
// cubbyhole of the given token (which has a TTL of the given number of
// seconds)
WrapInfo *SecretWrapInfo `json:"wrap_info,omitempty"`
}
2017-09-02 22:48:48 +00:00
// TokenID returns the standardized token ID (token) for the given secret.
func (s *Secret) TokenID() string {
if s == nil {
return ""
}
if s.Auth != nil && len(s.Auth.ClientToken) > 0 {
return s.Auth.ClientToken
}
if s.Data == nil || s.Data["id"] == nil {
return ""
}
id, ok := s.Data["id"].(string)
if !ok {
return ""
}
return id
}
// 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
// string.
func (s *Secret) TokenAccessor() string {
if s == nil {
return ""
}
if s.Auth != nil && len(s.Auth.Accessor) > 0 {
return s.Auth.Accessor
}
if s.Data == nil || s.Data["accessor"] == nil {
return ""
}
accessor, ok := s.Data["accessor"].(string)
if !ok {
return ""
}
return accessor
}
// TokenMeta returns the standardized token metadata for the given secret.
// If the secret is nil or does not contain an accessor, this returns the empty
// string. Metadata is usually modeled as an map[string]interface{}, but token
// metdata is always a map[string]string. This function handles the coercion.
func (s *Secret) TokenMeta() map[string]string {
if s == nil {
return nil
}
if s.Auth != nil && len(s.Auth.Metadata) > 0 {
return s.Auth.Metadata
}
if s.Data == nil || s.Data["meta"] == nil {
return nil
}
metaRaw, ok := s.Data["meta"].(map[string]interface{})
if !ok {
return nil
}
meta := make(map[string]string, len(metaRaw))
for k, v := range metaRaw {
m, ok := v.(string)
if !ok {
return nil
}
meta[k] = m
}
return meta
}
// TokenRemainingUses returns the standardized remaining uses for the given
// secret. If the secret is nil or does not contain the "num_uses", this returns
// 0..
func (s *Secret) TokenRemainingUses() int {
if s == nil || s.Data == nil || s.Data["num_uses"] == nil {
return 0
}
usesStr, ok := s.Data["num_uses"].(json.Number)
if !ok {
return 0
}
if string(usesStr) == "" {
return 0
}
uses, err := strconv.ParseInt(string(usesStr), 10, 64)
if err != nil {
return 0
}
return int(uses)
}
// 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.
// Policies are usually returned as []interface{}, but this function ensures
// they are []string.
func (s *Secret) TokenPolicies() []string {
if s == nil {
return nil
}
if s.Auth != nil && len(s.Auth.Policies) > 0 {
return s.Auth.Policies
}
if s.Data == nil || s.Data["policies"] == nil {
return nil
}
list, ok := s.Data["policies"].([]interface{})
if !ok {
return nil
}
policies := make([]string, len(list))
for i := range list {
p, ok := list[i].(string)
if !ok {
return nil
}
policies[i] = p
}
return policies
}
// TokenIsRenewable returns the standardized token renewability for the given
// secret. If the secret is nil or does not contain the "renewable" key, this
// returns false.
func (s *Secret) TokenIsRenewable() bool {
if s == nil {
return false
}
if s.Auth != nil && s.Auth.Renewable {
return s.Auth.Renewable
}
if s.Data == nil || s.Data["renewable"] == nil {
return false
}
renewable, ok := s.Data["renewable"].(bool)
if !ok {
return false
}
return renewable
}
// 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.
func (s *Secret) TokenTTL() time.Duration {
if s == nil {
return 0
}
if s.Auth != nil && s.Auth.LeaseDuration > 0 {
return time.Duration(s.Auth.LeaseDuration) * time.Second
}
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
}
ttl, err := time.ParseDuration(string(ttlStr) + "s")
if err != nil {
return 0
}
return ttl
}
// SecretWrapInfo contains wrapping information if we have it. If what is
// contained is an authentication token, the accessor for the token will be
// available in WrappedAccessor.
2016-05-02 05:58:58 +00:00
type SecretWrapInfo struct {
Token string `json:"token"`
TTL int `json:"ttl"`
CreationTime time.Time `json:"creation_time"`
CreationPath string `json:"creation_path"`
WrappedAccessor string `json:"wrapped_accessor"`
2015-04-04 22:40:41 +00:00
}
2015-09-29 07:35:16 +00:00
// SecretAuth is the structure containing auth information if we have it.
2015-04-04 22:40:41 +00:00
type SecretAuth struct {
ClientToken string `json:"client_token"`
Accessor string `json:"accessor"`
2015-04-04 22:40:41 +00:00
Policies []string `json:"policies"`
Metadata map[string]string `json:"metadata"`
LeaseDuration int `json:"lease_duration"`
Renewable bool `json:"renewable"`
2015-03-12 00:46:25 +00:00
}
// ParseSecret is used to parse a secret value from JSON from an io.Reader.
func ParseSecret(r io.Reader) (*Secret, error) {
// First decode the JSON into a map[string]interface{}
2015-03-16 03:35:33 +00:00
var secret Secret
if err := jsonutil.DecodeJSONFromReader(r, &secret); err != nil {
2015-03-12 00:46:25 +00:00
return nil, err
}
2015-03-16 03:35:33 +00:00
return &secret, nil
2015-03-12 00:46:25 +00:00
}