From 47dc1ccd259545cf2195173a72d8daa82b42b758 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 13 Jun 2016 23:58:17 +0000 Subject: [PATCH 1/2] Add token accessor to wrap information if one exists --- api/secret.go | 11 +++++++---- api/secret_test.go | 10 ++++++---- audit/format_json.go | 25 ++++++++++++++----------- audit/hashstructure.go | 4 ++++ audit/hashstructure_test.go | 21 ++++++++++++--------- builtin/audit/file/backend.go | 8 +++++++- builtin/audit/syslog/backend.go | 8 +++++++- command/format.go | 3 +++ command/util.go | 4 ++++ http/logical.go | 7 ++++--- logical/response.go | 4 ++++ logical/sanitize.go | 7 ++++--- vault/request_handling.go | 4 ++++ 13 files changed, 80 insertions(+), 36 deletions(-) diff --git a/api/secret.go b/api/secret.go index 378f287078480..d0a539e47f196 100644 --- a/api/secret.go +++ b/api/secret.go @@ -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. diff --git a/api/secret_test.go b/api/secret_test.go index c4efc9b6984ff..3b6496677a015 100644 --- a/api/secret_test.go +++ b/api/secret_test.go @@ -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) { diff --git a/audit/format_json.go b/audit/format_json.go index 007113553f01d..2850ce247239b 100644 --- a/audit/format_json.go +++ b/audit/format_json.go @@ -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 diff --git a/audit/hashstructure.go b/audit/hashstructure.go index 8e78c0ce28ed8..f428847b0d1ae 100644 --- a/audit/hashstructure.go +++ b/audit/hashstructure.go @@ -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 diff --git a/audit/hashstructure_test.go b/audit/hashstructure_test.go index eb3f9208f8c33..26b1d4153a3cc 100644 --- a/audit/hashstructure_test.go +++ b/audit/hashstructure_test.go @@ -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", }, }, }, diff --git a/builtin/audit/file/backend.go b/builtin/audit/file/backend.go index 52a6733521b13..704569635774f 100644 --- a/builtin/audit/file/backend.go +++ b/builtin/audit/file/backend.go @@ -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 diff --git a/builtin/audit/syslog/backend.go b/builtin/audit/syslog/backend.go index e6f461a6a8684..c603ed83664cc 100644 --- a/builtin/audit/syslog/backend.go +++ b/builtin/audit/syslog/backend.go @@ -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 diff --git a/command/format.go b/command/format.go index 8f9883e4f1983..3350d705605b8 100644 --- a/command/format.go +++ b/command/format.go @@ -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)) diff --git a/command/util.go b/command/util.go index 6666bc2fd8030..fc10487d399f0 100644 --- a/command/util.go +++ b/command/util.go @@ -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: diff --git a/http/logical.go b/http/logical.go index 0875d694e6546..94b434ec8e991 100644 --- a/http/logical.go +++ b/http/logical.go @@ -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 { diff --git a/logical/response.go b/logical/response.go index 0e53802e09a7d..033524f84dbf6 100644 --- a/logical/response.go +++ b/logical/response.go @@ -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. diff --git a/logical/sanitize.go b/logical/sanitize.go index 76079902833e2..3ea28aa61b67a 100644 --- a/logical/sanitize.go +++ b/logical/sanitize.go @@ -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"` } diff --git a/vault/request_handling.go b/vault/request_handling.go index 7cefb2a9bba95..ff84f02ff713a 100644 --- a/vault/request_handling.go +++ b/vault/request_handling.go @@ -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 From 65cdcd67992f520f7639dd04634738945072e830 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Tue, 14 Jun 2016 05:54:09 +0000 Subject: [PATCH 2/2] Add some commenting --- vault/request_handling.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vault/request_handling.go b/vault/request_handling.go index ff84f02ff713a..7498c8a03bc74 100644 --- a/vault/request_handling.go +++ b/vault/request_handling.go @@ -393,6 +393,8 @@ func (c *Core) wrapInCubbyhole(req *logical.Request, resp *logical.Response) (*l resp.WrapInfo.Token = te.ID resp.WrapInfo.CreationTime = creationTime + // This will only be non-nil if this response contains a token, so in that + // case put the accessor in the wrap info. if resp.Auth != nil { resp.WrapInfo.WrappedAccessor = resp.Auth.Accessor }