mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	 ae774b93d3
			
		
	
	ae774b93d3
	
	
	
		
			
			* options for syslog * fix bug in default value for HMACAccessor * backend device cleanup * socket backend options update * options: prefix removed check, added default file mode * fix option setting for elision * fix test for prefix and whitespace
		
			
				
	
	
		
			537 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			537 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) HashiCorp, Inc.
 | |
| // SPDX-License-Identifier: BUSL-1.1
 | |
| 
 | |
| package audit
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/stretchr/testify/require"
 | |
| )
 | |
| 
 | |
| // TestOptions_WithFormat exercises WithFormat Option to ensure it performs as expected.
 | |
| func TestOptions_WithFormat(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value                string
 | |
| 		IsErrorExpected      bool
 | |
| 		ExpectedErrorMessage string
 | |
| 		ExpectedValue        format
 | |
| 	}{
 | |
| 		"empty": {
 | |
| 			Value:           "",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   format(""),
 | |
| 		},
 | |
| 		"whitespace": {
 | |
| 			Value:           "     ",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   format(""),
 | |
| 		},
 | |
| 		"invalid-test": {
 | |
| 			Value:                "test",
 | |
| 			IsErrorExpected:      true,
 | |
| 			ExpectedErrorMessage: "audit.(format).validate: 'test' is not a valid format: invalid parameter",
 | |
| 		},
 | |
| 		"valid-json": {
 | |
| 			Value:           "json",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   JSONFormat,
 | |
| 		},
 | |
| 		"valid-jsonx": {
 | |
| 			Value:           "jsonx",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   JSONxFormat,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithFormat(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			switch {
 | |
| 			case tc.IsErrorExpected:
 | |
| 				require.Error(t, err)
 | |
| 				require.EqualError(t, err, tc.ExpectedErrorMessage)
 | |
| 			default:
 | |
| 				require.NoError(t, err)
 | |
| 				require.Equal(t, tc.ExpectedValue, opts.withFormat)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithSubtype exercises WithSubtype Option to ensure it performs as expected.
 | |
| func TestOptions_WithSubtype(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value                string
 | |
| 		IsErrorExpected      bool
 | |
| 		ExpectedErrorMessage string
 | |
| 		ExpectedValue        subtype
 | |
| 	}{
 | |
| 		"empty": {
 | |
| 			Value:                "",
 | |
| 			IsErrorExpected:      true,
 | |
| 			ExpectedErrorMessage: "subtype cannot be empty",
 | |
| 		},
 | |
| 		"whitespace": {
 | |
| 			Value:                "     ",
 | |
| 			IsErrorExpected:      true,
 | |
| 			ExpectedErrorMessage: "subtype cannot be empty",
 | |
| 		},
 | |
| 		"valid": {
 | |
| 			Value:           "AuditResponse",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   ResponseType,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithSubtype(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			switch {
 | |
| 			case tc.IsErrorExpected:
 | |
| 				require.Error(t, err)
 | |
| 				require.EqualError(t, err, tc.ExpectedErrorMessage)
 | |
| 			default:
 | |
| 				require.NoError(t, err)
 | |
| 				require.Equal(t, tc.ExpectedValue, opts.withSubtype)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithNow exercises WithNow Option to ensure it performs as expected.
 | |
| func TestOptions_WithNow(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value                time.Time
 | |
| 		IsErrorExpected      bool
 | |
| 		ExpectedErrorMessage string
 | |
| 		ExpectedValue        time.Time
 | |
| 	}{
 | |
| 		"default-time": {
 | |
| 			Value:                time.Time{},
 | |
| 			IsErrorExpected:      true,
 | |
| 			ExpectedErrorMessage: "cannot specify 'now' to be the zero time instant",
 | |
| 		},
 | |
| 		"valid-time": {
 | |
| 			Value:           time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithNow(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			switch {
 | |
| 			case tc.IsErrorExpected:
 | |
| 				require.Error(t, err)
 | |
| 				require.EqualError(t, err, tc.ExpectedErrorMessage)
 | |
| 			default:
 | |
| 				require.NoError(t, err)
 | |
| 				require.Equal(t, tc.ExpectedValue, opts.withNow)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithID exercises WithID Option to ensure it performs as expected.
 | |
| func TestOptions_WithID(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value                string
 | |
| 		IsErrorExpected      bool
 | |
| 		ExpectedErrorMessage string
 | |
| 		ExpectedValue        string
 | |
| 	}{
 | |
| 		"empty": {
 | |
| 			Value:                "",
 | |
| 			IsErrorExpected:      true,
 | |
| 			ExpectedErrorMessage: "id cannot be empty",
 | |
| 		},
 | |
| 		"whitespace": {
 | |
| 			Value:                "     ",
 | |
| 			IsErrorExpected:      true,
 | |
| 			ExpectedErrorMessage: "id cannot be empty",
 | |
| 		},
 | |
| 		"valid": {
 | |
| 			Value:           "test",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   "test",
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithID(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			switch {
 | |
| 			case tc.IsErrorExpected:
 | |
| 				require.Error(t, err)
 | |
| 				require.EqualError(t, err, tc.ExpectedErrorMessage)
 | |
| 			default:
 | |
| 				require.NoError(t, err)
 | |
| 				require.Equal(t, tc.ExpectedValue, opts.withID)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithPrefix exercises WithPrefix Option to ensure it performs as expected.
 | |
| func TestOptions_WithPrefix(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value                string
 | |
| 		IsErrorExpected      bool
 | |
| 		ExpectedErrorMessage string
 | |
| 		ExpectedValue        string
 | |
| 	}{
 | |
| 		"empty": {
 | |
| 			Value:           "",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   "",
 | |
| 		},
 | |
| 		"whitespace": {
 | |
| 			Value:           "     ",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   "     ",
 | |
| 		},
 | |
| 		"valid": {
 | |
| 			Value:           "test",
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedValue:   "test",
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithPrefix(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			switch {
 | |
| 			case tc.IsErrorExpected:
 | |
| 				require.Error(t, err)
 | |
| 				require.EqualError(t, err, tc.ExpectedErrorMessage)
 | |
| 			default:
 | |
| 				require.NoError(t, err)
 | |
| 				require.Equal(t, tc.ExpectedValue, opts.withPrefix)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithRaw exercises WithRaw Option to ensure it performs as expected.
 | |
| func TestOptions_WithRaw(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value         bool
 | |
| 		ExpectedValue bool
 | |
| 	}{
 | |
| 		"true": {
 | |
| 			Value:         true,
 | |
| 			ExpectedValue: true,
 | |
| 		},
 | |
| 		"false": {
 | |
| 			Value:         false,
 | |
| 			ExpectedValue: false,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithRaw(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			require.NoError(t, err)
 | |
| 			require.Equal(t, tc.ExpectedValue, opts.withRaw)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithElision exercises WithElision Option to ensure it performs as expected.
 | |
| func TestOptions_WithElision(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value         bool
 | |
| 		ExpectedValue bool
 | |
| 	}{
 | |
| 		"true": {
 | |
| 			Value:         true,
 | |
| 			ExpectedValue: true,
 | |
| 		},
 | |
| 		"false": {
 | |
| 			Value:         false,
 | |
| 			ExpectedValue: false,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithElision(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			require.NoError(t, err)
 | |
| 			require.Equal(t, tc.ExpectedValue, opts.withElision)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithHMACAccessor exercises WithHMACAccessor Option to ensure it performs as expected.
 | |
| func TestOptions_WithHMACAccessor(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value         bool
 | |
| 		ExpectedValue bool
 | |
| 	}{
 | |
| 		"true": {
 | |
| 			Value:         true,
 | |
| 			ExpectedValue: true,
 | |
| 		},
 | |
| 		"false": {
 | |
| 			Value:         false,
 | |
| 			ExpectedValue: false,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithHMACAccessor(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			require.NoError(t, err)
 | |
| 			require.Equal(t, tc.ExpectedValue, opts.withHMACAccessor)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithOmitTime exercises WithOmitTime Option to ensure it performs as expected.
 | |
| func TestOptions_WithOmitTime(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value         bool
 | |
| 		ExpectedValue bool
 | |
| 	}{
 | |
| 		"true": {
 | |
| 			Value:         true,
 | |
| 			ExpectedValue: true,
 | |
| 		},
 | |
| 		"false": {
 | |
| 			Value:         false,
 | |
| 			ExpectedValue: false,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			applyOption := WithOmitTime(tc.Value)
 | |
| 			err := applyOption(opts)
 | |
| 			require.NoError(t, err)
 | |
| 			require.Equal(t, tc.ExpectedValue, opts.withOmitTime)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_WithHeaderFormatter exercises the WithHeaderFormatter Option to
 | |
| // ensure it applies the option as expected under various circumstances.
 | |
| func TestOptions_WithHeaderFormatter(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		Value                    HeaderFormatter
 | |
| 		ExpectedValue            HeaderFormatter
 | |
| 		ShouldLeaveUninitialized bool
 | |
| 	}{
 | |
| 		"nil": {
 | |
| 			Value:         nil,
 | |
| 			ExpectedValue: nil,
 | |
| 		},
 | |
| 		"unassigned-interface": {
 | |
| 			ShouldLeaveUninitialized: true,
 | |
| 		},
 | |
| 		"happy-path": {
 | |
| 			Value:         &testHeaderFormatter{},
 | |
| 			ExpectedValue: &testHeaderFormatter{},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts := &options{}
 | |
| 			var f HeaderFormatter
 | |
| 			if !tc.ShouldLeaveUninitialized {
 | |
| 				f = tc.Value
 | |
| 			}
 | |
| 			applyOption := WithHeaderFormatter(f)
 | |
| 			err := applyOption(opts)
 | |
| 			require.NoError(t, err)
 | |
| 			require.Equal(t, tc.ExpectedValue, opts.withHeaderFormatter)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TestOptions_Default exercises getDefaultOptions to assert the default values.
 | |
| func TestOptions_Default(t *testing.T) {
 | |
| 	opts := getDefaultOptions()
 | |
| 	require.NotNil(t, opts)
 | |
| 	require.True(t, time.Now().After(opts.withNow))
 | |
| 	require.False(t, opts.withNow.IsZero())
 | |
| }
 | |
| 
 | |
| // TestOptions_Opts exercises GetOpts with various Option values.
 | |
| func TestOptions_Opts(t *testing.T) {
 | |
| 	tests := map[string]struct {
 | |
| 		opts                 []Option
 | |
| 		IsErrorExpected      bool
 | |
| 		ExpectedErrorMessage string
 | |
| 		ExpectedID           string
 | |
| 		ExpectedSubtype      subtype
 | |
| 		ExpectedFormat       format
 | |
| 		IsNowExpected        bool
 | |
| 		ExpectedNow          time.Time
 | |
| 	}{
 | |
| 		"nil-options": {
 | |
| 			opts:            nil,
 | |
| 			IsErrorExpected: false,
 | |
| 			IsNowExpected:   true,
 | |
| 			ExpectedFormat:  JSONFormat,
 | |
| 		},
 | |
| 		"empty-options": {
 | |
| 			opts:            []Option{},
 | |
| 			IsErrorExpected: false,
 | |
| 			IsNowExpected:   true,
 | |
| 			ExpectedFormat:  JSONFormat,
 | |
| 		},
 | |
| 		"with-multiple-valid-id": {
 | |
| 			opts: []Option{
 | |
| 				WithID("qwerty"),
 | |
| 				WithID("juan"),
 | |
| 			},
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedID:      "juan",
 | |
| 			IsNowExpected:   true,
 | |
| 			ExpectedFormat:  JSONFormat,
 | |
| 		},
 | |
| 		"with-multiple-valid-subtype": {
 | |
| 			opts: []Option{
 | |
| 				WithSubtype("AuditRequest"),
 | |
| 				WithSubtype("AuditResponse"),
 | |
| 			},
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedSubtype: ResponseType,
 | |
| 			IsNowExpected:   true,
 | |
| 			ExpectedFormat:  JSONFormat,
 | |
| 		},
 | |
| 		"with-multiple-valid-format": {
 | |
| 			opts: []Option{
 | |
| 				WithFormat("json"),
 | |
| 				WithFormat("jsonx"),
 | |
| 			},
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedFormat:  JSONxFormat,
 | |
| 			IsNowExpected:   true,
 | |
| 		},
 | |
| 		"with-multiple-valid-now": {
 | |
| 			opts: []Option{
 | |
| 				WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
 | |
| 				WithNow(time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local)),
 | |
| 			},
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedNow:     time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local),
 | |
| 			IsNowExpected:   false,
 | |
| 			ExpectedFormat:  JSONFormat,
 | |
| 		},
 | |
| 		"with-multiple-valid-then-invalid-now": {
 | |
| 			opts: []Option{
 | |
| 				WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
 | |
| 				WithNow(time.Time{}),
 | |
| 			},
 | |
| 			IsErrorExpected:      true,
 | |
| 			ExpectedErrorMessage: "cannot specify 'now' to be the zero time instant",
 | |
| 			ExpectedFormat:       JSONFormat,
 | |
| 		},
 | |
| 		"with-multiple-valid-options": {
 | |
| 			opts: []Option{
 | |
| 				WithID("qwerty"),
 | |
| 				WithSubtype("AuditRequest"),
 | |
| 				WithFormat("json"),
 | |
| 				WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
 | |
| 			},
 | |
| 			IsErrorExpected: false,
 | |
| 			ExpectedID:      "qwerty",
 | |
| 			ExpectedSubtype: RequestType,
 | |
| 			ExpectedFormat:  JSONFormat,
 | |
| 			ExpectedNow:     time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for name, tc := range tests {
 | |
| 		name := name
 | |
| 		tc := tc
 | |
| 		t.Run(name, func(t *testing.T) {
 | |
| 			t.Parallel()
 | |
| 			opts, err := getOpts(tc.opts...)
 | |
| 
 | |
| 			switch {
 | |
| 			case tc.IsErrorExpected:
 | |
| 				require.Error(t, err)
 | |
| 				require.EqualError(t, err, tc.ExpectedErrorMessage)
 | |
| 			default:
 | |
| 				require.NotNil(t, opts)
 | |
| 				require.NoError(t, err)
 | |
| 				require.Equal(t, tc.ExpectedID, opts.withID)
 | |
| 				require.Equal(t, tc.ExpectedSubtype, opts.withSubtype)
 | |
| 				require.Equal(t, tc.ExpectedFormat, opts.withFormat)
 | |
| 				switch {
 | |
| 				case tc.IsNowExpected:
 | |
| 					require.True(t, time.Now().After(opts.withNow))
 | |
| 					require.False(t, opts.withNow.IsZero())
 | |
| 				default:
 | |
| 					require.Equal(t, tc.ExpectedNow, opts.withNow)
 | |
| 				}
 | |
| 
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // testHeaderFormatter is a stub to prevent the need to import the vault package
 | |
| // to bring in vault.AuditedHeadersConfig for testing.
 | |
| type testHeaderFormatter struct{}
 | |
| 
 | |
| // ApplyConfig satisfied the HeaderFormatter interface for testing.
 | |
| func (f *testHeaderFormatter) ApplyConfig(ctx context.Context, headers map[string][]string, salter Salter) (result map[string][]string, retErr error) {
 | |
| 	return nil, nil
 | |
| }
 |