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 }