github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/edgegrid/signer_test.go (about)

     1  package edgegrid
     2  
     3  import (
     4  	"encoding/base64"
     5  	"net/http"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/google/uuid"
    11  	"github.com/stretchr/testify/require"
    12  	"github.com/tj/assert"
    13  )
    14  
    15  func TestConfig_createAuthHeader(t *testing.T) {
    16  	tests := map[string]struct {
    17  		config    Config
    18  		request   *http.Request
    19  		expected  authHeader
    20  		withError error
    21  	}{
    22  		"method is GET": {
    23  			config: Config{
    24  				ClientToken: "12345",
    25  				AccessToken: "54321",
    26  				MaxBody:     MaxBodySize,
    27  			},
    28  			request: func() *http.Request {
    29  				req, err := http.NewRequest(http.MethodGet, "http://akamai.com/test/path?query=test", nil)
    30  				require.NoError(t, err)
    31  				return req
    32  			}(),
    33  			expected: authHeader{
    34  				authType:    authType,
    35  				clientToken: "12345",
    36  				accessToken: "54321",
    37  			},
    38  		},
    39  	}
    40  
    41  	for name, test := range tests {
    42  		t.Run(name, func(t *testing.T) {
    43  			res := test.config.createAuthHeader(test.request)
    44  			assert.Equal(t, test.expected.authType, res.authType)
    45  			assert.Equal(t, test.expected.accessToken, res.accessToken)
    46  			assert.Equal(t, test.expected.clientToken, res.clientToken)
    47  			assert.NotEmpty(t, res.signature)
    48  			_, err := uuid.Parse(res.nonce)
    49  			assert.NoError(t, err)
    50  			_, err = base64.StdEncoding.DecodeString(res.signature)
    51  			require.NoError(t, err)
    52  			_, err = time.Parse("20060102T15:04:05-0700", res.timestamp)
    53  			assert.NoError(t, err)
    54  		})
    55  	}
    56  }
    57  
    58  func TestCanonicalizeHeaders(t *testing.T) {
    59  	tests := map[string]struct {
    60  		requestHeaders http.Header
    61  		headersToSign  []string
    62  		expected       string
    63  	}{
    64  		"found matching request headers": {
    65  			requestHeaders: map[string][]string{
    66  				"A": {"val1"},
    67  				"B": {"  VAL   2   "},
    68  				"C": {"V A L 3"},
    69  			},
    70  			headersToSign: []string{"B", "C"},
    71  			expected:      "b:val 2\tc:v a l 3",
    72  		},
    73  		"no matching headers found": {
    74  			requestHeaders: map[string][]string{
    75  				"A": {"val1"},
    76  				"B": {"  VAL   2   "},
    77  				"C": {"V A L 3"},
    78  			},
    79  			headersToSign: []string{"D", "E"},
    80  			expected:      "",
    81  		},
    82  	}
    83  
    84  	for name, test := range tests {
    85  		t.Run(name, func(t *testing.T) {
    86  			res := canonicalizeHeaders(test.requestHeaders, test.headersToSign)
    87  			assert.Equal(t, test.expected, res)
    88  		})
    89  	}
    90  }
    91  
    92  func TestCreateContentHash(t *testing.T) {
    93  	tests := map[string]struct {
    94  		httpMethod  string
    95  		body        string
    96  		resultEmpty bool
    97  	}{
    98  		"PUT request": {
    99  			httpMethod:  http.MethodPut,
   100  			body:        `{"key":"value"}`,
   101  			resultEmpty: true,
   102  		},
   103  		"POST request, empty body": {
   104  			httpMethod:  http.MethodPost,
   105  			body:        "",
   106  			resultEmpty: true,
   107  		},
   108  		"POST request, body is not empty": {
   109  			httpMethod:  http.MethodPost,
   110  			body:        `{"key":"value"}`,
   111  			resultEmpty: false,
   112  		},
   113  	}
   114  
   115  	for name, test := range tests {
   116  		t.Run(name, func(t *testing.T) {
   117  			req, err := http.NewRequest(test.httpMethod, "", strings.NewReader(test.body))
   118  			require.NoError(t, err)
   119  			res := createContentHash(req, MaxBodySize)
   120  			if test.resultEmpty {
   121  				assert.Empty(t, res)
   122  				return
   123  			}
   124  			require.NotEmpty(t, res)
   125  			_, err = base64.StdEncoding.DecodeString(res)
   126  			assert.NoError(t, err)
   127  		})
   128  	}
   129  }
   130  
   131  func TestAuthHeader_String(t *testing.T) {
   132  	tests := map[string]struct {
   133  		given    authHeader
   134  		expected string
   135  	}{
   136  		"signature is empty": {
   137  			given: authHeader{
   138  				authType:    "A",
   139  				clientToken: "B",
   140  				accessToken: "C",
   141  				timestamp:   "D",
   142  				nonce:       "E",
   143  			},
   144  			expected: "A client_token=B;access_token=C;timestamp=D;nonce=E;",
   145  		},
   146  		"signature is not empty": {
   147  			given: authHeader{
   148  				authType:    "A",
   149  				clientToken: "B",
   150  				accessToken: "C",
   151  				timestamp:   "D",
   152  				nonce:       "E",
   153  				signature:   "F",
   154  			},
   155  			expected: "A client_token=B;access_token=C;timestamp=D;nonce=E;signature=F",
   156  		},
   157  	}
   158  
   159  	for name, test := range tests {
   160  		t.Run(name, func(t *testing.T) {
   161  			res := test.given.String()
   162  			assert.Equal(t, test.expected, res)
   163  		})
   164  	}
   165  }
   166  
   167  func TestAddAccountSwitchKey(t *testing.T) {
   168  	tests := map[string]struct {
   169  		config    Config
   170  		request   *http.Request
   171  		expected  string
   172  		withError error
   173  	}{
   174  		"test account switch single param GET": {
   175  			config: Config{
   176  				ClientToken: "12345",
   177  				AccessToken: "54321",
   178  				AccountKey:  "test_switch",
   179  				MaxBody:     MaxBodySize,
   180  			},
   181  			request: func() *http.Request {
   182  				req, err := http.NewRequest(http.MethodGet, "http://akamai.com/test/path?query=test", nil)
   183  				require.NoError(t, err)
   184  				return req
   185  			}(),
   186  			expected: "accountSwitchKey=test_switch&query=test",
   187  		},
   188  		"test account switch multiple param GET": {
   189  			config: Config{
   190  				ClientToken: "12345",
   191  				AccessToken: "54321",
   192  				AccountKey:  "test_switch",
   193  				MaxBody:     MaxBodySize,
   194  			},
   195  			request: func() *http.Request {
   196  				req, err := http.NewRequest(http.MethodGet, "http://akamai.com/test/path?query1=test1&query2=test2", nil)
   197  				require.NoError(t, err)
   198  				return req
   199  			}(),
   200  			expected: "accountSwitchKey=test_switch&query1=test1&query2=test2",
   201  		},
   202  		"test account switch empty GET": {
   203  			config: Config{
   204  				ClientToken: "12345",
   205  				AccessToken: "54321",
   206  				AccountKey:  "test_switch",
   207  				MaxBody:     MaxBodySize,
   208  			},
   209  			request: func() *http.Request {
   210  				req, err := http.NewRequest(http.MethodGet, "http://akamai.com/test/path", nil)
   211  				require.NoError(t, err)
   212  				return req
   213  			}(),
   214  			expected: "accountSwitchKey=test_switch",
   215  		},
   216  	}
   217  
   218  	for name, test := range tests {
   219  		t.Run(name, func(t *testing.T) {
   220  			res := test.config.addAccountSwitchKey(test.request)
   221  			assert.NotNil(t, test.request.URL.Host)
   222  			assert.NotEmpty(t, res)
   223  			assert.Equal(t, test.expected, res)
   224  			assert.Equal(t, test.request.URL.Host, "akamai.com")
   225  			assert.Equal(t, test.request.URL.Path, "/test/path")
   226  		})
   227  	}
   228  }