Add token accessor to wrap information if one exists

This commit is contained in:
Jeff Mitchell 2016-06-13 23:58:17 +00:00
parent 8b4c39ea1b
commit e925987cb6
13 changed files with 80 additions and 36 deletions

View File

@ -31,11 +31,14 @@ type Secret struct {
WrapInfo *SecretWrapInfo `json:"wrap_info,omitempty"`
}
// SecretWrapInfo contains wrapping information if we have it.
// 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.
type SecretWrapInfo struct {
Token string `json:"token"`
TTL int `json:"ttl"`
CreationTime time.Time `json:"creation_time"`
Token string `json:"token"`
TTL int `json:"ttl"`
CreationTime time.Time `json:"creation_time"`
WrappedAccessor string `json:"wrapped_accessor"`
}
// SecretAuth is the structure containing auth information if we have it.

View File

@ -22,7 +22,8 @@ func TestParseSecret(t *testing.T) {
"wrap_info": {
"token": "token",
"ttl": 60,
"creation_time": "2016-06-07T15:52:10-04:00"
"creation_time": "2016-06-07T15:52:10-04:00",
"wrapped_accessor": "abcd1234"
}
}`)
@ -44,9 +45,10 @@ func TestParseSecret(t *testing.T) {
"a warning!",
},
WrapInfo: &SecretWrapInfo{
Token: "token",
TTL: 60,
CreationTime: rawTime,
Token: "token",
TTL: 60,
CreationTime: rawTime,
WrappedAccessor: "abcd1234",
},
}
if !reflect.DeepEqual(secret, expected) {

View File

@ -90,9 +90,10 @@ func (f *FormatJSON) FormatResponse(
var respWrapInfo *JSONWrapInfo
if resp.WrapInfo != nil {
respWrapInfo = &JSONWrapInfo{
TTL: int(resp.WrapInfo.TTL / time.Second),
Token: resp.WrapInfo.Token,
CreationTime: resp.WrapInfo.CreationTime,
TTL: int(resp.WrapInfo.TTL / time.Second),
Token: resp.WrapInfo.Token,
CreationTime: resp.WrapInfo.CreationTime,
WrappedAccessor: resp.WrapInfo.WrappedAccessor,
}
}
@ -110,11 +111,12 @@ func (f *FormatJSON) FormatResponse(
},
Request: JSONRequest{
Operation: req.Operation,
Path: req.Path,
Data: req.Data,
RemoteAddr: getRemoteAddr(req),
WrapTTL: int(req.WrapTTL / time.Second),
ClientToken: req.ClientToken,
Operation: req.Operation,
Path: req.Path,
Data: req.Data,
RemoteAddr: getRemoteAddr(req),
WrapTTL: int(req.WrapTTL / time.Second),
},
Response: JSONResponse{
@ -176,9 +178,10 @@ type JSONSecret struct {
}
type JSONWrapInfo struct {
TTL int `json:"ttl"`
Token string `json:"token"`
CreationTime time.Time `json:"creation_time"`
TTL int `json:"ttl"`
Token string `json:"token"`
CreationTime time.Time `json:"creation_time"`
WrappedAccessor string `json:"wrapped_accessor,omitempty"`
}
// getRemoteAddr safely gets the remote address avoiding a nil pointer

View File

@ -86,6 +86,10 @@ func Hash(salter *salt.Salt, raw interface{}) error {
}
s.Token = fn(s.Token)
if s.WrappedAccessor != "" {
s.WrappedAccessor = fn(s.WrappedAccessor)
}
}
return nil

View File

@ -68,9 +68,10 @@ func TestCopy_response(t *testing.T) {
"foo": "bar",
},
WrapInfo: &logical.WrapInfo{
TTL: 60,
Token: "foo",
CreationTime: time.Now(),
TTL: 60,
Token: "foo",
CreationTime: time.Now(),
WrappedAccessor: "abcd1234",
},
}
arg := expected
@ -138,9 +139,10 @@ func TestHash(t *testing.T) {
"foo": "bar",
},
WrapInfo: &logical.WrapInfo{
TTL: 60,
Token: "bar",
CreationTime: now,
TTL: 60,
Token: "bar",
CreationTime: now,
WrappedAccessor: "bar",
},
},
&logical.Response{
@ -148,9 +150,10 @@ func TestHash(t *testing.T) {
"foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
},
WrapInfo: &logical.WrapInfo{
TTL: 60,
Token: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
CreationTime: now,
TTL: 60,
Token: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
CreationTime: now,
WrappedAccessor: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
},
},
},

View File

@ -167,7 +167,7 @@ func (b *Backend) LogResponse(
// Hash any sensitive information
// Cache and restore accessor in the auth
var accessor string
var accessor, wrappedAccessor string
if !b.hmacAccessor && auth != nil && auth.Accessor != "" {
accessor = auth.Accessor
}
@ -187,12 +187,18 @@ func (b *Backend) LogResponse(
if !b.hmacAccessor && resp != nil && resp.Auth != nil && resp.Auth.Accessor != "" {
accessor = resp.Auth.Accessor
}
if !b.hmacAccessor && resp != nil && resp.WrapInfo != nil && resp.WrapInfo.WrappedAccessor != "" {
wrappedAccessor = resp.WrapInfo.WrappedAccessor
}
if err := audit.Hash(b.salt, resp); err != nil {
return err
}
if accessor != "" {
resp.Auth.Accessor = accessor
}
if wrappedAccessor != "" {
resp.WrapInfo.WrappedAccessor = wrappedAccessor
}
}
var format audit.FormatJSON

View File

@ -159,7 +159,7 @@ func (b *Backend) LogResponse(auth *logical.Auth, req *logical.Request,
// Hash any sensitive information
// Cache and restore accessor in the auth
var accessor string
var accessor, wrappedAccessor string
if !b.hmacAccessor && auth != nil && auth.Accessor != "" {
accessor = auth.Accessor
}
@ -179,12 +179,18 @@ func (b *Backend) LogResponse(auth *logical.Auth, req *logical.Request,
if !b.hmacAccessor && resp != nil && resp.Auth != nil && resp.Auth.Accessor != "" {
accessor = resp.Auth.Accessor
}
if !b.hmacAccessor && resp != nil && resp.WrapInfo != nil && resp.WrapInfo.WrappedAccessor != "" {
wrappedAccessor = resp.WrapInfo.WrappedAccessor
}
if err := audit.Hash(b.salt, resp); err != nil {
return err
}
if accessor != "" {
resp.Auth.Accessor = accessor
}
if wrappedAccessor != "" {
resp.WrapInfo.WrappedAccessor = wrappedAccessor
}
}
// Encode the entry as JSON

View File

@ -161,6 +161,9 @@ func (t TableFormatter) OutputSecret(ui cli.Ui, secret, s *api.Secret) error {
input = append(input, fmt.Sprintf("wrapping_token: %s %s", config.Delim, s.WrapInfo.Token))
input = append(input, fmt.Sprintf("wrapping_token_ttl: %s %d", config.Delim, s.WrapInfo.TTL))
input = append(input, fmt.Sprintf("wrapping_token_creation_time: %s %s", config.Delim, s.WrapInfo.CreationTime.String()))
if s.WrapInfo.WrappedAccessor != "" {
input = append(input, fmt.Sprintf("wrapped_accessor: %s %s", config.Delim, s.WrapInfo.WrappedAccessor))
}
}
keys := make([]string, 0, len(s.Data))

View File

@ -44,6 +44,10 @@ func PrintRawField(ui cli.Ui, secret *api.Secret, field string) int {
if secret.WrapInfo != nil {
val = secret.WrapInfo.CreationTime.String()
}
case "wrapped_accessor":
if secret.WrapInfo != nil {
val = secret.WrapInfo.WrappedAccessor
}
case "refresh_interval":
val = secret.LeaseDuration
default:

View File

@ -163,9 +163,10 @@ func respondLogical(w http.ResponseWriter, r *http.Request, path string, dataOnl
if resp.WrapInfo != nil && resp.WrapInfo.Token != "" {
httpResp = logical.HTTPResponse{
WrapInfo: &logical.HTTPWrapInfo{
Token: resp.WrapInfo.Token,
TTL: int(resp.WrapInfo.TTL.Seconds()),
CreationTime: resp.WrapInfo.CreationTime,
Token: resp.WrapInfo.Token,
TTL: int(resp.WrapInfo.TTL.Seconds()),
CreationTime: resp.WrapInfo.CreationTime,
WrappedAccessor: resp.WrapInfo.WrappedAccessor,
},
}
} else {

View File

@ -38,6 +38,10 @@ type WrapInfo struct {
// The creation time. This can be used with the TTL to figure out an
// expected expiration.
CreationTime time.Time
// If the contained response is the output of a token creation call, the
// created token's accessor will be accessible here
WrappedAccessor string
}
// Response is a struct that stores the response of a request.

View File

@ -54,7 +54,8 @@ type HTTPAuth struct {
}
type HTTPWrapInfo struct {
Token string `json:"token"`
TTL int `json:"ttl"`
CreationTime time.Time `json:"creation_time"`
Token string `json:"token"`
TTL int `json:"ttl"`
CreationTime time.Time `json:"creation_time"`
WrappedAccessor string `json:"wrapped_accessor,omitempty"`
}

View File

@ -393,6 +393,10 @@ func (c *Core) wrapInCubbyhole(req *logical.Request, resp *logical.Response) (*l
resp.WrapInfo.Token = te.ID
resp.WrapInfo.CreationTime = creationTime
if resp.Auth != nil {
resp.WrapInfo.WrappedAccessor = resp.Auth.Accessor
}
httpResponse := logical.SanitizeResponse(resp)
// Because of the way that JSON encodes (likely just in Go) we actually get