// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package audit import ( "bytes" "context" "errors" "fmt" "strings" "testing" "time" "github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/sdk/helper/salt" "github.com/hashicorp/vault/sdk/logical" ) func TestFormatJSONx_formatRequest(t *testing.T) { salter, err := salt.NewSalt(context.Background(), nil, nil) if err != nil { t.Fatal(err) } saltFunc := func(context.Context) (*salt.Salt, error) { return salter, nil } fooSalted := 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 Err error Prefix string Result string ExpectedStr string }{ "auth, request": { &logical.Auth{ ClientToken: "foo", Accessor: "bar", DisplayName: "testtoken", EntityID: "foobarentity", NoDefaultPolicy: true, Policies: []string{"root"}, TokenType: logical.TokenTypeService, LeaseOptions: logical.LeaseOptions{ TTL: time.Hour * 4, IssueTime: issueTime, }, }, &logical.Request{ ID: "request", ClientToken: "foo", ClientTokenAccessor: "bar", Operation: logical.UpdateOperation, Path: "/foo", Connection: &logical.Connection{ RemoteAddr: "127.0.0.1", }, WrapInfo: &logical.RequestWrapInfo{ TTL: 60 * time.Second, }, Headers: map[string][]string{ "foo": {"bar"}, }, PolicyOverride: true, }, errors.New("this is an error"), "", "", fmt.Sprintf(`bar%stesttokenfoobarentitytrueroot2020-05-28T13:40:18-05:0014400servicethis is an error%sbarbarrequestrootupdate/footrue127.0.0.160request`, fooSalted, fooSalted), }, "auth, request with prefix": { &logical.Auth{ ClientToken: "foo", Accessor: "bar", DisplayName: "testtoken", NoDefaultPolicy: true, EntityID: "foobarentity", Policies: []string{"root"}, TokenType: logical.TokenTypeService, LeaseOptions: logical.LeaseOptions{ TTL: time.Hour * 4, IssueTime: issueTime, }, }, &logical.Request{ ID: "request", ClientToken: "foo", ClientTokenAccessor: "bar", Operation: logical.UpdateOperation, Path: "/foo", Connection: &logical.Connection{ RemoteAddr: "127.0.0.1", }, WrapInfo: &logical.RequestWrapInfo{ TTL: 60 * time.Second, }, Headers: map[string][]string{ "foo": {"bar"}, }, PolicyOverride: true, }, errors.New("this is an error"), "", "@cee: ", fmt.Sprintf(`bar%stesttokenfoobarentitytrueroot2020-05-28T13:40:18-05:0014400servicethis is an error%sbarbarrequestrootupdate/footrue127.0.0.160request`, fooSalted, fooSalted), }, } for name, tc := range cases { var buf bytes.Buffer formatter := AuditFormatter{ AuditFormatWriter: &JSONxFormatWriter{ Prefix: tc.Prefix, SaltFunc: saltFunc, }, } config := FormatterConfig{ OmitTime: true, HMACAccessor: false, } in := &logical.LogInput{ Auth: tc.Auth, Request: tc.Req, OuterErr: tc.Err, } if err := formatter.FormatRequest(namespace.RootContext(nil), &buf, config, in); err != nil { t.Fatalf("bad: %s\nerr: %s", name, err) } if !strings.HasPrefix(buf.String(), tc.Prefix) { t.Fatalf("no prefix: %s \n log: %s\nprefix: %s", name, tc.Result, tc.Prefix) } if !strings.HasSuffix(strings.TrimSpace(buf.String()), string(tc.ExpectedStr)) { t.Fatalf( "bad: %s\nResult:\n\n%q\n\nExpected:\n\n%q", name, strings.TrimSpace(buf.String()), string(tc.ExpectedStr)) } } }