From 6b8a00d24a08fc21889313f266a837e467041f04 Mon Sep 17 00:00:00 2001 From: "Scott G. Miller" Date: Wed, 27 May 2020 15:03:11 -0500 Subject: [PATCH 1/4] Populate a token_ttl and token_issue_time field on the Auth struct of audit log entries, and in the Auth portion of a response for login methods --- audit/format.go | 22 ++++++++++++++++++++-- vault/request_handling.go | 4 ++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/audit/format.go b/audit/format.go index 329e7ba7125a..5f4382352ad2 100644 --- a/audit/format.go +++ b/audit/format.go @@ -4,6 +4,8 @@ import ( "context" "crypto/tls" "fmt" + "github.com/hashicorp/vault/sdk/helper/salt" + "github.com/hashicorp/vault/sdk/logical" "io" "strings" "time" @@ -12,8 +14,6 @@ import ( "github.com/hashicorp/errwrap" "github.com/hashicorp/vault/helper/namespace" - "github.com/hashicorp/vault/sdk/helper/salt" - "github.com/hashicorp/vault/sdk/logical" ) type AuditFormatWriter interface { @@ -106,6 +106,7 @@ func (f *AuditFormatter) FormatRequest(ctx context.Context, w io.Writer, config EntityID: auth.EntityID, RemainingUses: req.ClientTokenRemainingUses, TokenType: auth.TokenType.String(), + TokenTTL: int64(auth.TTL.Seconds()), }, Request: &AuditRequest{ @@ -127,6 +128,11 @@ func (f *AuditFormatter) FormatRequest(ctx context.Context, w io.Writer, config }, } + var zt time.Time + if auth.IssueTime != zt { + reqEntry.Auth.TokenIssueTime = auth.IssueTime.Format(time.RFC3339) + } + if req.WrapInfo != nil { reqEntry.Request.WrapTTL = int(req.WrapInfo.TTL / time.Second) } @@ -212,6 +218,11 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config NumUses: resp.Auth.NumUses, EntityID: resp.Auth.EntityID, TokenType: resp.Auth.TokenType.String(), + TokenTTL: int64(resp.Auth.TTL.Seconds()), + } + var zt time.Time + if resp.Auth.IssueTime != zt { + respAuth.TokenIssueTime = resp.Auth.IssueTime.Format(time.RFC3339) } } @@ -258,6 +269,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config RemainingUses: req.ClientTokenRemainingUses, EntityID: auth.EntityID, TokenType: auth.TokenType.String(), + TokenTTL: int64(auth.TTL.Seconds()), }, Request: &AuditRequest{ @@ -289,6 +301,10 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config }, } + var zt time.Time + if auth.IssueTime != zt { + respEntry.Auth.TokenIssueTime = auth.IssueTime.Format(time.RFC3339) + } if req.WrapInfo != nil { respEntry.Request.WrapTTL = int(req.WrapInfo.TTL / time.Second) } @@ -359,6 +375,8 @@ type AuditAuth struct { RemainingUses int `json:"remaining_uses,omitempty"` EntityID string `json:"entity_id,omitempty"` TokenType string `json:"token_type,omitempty"` + TokenTTL int64 `json:"token_ttl,omitempty"` + TokenIssueTime string `json:"token_issue_time,omitempty"` } type AuditSecret struct { diff --git a/vault/request_handling.go b/vault/request_handling.go index eeeda8ae6d55..f0d82c195c40 100644 --- a/vault/request_handling.go +++ b/vault/request_handling.go @@ -343,6 +343,10 @@ func (c *Core) checkToken(ctx context.Context, req *logical.Request, unauth bool // Store the entity ID in the request object req.EntityID = te.EntityID auth.TokenType = te.Type + auth.TTL = te.TTL + if te.CreationTime > 0 { + auth.IssueTime = time.Unix(te.CreationTime, 0) + } } // Check the standard non-root ACLs. Return the token entry if it's not From 844b6d93f5b998024bc9f336f1190e5b858fc1ce Mon Sep 17 00:00:00 2001 From: "Scott G. Miller" Date: Thu, 28 May 2020 12:53:20 -0500 Subject: [PATCH 2/4] Revert go fmt, better zero checking --- audit/format.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/audit/format.go b/audit/format.go index 5f4382352ad2..a25aa8bcde34 100644 --- a/audit/format.go +++ b/audit/format.go @@ -4,8 +4,6 @@ import ( "context" "crypto/tls" "fmt" - "github.com/hashicorp/vault/sdk/helper/salt" - "github.com/hashicorp/vault/sdk/logical" "io" "strings" "time" @@ -14,6 +12,8 @@ import ( "github.com/hashicorp/errwrap" "github.com/hashicorp/vault/helper/namespace" + "github.com/hashicorp/vault/sdk/helper/salt" + "github.com/hashicorp/vault/sdk/logical" ) type AuditFormatWriter interface { @@ -128,8 +128,7 @@ func (f *AuditFormatter) FormatRequest(ctx context.Context, w io.Writer, config }, } - var zt time.Time - if auth.IssueTime != zt { + if !auth.IssueTime.IsZero() { reqEntry.Auth.TokenIssueTime = auth.IssueTime.Format(time.RFC3339) } @@ -220,8 +219,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config TokenType: resp.Auth.TokenType.String(), TokenTTL: int64(resp.Auth.TTL.Seconds()), } - var zt time.Time - if resp.Auth.IssueTime != zt { + if !resp.Auth.IssueTime.IsZero() { respAuth.TokenIssueTime = resp.Auth.IssueTime.Format(time.RFC3339) } } @@ -301,8 +299,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config }, } - var zt time.Time - if auth.IssueTime != zt { + if !auth.IssueTime.IsZero() { respEntry.Auth.TokenIssueTime = auth.IssueTime.Format(time.RFC3339) } if req.WrapInfo != nil { From fa2111907c578ad2e4a6a84b4751a8bb1a1f71c8 Mon Sep 17 00:00:00 2001 From: "Scott G. Miller" Date: Thu, 28 May 2020 13:47:59 -0500 Subject: [PATCH 3/4] Update unit tests --- audit/format_json_test.go | 11 ++++++++++- audit/format_jsonx_test.go | 13 +++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/audit/format_json_test.go b/audit/format_json_test.go index a1e32a11035a..bfffe501b8f2 100644 --- a/audit/format_json_test.go +++ b/audit/format_json_test.go @@ -29,6 +29,7 @@ func TestFormatJSON_formatRequest(t *testing.T) { expectedResultStr := fmt.Sprintf(testFormatJSONReqBasicStrFmt, salter.GetIdentifiedHMAC("foo")) + issueTime, _ := time.Parse(time.RFC3339, "2020-05-28T13:40:18-05:00") cases := map[string]struct { Auth *logical.Auth Req *logical.Request @@ -45,6 +46,10 @@ func TestFormatJSON_formatRequest(t *testing.T) { NoDefaultPolicy: true, Policies: []string{"root"}, TokenType: logical.TokenTypeService, + LeaseOptions: logical.LeaseOptions{ + TTL: time.Hour * 4, + IssueTime: issueTime, + }, }, &logical.Request{ Operation: logical.UpdateOperation, @@ -72,6 +77,10 @@ func TestFormatJSON_formatRequest(t *testing.T) { NoDefaultPolicy: true, Policies: []string{"root"}, TokenType: logical.TokenTypeService, + LeaseOptions: logical.LeaseOptions{ + TTL: time.Hour * 4, + IssueTime: issueTime, + }, }, &logical.Request{ Operation: logical.UpdateOperation, @@ -143,5 +152,5 @@ func TestFormatJSON_formatRequest(t *testing.T) { } } -const testFormatJSONReqBasicStrFmt = `{"time":"2015-08-05T13:45:46Z","type":"request","auth":{"client_token":"%s","accessor":"bar","display_name":"testtoken","policies":["root"],"no_default_policy":true,"metadata":null,"entity_id":"foobarentity","token_type":"service"},"request":{"operation":"update","path":"/foo","data":null,"wrap_ttl":60,"remote_address":"127.0.0.1","headers":{"foo":["bar"]}},"error":"this is an error"} +const testFormatJSONReqBasicStrFmt = `{"time":"2015-08-05T13:45:46Z","type":"request","auth":{"client_token":"%s","accessor":"bar","display_name":"testtoken","policies":["root"],"no_default_policy":true,"metadata":null,"entity_id":"foobarentity","token_type":"service", "token_ttl": 14400, "token_issue_time": "2020-05-28T13:40:18-05:00"},"request":{"operation":"update","path":"/foo","data":null,"wrap_ttl":60,"remote_address":"127.0.0.1","headers":{"foo":["bar"]}},"error":"this is an error"} ` diff --git a/audit/format_jsonx_test.go b/audit/format_jsonx_test.go index 6c46d3d9db38..dae1f9fcdfde 100644 --- a/audit/format_jsonx_test.go +++ b/audit/format_jsonx_test.go @@ -26,6 +26,7 @@ func TestFormatJSONx_formatRequest(t *testing.T) { } fooSalted := salter.GetIdentifiedHMAC("foo") + issueTime, _ := time.Parse(time.RFC3339, "2020-05-28T13:40:18-05:00") cases := map[string]struct { Auth *logical.Auth @@ -44,6 +45,10 @@ func TestFormatJSONx_formatRequest(t *testing.T) { NoDefaultPolicy: true, Policies: []string{"root"}, TokenType: logical.TokenTypeService, + LeaseOptions: logical.LeaseOptions{ + TTL: time.Hour * 4, + IssueTime: issueTime, + }, }, &logical.Request{ ID: "request", @@ -65,7 +70,7 @@ func TestFormatJSONx_formatRequest(t *testing.T) { errors.New("this is an error"), "", "", - fmt.Sprintf(`bar%stesttokenfoobarentitytruerootservicethis is an error%sbarbarrequestrootupdate/footrue127.0.0.160request`, + fmt.Sprintf(`bar%stesttokenfoobarentitytrueroot2020-05-28T13:40:18-05:0014400servicethis is an error%sbarbarrequestrootupdate/footrue127.0.0.160request`, fooSalted, fooSalted), }, "auth, request with prefix": { @@ -77,6 +82,10 @@ func TestFormatJSONx_formatRequest(t *testing.T) { EntityID: "foobarentity", Policies: []string{"root"}, TokenType: logical.TokenTypeService, + LeaseOptions: logical.LeaseOptions{ + TTL: time.Hour * 4, + IssueTime: issueTime, + }, }, &logical.Request{ ID: "request", @@ -98,7 +107,7 @@ func TestFormatJSONx_formatRequest(t *testing.T) { errors.New("this is an error"), "", "@cee: ", - fmt.Sprintf(`bar%stesttokenfoobarentitytruerootservicethis is an error%sbarbarrequestrootupdate/footrue127.0.0.160request`, + fmt.Sprintf(`bar%stesttokenfoobarentitytrueroot2020-05-28T13:40:18-05:0014400servicethis is an error%sbarbarrequestrootupdate/footrue127.0.0.160request`, fooSalted, fooSalted), }, } From a11dd3e41fbdc62e24ecce60483d23ffaf53f8fd Mon Sep 17 00:00:00 2001 From: "Scott G. Miller" Date: Thu, 28 May 2020 13:49:18 -0500 Subject: [PATCH 4/4] changelog++ --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85748702d6a2..f285ffff17fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGES: * token: Token renewals will now return token policies within the `token_policies` , identity policies within `identity_policies`, and the full policy set within `policies`. [[GH-8535](https://github.com/hashicorp/vault/pull/8535)] * cubbyhole: Reject reads and writes to an empty ("") path. [[GH-8971](https://github.com/hashicorp/vault/pull/8971)] * core: Remove the addition of newlines to parsed configuration when using integer/boolean values [[GH-8928](https://github.com/hashicorp/vault/pull/8928)] +* audit: Token TTL and issue time are now provided in the auth portion of audit logs. [[GH-9091](https://github.com/hashicorp/vault/pull/9091)] IMPROVEMENTS: