github.com/Axway/agent-sdk@v1.1.101/pkg/traceability/redaction/redaction_test.go (about)

     1  package redaction
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  var requestHeaders = map[string]string{
    13  	"request":                 "value",
    14  	"x-amplify-something":     "random",
    15  	"x-amplify-somethingelse": "else",
    16  }
    17  
    18  var responseHeaders = map[string]string{
    19  	"response":   "value",
    20  	"x-response": "random",
    21  	"x-value":    "test",
    22  }
    23  
    24  var queryParams = map[string][]string{
    25  	"param1": {"date"},
    26  	"param2": {"day", "time"},
    27  }
    28  
    29  var jmsProperties = map[string]string{
    30  	"jmsMessageID":   "messageid",
    31  	"jmsDestination": "queue://test-queue",
    32  	"jmsReplyTo":     "queue://reply-queue",
    33  }
    34  
    35  func TestDefaultRedaction(t *testing.T) {
    36  	redactionCfg := DefaultConfig()
    37  
    38  	SetupGlobalRedaction(redactionCfg)
    39  
    40  	// URI redaction
    41  	redactedPath, err := URIRedaction("https://apicentral.axway.com/test/the/path/redaction")
    42  	assert.Nil(t, err)
    43  	assert.NotNil(t, redactedPath)
    44  	assert.Equal(t, "/{*}/{*}/{*}/{*}", redactedPath)
    45  
    46  	// Only send path to URI redaction
    47  	redactedPath, err = URIRedaction("/test/the/path/redaction")
    48  	assert.Nil(t, err)
    49  	assert.NotNil(t, redactedPath)
    50  	assert.Equal(t, "/{*}/{*}/{*}/{*}", redactedPath)
    51  
    52  	// Query args redaction
    53  	queryArgString := ""
    54  	for key, val := range queryParams {
    55  		if queryArgString != "" {
    56  			queryArgString += "&"
    57  		}
    58  		queryArgString += fmt.Sprintf("%s=%s", key, strings.Join(val, ","))
    59  	}
    60  	redactedQueryParamsString, err := QueryArgsRedactionString(queryArgString)
    61  	assert.Nil(t, err)
    62  	assert.Empty(t, redactedQueryParamsString)
    63  	var redactedQueryParams map[string][]string
    64  	json.Unmarshal([]byte(redactedQueryParamsString), &redactedQueryParams)
    65  	assert.Len(t, redactedQueryParams, 0)
    66  
    67  	// Request Header redaction
    68  	redactedRequestHeaders, err := RequestHeadersRedaction(requestHeaders)
    69  	assert.Nil(t, err)
    70  	assert.NotNil(t, redactedRequestHeaders)
    71  	assert.Len(t, redactedRequestHeaders, 0)
    72  
    73  	// Response Header redaction
    74  	redactedResponseHeaders, err := ResponseHeadersRedaction(responseHeaders)
    75  	assert.Nil(t, err)
    76  	assert.NotNil(t, redactedResponseHeaders)
    77  	assert.Len(t, redactedResponseHeaders, 0)
    78  
    79  	// JMS Property redaction
    80  	redactedJMSProperties, err := JMSPropertiesRedaction(jmsProperties)
    81  	assert.Nil(t, err)
    82  	assert.NotNil(t, redactedJMSProperties)
    83  	assert.Len(t, redactedJMSProperties, 0)
    84  }
    85  
    86  func TestBadSetupRedaction(t *testing.T) {
    87  	testCases := []struct {
    88  		name   string
    89  		config Config
    90  	}{
    91  		{
    92  			name: "PathRegex",
    93  			config: Config{
    94  				Path: Path{
    95  					Allowed: []Show{
    96  						{
    97  							KeyMatch: "*test",
    98  						},
    99  					},
   100  				},
   101  			},
   102  		},
   103  		{
   104  			name: "QueryArgsAllowRegex",
   105  			config: Config{
   106  				Args: Filter{
   107  					Allowed: []Show{
   108  						{
   109  							KeyMatch: "*test",
   110  						},
   111  					},
   112  				},
   113  			},
   114  		},
   115  		{
   116  			name: "QueryArgsSanitizeRegex",
   117  			config: Config{
   118  				Args: Filter{
   119  					Sanitize: []Sanitize{
   120  						{
   121  							KeyMatch:   "test",
   122  							ValueMatch: "*test",
   123  						},
   124  					},
   125  				},
   126  			},
   127  		},
   128  		{
   129  			name: "ResponseHeadersSanitizeRegex",
   130  			config: Config{
   131  				ResponseHeaders: Filter{
   132  					Sanitize: []Sanitize{
   133  						{
   134  							KeyMatch:   "*test",
   135  							ValueMatch: "*test",
   136  						},
   137  					},
   138  				},
   139  			},
   140  		},
   141  		{
   142  			name: "ResponseHeadersRegex",
   143  			config: Config{
   144  				ResponseHeaders: Filter{
   145  					Allowed: []Show{
   146  						{
   147  							KeyMatch: "*test",
   148  						},
   149  					},
   150  				},
   151  			},
   152  		},
   153  		{
   154  			name: "RequesteHeadersSanitizeRegex",
   155  			config: Config{
   156  				RequestHeaders: Filter{
   157  					Sanitize: []Sanitize{
   158  						{
   159  							KeyMatch:   "*test",
   160  							ValueMatch: "*test",
   161  						},
   162  					},
   163  				},
   164  			},
   165  		},
   166  		{
   167  			name: "RequestHeadersRegex",
   168  			config: Config{
   169  				RequestHeaders: Filter{
   170  					Allowed: []Show{
   171  						{
   172  							KeyMatch: "*test",
   173  						},
   174  					},
   175  				},
   176  			},
   177  		},
   178  		{
   179  			name: "JMSPropertiesSanitizeRegex",
   180  			config: Config{
   181  				RequestHeaders: Filter{
   182  					Sanitize: []Sanitize{
   183  						{
   184  							KeyMatch:   "*test",
   185  							ValueMatch: "*test",
   186  						},
   187  					},
   188  				},
   189  			},
   190  		},
   191  		{
   192  			name: "JMSPropertiesRegex",
   193  			config: Config{
   194  				RequestHeaders: Filter{
   195  					Allowed: []Show{
   196  						{
   197  							KeyMatch: "*test",
   198  						},
   199  					},
   200  				},
   201  			},
   202  		},
   203  	}
   204  
   205  	for _, test := range testCases {
   206  		t.Run(test.name, func(t *testing.T) {
   207  			err := SetupGlobalRedaction(test.config)
   208  			assert.NotNil(t, err)
   209  		})
   210  	}
   211  
   212  }
   213  
   214  func TestURIRedaction(t *testing.T) {
   215  	testCases := []struct {
   216  		name              string
   217  		pathConfig        []Show
   218  		input             string
   219  		output            string
   220  		maskingCharacters string
   221  	}{
   222  		{
   223  			name: "SingleWord",
   224  			pathConfig: []Show{
   225  				{
   226  					KeyMatch: "test",
   227  				},
   228  			},
   229  			input:  "https://apicentral.axway.com/test/the/path/redaction",
   230  			output: "/test/{*}/{*}/{*}",
   231  		},
   232  		{
   233  			name: "TwoWords",
   234  			pathConfig: []Show{
   235  				{
   236  					KeyMatch: "test",
   237  				},
   238  				{
   239  					KeyMatch: "redaction",
   240  				},
   241  			},
   242  			maskingCharacters: "{#}",
   243  			input:             "https://apicentral.axway.com/test/the/path/redaction",
   244  			output:            "/test/{#}/{#}/redaction",
   245  		},
   246  		{
   247  			name: "Regex - invalid masking character",
   248  			pathConfig: []Show{
   249  				{
   250  					KeyMatch: ".*th.*",
   251  				},
   252  			},
   253  			maskingCharacters: "{$}", // invalid masking character
   254  			input:             "https://apicentral.axway.com/test/the/path/redaction",
   255  			output:            "/{*}/the/path/{*}",
   256  		},
   257  		{
   258  			name: "Regex - overriding masking character",
   259  			pathConfig: []Show{
   260  				{
   261  					KeyMatch: ".*th.*",
   262  				},
   263  			},
   264  			maskingCharacters: "{^}", // invalid masking character
   265  			input:             "https://apicentral.axway.com/test/the/path/redaction",
   266  			output:            "/{^}/the/path/{^}",
   267  		},
   268  	}
   269  
   270  	for _, test := range testCases {
   271  		t.Run(test.name, func(t *testing.T) {
   272  			defConfig := DefaultConfig()
   273  			defConfig.Path.Allowed = test.pathConfig // update to the test config
   274  			if test.maskingCharacters != "" {
   275  				defConfig.MaskingCharacters = test.maskingCharacters
   276  			}
   277  
   278  			err := SetupGlobalRedaction(defConfig)
   279  			assert.Nil(t, err)
   280  
   281  			// URI redaction
   282  			redactedPath, err := URIRedaction(test.input)
   283  			assert.Nil(t, err)
   284  			assert.NotNil(t, redactedPath)
   285  			assert.Equal(t, test.output, redactedPath)
   286  		})
   287  	}
   288  }
   289  
   290  func TestQueryParamsRedaction(t *testing.T) {
   291  	testCases := []struct {
   292  		name     string
   293  		qpConfig Filter
   294  		input    map[string][]string
   295  		output   map[string][]string
   296  	}{
   297  		{
   298  			name: "SingleParam",
   299  			qpConfig: Filter{
   300  				Allowed: []Show{
   301  					{
   302  						KeyMatch: "param1",
   303  					},
   304  				},
   305  			},
   306  			input: queryParams,
   307  			output: map[string][]string{
   308  				"param1": {"date"},
   309  			},
   310  		},
   311  		{
   312  			name: "TwoParas",
   313  			qpConfig: Filter{
   314  				Allowed: []Show{
   315  					{
   316  						KeyMatch: "param1",
   317  					},
   318  					{
   319  						KeyMatch: "param2",
   320  					},
   321  				},
   322  			},
   323  			input: queryParams,
   324  			output: map[string][]string{
   325  				"param1": {"date"},
   326  				"param2": {"day", "time"},
   327  			},
   328  		},
   329  		{
   330  			name: "AllowRegex",
   331  			qpConfig: Filter{
   332  				Allowed: []Show{
   333  					{
   334  						KeyMatch: "param\\d",
   335  					},
   336  				},
   337  			},
   338  			input: queryParams,
   339  			output: map[string][]string{
   340  				"param1": {"date"},
   341  				"param2": {"day", "time"},
   342  			},
   343  		},
   344  		{
   345  			name: "Sanitize1",
   346  			qpConfig: Filter{
   347  				Allowed: []Show{
   348  					{
   349  						KeyMatch: "param1",
   350  					},
   351  					{
   352  						KeyMatch: "param2",
   353  					},
   354  				},
   355  				Sanitize: []Sanitize{
   356  					{
   357  						KeyMatch:   "param2",
   358  						ValueMatch: "time",
   359  					},
   360  				},
   361  			},
   362  			input: queryParams,
   363  			output: map[string][]string{
   364  				"param1": {"date"},
   365  				"param2": {"day", "{*}"},
   366  			},
   367  		},
   368  		{
   369  			name: "SanitizeButNotAllowed",
   370  			qpConfig: Filter{
   371  				Allowed: []Show{
   372  					{
   373  						KeyMatch: "param1",
   374  					},
   375  				},
   376  				Sanitize: []Sanitize{
   377  					{
   378  						KeyMatch:   "param2",
   379  						ValueMatch: "time",
   380  					},
   381  				},
   382  			},
   383  			input: queryParams,
   384  			output: map[string][]string{
   385  				"param1": {"date"},
   386  			},
   387  		},
   388  	}
   389  
   390  	for _, test := range testCases {
   391  		t.Run(test.name, func(t *testing.T) {
   392  
   393  			defConfig := DefaultConfig()
   394  			defConfig.Args = test.qpConfig // update to the test config
   395  
   396  			err := SetupGlobalRedaction(defConfig)
   397  			assert.Nil(t, err)
   398  
   399  			// QueryParams redaction
   400  			redactedQueryParams, err := QueryArgsRedaction(queryParams)
   401  			assert.Nil(t, err)
   402  			assert.NotNil(t, redactedQueryParams)
   403  			assert.Equal(t, test.output, redactedQueryParams)
   404  		})
   405  	}
   406  }
   407  
   408  func TestHeadersRedaction(t *testing.T) {
   409  	testCases := []struct {
   410  		name           string
   411  		responseConfig Filter
   412  		requestConfig  Filter
   413  		inputResponse  map[string]string
   414  		inputRequest   map[string]string
   415  		outputResponse map[string]string
   416  		outputRequest  map[string]string
   417  	}{
   418  		{
   419  			name: "SingleParam",
   420  			responseConfig: Filter{
   421  				Allowed: []Show{
   422  					{
   423  						KeyMatch: "x-value",
   424  					},
   425  				},
   426  			},
   427  			requestConfig: Filter{
   428  				Allowed: []Show{
   429  					{
   430  						KeyMatch: "request",
   431  					},
   432  				},
   433  			},
   434  			inputResponse: responseHeaders,
   435  			inputRequest:  requestHeaders,
   436  			outputResponse: map[string]string{
   437  				"x-value": "test",
   438  			},
   439  			outputRequest: map[string]string{
   440  				"request": "value",
   441  			},
   442  		},
   443  		{
   444  			name: "TwoParams",
   445  			responseConfig: Filter{
   446  				Allowed: []Show{
   447  					{
   448  						KeyMatch: "x-value",
   449  					},
   450  					{
   451  						KeyMatch: "x-response",
   452  					},
   453  				},
   454  			},
   455  			requestConfig: Filter{
   456  				Allowed: []Show{
   457  					{
   458  						KeyMatch: "request",
   459  					},
   460  					{
   461  						KeyMatch: "x-amplify-somethingelse",
   462  					},
   463  				},
   464  			},
   465  			inputResponse: responseHeaders,
   466  			inputRequest:  requestHeaders,
   467  			outputResponse: map[string]string{
   468  				"x-value":    "test",
   469  				"x-response": "random",
   470  			},
   471  			outputRequest: map[string]string{
   472  				"request":                 "value",
   473  				"x-amplify-somethingelse": "else",
   474  			},
   475  		},
   476  		{
   477  			name: "Regex",
   478  			responseConfig: Filter{
   479  				Allowed: []Show{
   480  					{
   481  						KeyMatch: "^.*response",
   482  					},
   483  				},
   484  			},
   485  			requestConfig: Filter{
   486  				Allowed: []Show{
   487  					{
   488  						KeyMatch: "^x-amplify.*$",
   489  					},
   490  				},
   491  			},
   492  			inputResponse: responseHeaders,
   493  			inputRequest:  requestHeaders,
   494  			outputResponse: map[string]string{
   495  				"response":   "value",
   496  				"x-response": "random",
   497  			},
   498  			outputRequest: map[string]string{
   499  				"x-amplify-something":     "random",
   500  				"x-amplify-somethingelse": "else",
   501  			},
   502  		},
   503  		{
   504  			name: "Sanitize",
   505  			responseConfig: Filter{
   506  				Allowed: []Show{
   507  					{
   508  						KeyMatch: "^x-.*",
   509  					},
   510  				},
   511  				Sanitize: []Sanitize{
   512  					{
   513  						KeyMatch:   "^x-value.*$",
   514  						ValueMatch: "^tes",
   515  					},
   516  				},
   517  			},
   518  			requestConfig: Filter{
   519  				Allowed: []Show{
   520  					{
   521  						KeyMatch: "^x-amplify.*$",
   522  					},
   523  				},
   524  				Sanitize: []Sanitize{
   525  					{
   526  						KeyMatch:   "^x-amplify.*$",
   527  						ValueMatch: "^ran",
   528  					},
   529  				},
   530  			},
   531  			inputResponse: responseHeaders,
   532  			inputRequest:  requestHeaders,
   533  			outputResponse: map[string]string{
   534  				"x-response": "random",
   535  				"x-value":    "{*}t",
   536  			},
   537  			outputRequest: map[string]string{
   538  				"x-amplify-something":     "{*}dom",
   539  				"x-amplify-somethingelse": "else",
   540  			},
   541  		},
   542  		{
   543  			name: "SanitizeNoShow",
   544  			responseConfig: Filter{
   545  				Allowed: []Show{
   546  					{
   547  						KeyMatch: "x-response",
   548  					},
   549  				},
   550  				Sanitize: []Sanitize{
   551  					{
   552  						KeyMatch:   "^x-value",
   553  						ValueMatch: "^tes",
   554  					},
   555  				},
   556  			},
   557  			requestConfig: Filter{
   558  				Allowed: []Show{
   559  					{
   560  						KeyMatch: "^x-amplify-somethingelse",
   561  					},
   562  				},
   563  				Sanitize: []Sanitize{
   564  					{
   565  						KeyMatch:   "^x-amplify-something",
   566  						ValueMatch: "^ran",
   567  					},
   568  				},
   569  			},
   570  			inputResponse: responseHeaders,
   571  			inputRequest:  requestHeaders,
   572  			outputResponse: map[string]string{
   573  				"x-response": "random",
   574  			},
   575  			outputRequest: map[string]string{
   576  				"x-amplify-somethingelse": "else",
   577  			},
   578  		},
   579  	}
   580  
   581  	for _, test := range testCases {
   582  		t.Run(test.name, func(t *testing.T) {
   583  
   584  			defConfig := DefaultConfig()
   585  			defConfig.RequestHeaders = test.requestConfig   // update to the test config
   586  			defConfig.ResponseHeaders = test.responseConfig // update to the test config
   587  
   588  			err := SetupGlobalRedaction(defConfig)
   589  			assert.Nil(t, err)
   590  
   591  			// Request Header redaction
   592  			redactedRequestHeaders, err := RequestHeadersRedaction(test.inputRequest)
   593  			assert.Nil(t, err)
   594  			assert.NotNil(t, redactedRequestHeaders)
   595  			assert.Equal(t, test.outputRequest, redactedRequestHeaders)
   596  
   597  			// Response Header redaction
   598  			redactedResponseHeaders, err := ResponseHeadersRedaction(test.inputResponse)
   599  			assert.Nil(t, err)
   600  			assert.NotNil(t, redactedResponseHeaders)
   601  			assert.Equal(t, test.outputResponse, redactedResponseHeaders)
   602  		})
   603  	}
   604  }