Skip to content

Commit

Permalink
Add support for hashing time.Time within slices (#6767)
Browse files Browse the repository at this point in the history
Add support for hashing time.Time within slices, which unbreaks auditing of requests returning the request counters.  

Break Hash into struct-specific func like HashAuth, HashRequest. Move all the copying/hashing logic from FormatRequest/FormatResponse into the new Hash* funcs.  HashStructure now modifies in place instead of copying.

Instead of returning an error when trying to hash map keys of type time.Time, ignore them, i.e. pass them through unhashed.

Enable auditing on test clusters by default if the caller didn't specify any audit backends.  If they do, they're responsible for setting it up.
  • Loading branch information
ncabatoff authored Jul 2, 2019
1 parent 8f6d200 commit 056e90b
Show file tree
Hide file tree
Showing 4 changed files with 424 additions and 362 deletions.
190 changes: 22 additions & 168 deletions audit/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package audit
import (
"context"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"strings"
Expand All @@ -15,12 +14,14 @@ import (
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/logical"
"github.com/mitchellh/copystructure"
)

type AuditFormatWriter interface {
// WriteRequest writes the request entry to the writer or returns an error.
WriteRequest(io.Writer, *AuditRequestEntry) error
// WriteResponse writes the response entry to the writer or returns an error.
WriteResponse(io.Writer, *AuditResponseEntry) error
// Salt returns a non-nil salt or an error.
Salt(context.Context) (*salt.Salt, error)
}

Expand Down Expand Up @@ -54,79 +55,26 @@ func (f *AuditFormatter) FormatRequest(ctx context.Context, w io.Writer, config
auth := in.Auth
req := in.Request
var connState *tls.ConnectionState
if auth == nil {
auth = new(logical.Auth)
}

if in.Request.Connection != nil && in.Request.Connection.ConnState != nil {
connState = in.Request.Connection.ConnState
}

if !config.Raw {
// Before we copy the structure we must nil out some data
// otherwise we will cause reflection to panic and die
if connState != nil {
in.Request.Connection.ConnState = nil
defer func() {
in.Request.Connection.ConnState = connState
}()
}

// Copy the auth structure
if in.Auth != nil {
cp, err := copystructure.Copy(in.Auth)
if err != nil {
return err
}
auth = cp.(*logical.Auth)
}

cp, err := copystructure.Copy(in.Request)
auth, err = HashAuth(salt, auth, config.HMACAccessor)
if err != nil {
return err
}
req = cp.(*logical.Request)
for k, v := range req.Data {
if o, ok := v.(logical.OptMarshaler); ok {
marshaled, err := o.MarshalJSONWithOptions(&logical.MarshalOptions{
ValueHasher: salt.GetIdentifiedHMAC,
})
if err != nil {
return err
}
req.Data[k] = json.RawMessage(marshaled)
}
}

// Hash any sensitive information
if auth != nil {
// Cache and restore accessor in the auth
var authAccessor string
if !config.HMACAccessor && auth.Accessor != "" {
authAccessor = auth.Accessor
}
if err := Hash(salt, auth, nil); err != nil {
return err
}
if authAccessor != "" {
auth.Accessor = authAccessor
}
}

// Cache and restore accessor in the request
var clientTokenAccessor string
if !config.HMACAccessor && req != nil && req.ClientTokenAccessor != "" {
clientTokenAccessor = req.ClientTokenAccessor
}
if err := Hash(salt, req, in.NonHMACReqDataKeys); err != nil {
req, err = HashRequest(salt, req, config.HMACAccessor, in.NonHMACReqDataKeys)
if err != nil {
return err
}
if clientTokenAccessor != "" {
req.ClientTokenAccessor = clientTokenAccessor
}
}

// If auth is nil, make an empty one
if auth == nil {
auth = new(logical.Auth)
}
var errString string
if in.OuterErr != nil {
errString = in.OuterErr.Error()
Expand Down Expand Up @@ -209,130 +157,36 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
}

// Set these to the input values at first
auth := in.Auth
req := in.Request
resp := in.Response
auth, req, resp := in.Auth, in.Request, in.Response
if auth == nil {
auth = new(logical.Auth)
}
if resp == nil {
resp = new(logical.Response)
}
var connState *tls.ConnectionState

if in.Request.Connection != nil && in.Request.Connection.ConnState != nil {
connState = in.Request.Connection.ConnState
}

if !config.Raw {
// Before we copy the structure we must nil out some data
// otherwise we will cause reflection to panic and die
if connState != nil {
in.Request.Connection.ConnState = nil
defer func() {
in.Request.Connection.ConnState = connState
}()
}

// Copy the auth structure
if in.Auth != nil {
cp, err := copystructure.Copy(in.Auth)
if err != nil {
return err
}
auth = cp.(*logical.Auth)
}

cp, err := copystructure.Copy(in.Request)
auth, err = HashAuth(salt, auth, config.HMACAccessor)
if err != nil {
return err
}
req = cp.(*logical.Request)
for k, v := range req.Data {
if o, ok := v.(logical.OptMarshaler); ok {
marshaled, err := o.MarshalJSONWithOptions(&logical.MarshalOptions{
ValueHasher: salt.GetIdentifiedHMAC,
})
if err != nil {
return err
}
req.Data[k] = json.RawMessage(marshaled)
}
}

if in.Response != nil {
cp, err := copystructure.Copy(in.Response)
if err != nil {
return err
}
resp = cp.(*logical.Response)
for k, v := range resp.Data {
if o, ok := v.(logical.OptMarshaler); ok {
marshaled, err := o.MarshalJSONWithOptions(&logical.MarshalOptions{
ValueHasher: salt.GetIdentifiedHMAC,
})
if err != nil {
return err
}
resp.Data[k] = json.RawMessage(marshaled)
}
}
}

// Hash any sensitive information

// Cache and restore accessor in the auth
if auth != nil {
var accessor string
if !config.HMACAccessor && auth.Accessor != "" {
accessor = auth.Accessor
}
if err := Hash(salt, auth, nil); err != nil {
return err
}
if accessor != "" {
auth.Accessor = accessor
}
}

// Cache and restore accessor in the request
var clientTokenAccessor string
if !config.HMACAccessor && req != nil && req.ClientTokenAccessor != "" {
clientTokenAccessor = req.ClientTokenAccessor
}
if err := Hash(salt, req, in.NonHMACReqDataKeys); err != nil {
req, err = HashRequest(salt, req, config.HMACAccessor, in.NonHMACReqDataKeys)
if err != nil {
return err
}
if clientTokenAccessor != "" {
req.ClientTokenAccessor = clientTokenAccessor
}

// Cache and restore accessor in the response
if resp != nil {
var accessor, wrappedAccessor, wrappingAccessor string
if !config.HMACAccessor && resp != nil && resp.Auth != nil && resp.Auth.Accessor != "" {
accessor = resp.Auth.Accessor
}
if !config.HMACAccessor && resp != nil && resp.WrapInfo != nil && resp.WrapInfo.WrappedAccessor != "" {
wrappedAccessor = resp.WrapInfo.WrappedAccessor
wrappingAccessor = resp.WrapInfo.Accessor
}
if err := Hash(salt, resp, in.NonHMACRespDataKeys); err != nil {
return err
}
if accessor != "" {
resp.Auth.Accessor = accessor
}
if wrappedAccessor != "" {
resp.WrapInfo.WrappedAccessor = wrappedAccessor
}
if wrappingAccessor != "" {
resp.WrapInfo.Accessor = wrappingAccessor
}
resp, err = HashResponse(salt, resp, config.HMACAccessor, in.NonHMACRespDataKeys)
if err != nil {
return err
}
}

// If things are nil, make empty to avoid panics
if auth == nil {
auth = new(logical.Auth)
}
if resp == nil {
resp = new(logical.Response)
}
var errString string
if in.OuterErr != nil {
errString = in.OuterErr.Error()
Expand Down
Loading

0 comments on commit 056e90b

Please sign in to comment.