diff --git a/audit/format.go b/audit/format.go index c1d0126ed8..60833a2150 100644 --- a/audit/format.go +++ b/audit/format.go @@ -3,8 +3,10 @@ package audit import ( "fmt" "io" + "strings" "time" + "github.com/SermoDigital/jose/jws" "github.com/hashicorp/vault/logical" "github.com/mitchellh/copystructure" ) @@ -87,14 +89,6 @@ func (f *AuditFormatter) FormatRequest( errString = err.Error() } - var reqWrapInfo *AuditRequestWrapInfo - if req.WrapInfo != nil { - reqWrapInfo = &AuditRequestWrapInfo{ - TTL: int(req.WrapInfo.TTL / time.Second), - Format: req.WrapInfo.Format, - } - } - reqEntry := &AuditRequestEntry{ Type: "request", Error: errString, @@ -113,10 +107,13 @@ func (f *AuditFormatter) FormatRequest( Path: req.Path, Data: req.Data, RemoteAddr: getRemoteAddr(req), - WrapInfo: reqWrapInfo, }, } + if req.WrapInfo != nil { + reqEntry.Request.WrapTTL = int(req.WrapInfo.TTL / time.Second) + } + if !config.OmitTime { reqEntry.Time = time.Now().UTC().Format(time.RFC3339) } @@ -246,19 +243,15 @@ func (f *AuditFormatter) FormatResponse( } } - var reqWrapInfo *AuditRequestWrapInfo - if req.WrapInfo != nil { - reqWrapInfo = &AuditRequestWrapInfo{ - TTL: int(req.WrapInfo.TTL / time.Second), - Format: req.WrapInfo.Format, - } - } - var respWrapInfo *AuditResponseWrapInfo if resp.WrapInfo != nil { + token := resp.WrapInfo.Token + if jwtToken := parseVaultTokenFromJWT(token); jwtToken != nil { + token = *jwtToken + } respWrapInfo = &AuditResponseWrapInfo{ TTL: int(resp.WrapInfo.TTL / time.Second), - Token: resp.WrapInfo.Token, + Token: token, CreationTime: resp.WrapInfo.CreationTime.Format(time.RFC3339Nano), WrappedAccessor: resp.WrapInfo.WrappedAccessor, } @@ -282,7 +275,6 @@ func (f *AuditFormatter) FormatResponse( Path: req.Path, Data: req.Data, RemoteAddr: getRemoteAddr(req), - WrapInfo: reqWrapInfo, }, Response: AuditResponse{ @@ -294,6 +286,10 @@ func (f *AuditFormatter) FormatResponse( }, } + if req.WrapInfo != nil { + respEntry.Request.WrapTTL = int(req.WrapInfo.TTL / time.Second) + } + if !config.OmitTime { respEntry.Time = time.Now().UTC().Format(time.RFC3339) } @@ -328,7 +324,7 @@ type AuditRequest struct { Path string `json:"path"` Data map[string]interface{} `json:"data"` RemoteAddr string `json:"remote_address"` - WrapInfo *AuditRequestWrapInfo `json:"wrap_info,omitempty"` + WrapTTL int `json:"wrap_ttl"` } type AuditResponse struct { @@ -351,11 +347,6 @@ type AuditSecret struct { LeaseID string `json:"lease_id"` } -type AuditRequestWrapInfo struct { - TTL int `json:"ttl"` - Format string `json:"format"` -} - type AuditResponseWrapInfo struct { TTL int `json:"ttl"` Token string `json:"token"` @@ -370,3 +361,20 @@ func getRemoteAddr(req *logical.Request) string { } return "" } + +// parseVaultTokenFromJWT returns a string iff the token was a JWT and we could +// extract the original token ID from inside +func parseVaultTokenFromJWT(token string) *string { + if strings.Count(token, ".") != 2 { + return nil + } + + wt, err := jws.ParseJWT([]byte(token)) + if err != nil || wt == nil { + return nil + } + + result, _ := wt.Claims().JWTID() + + return &result +} diff --git a/audit/format_json_test.go b/audit/format_json_test.go index 5b2b098484..7fb7a8a15f 100644 --- a/audit/format_json_test.go +++ b/audit/format_json_test.go @@ -76,5 +76,5 @@ func TestFormatJSON_formatRequest(t *testing.T) { } } -const testFormatJSONReqBasicStr = `{"time":"2015-08-05T13:45:46Z","type":"request","auth":{"display_name":"","policies":["root"],"metadata":null},"request":{"operation":"update","path":"/foo","data":null,"wrap_ttl":60,"remote_address":"127.0.0.1","wrap_info":{"ttl":60,"format":""}},"error":"this is an error"} +const testFormatJSONReqBasicStr = `{"time":"2015-08-05T13:45:46Z","type":"request","auth":{"display_name":"","policies":["root"],"metadata":null},"request":{"operation":"update","path":"/foo","data":null,"wrap_ttl":60,"remote_address":"127.0.0.1"},"error":"this is an error"} ` diff --git a/audit/format_jsonx_test.go b/audit/format_jsonx_test.go index 1324b534a5..40d0bc572b 100644 --- a/audit/format_jsonx_test.go +++ b/audit/format_jsonx_test.go @@ -34,7 +34,7 @@ func TestFormatJSONx_formatRequest(t *testing.T) { }, errors.New("this is an error"), "", - `rootthis is an errorupdate/foo127.0.0.160request`, + `rootthis is an errorupdate/foo127.0.0.160request`, }, } diff --git a/vault/cluster.go b/vault/cluster.go index 69c171fbfc..d2dd63704a 100644 --- a/vault/cluster.go +++ b/vault/cluster.go @@ -42,11 +42,10 @@ var ( // This can be one of a few key types so the different params may or may not be filled type clusterKeyParams struct { - Type string `json:"type"` - X *big.Int `json:"x,omitempty"` - Y *big.Int `json:"y,omitempty"` - D *big.Int `json:"d,omitempty"` - ED25519Key []byte `json:"ed25519_key,omitempty"` + Type string `json:"type"` + X *big.Int `json:"x,omitempty"` + Y *big.Int `json:"y,omitempty"` + D *big.Int `json:"d,omitempty"` } type activeConnection struct { diff --git a/vault/logical_system.go b/vault/logical_system.go index f8519527ff..534651d52a 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -1528,10 +1528,6 @@ func (b *SystemBackend) handleWrappingUnwrap( token = req.ClientToken } - if wt := b.Core.parseVaultTokenFromJWT(token); wt != nil { - token = *wt - } - if thirdParty { // Use the token to decrement the use count to avoid a second operation on the token. _, err := b.Core.tokenStore.UseTokenByID(token) @@ -1592,10 +1588,6 @@ func (b *SystemBackend) handleWrappingLookup( return logical.ErrorResponse("missing \"token\" value in input"), logical.ErrInvalidRequest } - if wt := b.Core.parseVaultTokenFromJWT(token); wt != nil { - token = *wt - } - cubbyReq := &logical.Request{ Operation: logical.ReadOperation, Path: "cubbyhole/wrapinfo", @@ -1652,10 +1644,6 @@ func (b *SystemBackend) handleWrappingRewrap( token = req.ClientToken } - if wt := b.Core.parseVaultTokenFromJWT(token); wt != nil { - token = *wt - } - if thirdParty { // Use the token to decrement the use count to avoid a second operation on the token. _, err := b.Core.tokenStore.UseTokenByID(token) diff --git a/vault/wrapping.go b/vault/wrapping.go index 9e665cc837..0dc2e9b59a 100644 --- a/vault/wrapping.go +++ b/vault/wrapping.go @@ -240,7 +240,9 @@ func (c *Core) ValidateWrappingToken(req *logical.Request) (bool, error) { var err error var token string + var thirdParty bool if req.Data != nil && req.Data["token"] != nil { + thirdParty = true if tokenStr, ok := req.Data["token"].(string); !ok { return false, fmt.Errorf("could not decode token in request body") } else if tokenStr == "" { @@ -264,6 +266,14 @@ func (c *Core) ValidateWrappingToken(req *logical.Request) (bool, error) { return false, errwrap.Wrapf("wrapping token signature could not be validated: {{err}}", err) } token, _ = wt.Claims().JWTID() + // We override the given request client token so that the rest of + // Vault sees the real value. This also ensures audit logs are + // consistent with the actual token that was issued. + if !thirdParty { + req.ClientToken = token + } else { + req.Data["token"] = token + } } } @@ -298,21 +308,3 @@ func (c *Core) ValidateWrappingToken(req *logical.Request) (bool, error) { return true, nil } - -// parseVaultTokenFromJWT returns a string iff the token was a JWT and we could -// extract the original token ID from inside -func (c *Core) parseVaultTokenFromJWT(token string) *string { - var result string - if strings.Count(token, ".") != 2 { - return nil - } - - wt, err := jws.ParseJWT([]byte(token)) - if err != nil || wt == nil { - return nil - } - - result, _ = wt.Claims().JWTID() - - return &result -}