Skip to content

Commit

Permalink
Merge pull request #1520 from hashicorp/wrapinfo-accessor
Browse files Browse the repository at this point in the history
Add token accessor to wrap information if one exists
  • Loading branch information
jefferai committed Jun 14, 2016
2 parents 4f039d0 + 65cdcd6 commit 926e56e
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 36 deletions.
11 changes: 7 additions & 4 deletions api/secret.go
Expand Up @@ -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.
Expand Down
10 changes: 6 additions & 4 deletions api/secret_test.go
Expand Up @@ -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"
}
}`)

Expand All @@ -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) {
Expand Down
25 changes: 14 additions & 11 deletions audit/format_json.go
Expand Up @@ -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,
}
}

Expand All @@ -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{
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions audit/hashstructure.go
Expand Up @@ -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
Expand Down
21 changes: 12 additions & 9 deletions audit/hashstructure_test.go
Expand Up @@ -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
Expand Down Expand Up @@ -138,19 +139,21 @@ 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{
Data: map[string]interface{}{
"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",
},
},
},
Expand Down
8 changes: 7 additions & 1 deletion builtin/audit/file/backend.go
Expand Up @@ -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
}
Expand All @@ -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
Expand Down
8 changes: 7 additions & 1 deletion builtin/audit/syslog/backend.go
Expand Up @@ -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
}
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions command/format.go
Expand Up @@ -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))
Expand Down
4 changes: 4 additions & 0 deletions command/util.go
Expand Up @@ -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:
Expand Down
7 changes: 4 additions & 3 deletions http/logical.go
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions logical/response.go
Expand Up @@ -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.
Expand Down
7 changes: 4 additions & 3 deletions logical/sanitize.go
Expand Up @@ -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"`
}
6 changes: 6 additions & 0 deletions vault/request_handling.go
Expand Up @@ -393,6 +393,12 @@ 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
}

httpResponse := logical.SanitizeResponse(resp)

// Because of the way that JSON encodes (likely just in Go) we actually get
Expand Down

0 comments on commit 926e56e

Please sign in to comment.