github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/crypto/header_test.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package crypto 19 20 import ( 21 "encoding/base64" 22 "net/http" 23 "sort" 24 "testing" 25 26 xhttp "github.com/minio/minio/internal/http" 27 ) 28 29 func TestIsRequested(t *testing.T) { 30 for i, test := range kmsIsRequestedTests { 31 _, got := IsRequested(test.Header) 32 if Requested(test.Header) != got { 33 // Test if result matches. 34 t.Errorf("Requested mismatch, want %v, got %v", Requested(test.Header), got) 35 } 36 got = got && S3KMS.IsRequested(test.Header) 37 if got != test.Expected { 38 t.Errorf("SSE-KMS: Test %d: Wanted %v but got %v", i, test.Expected, got) 39 } 40 } 41 for i, test := range s3IsRequestedTests { 42 _, got := IsRequested(test.Header) 43 if Requested(test.Header) != got { 44 // Test if result matches. 45 t.Errorf("Requested mismatch, want %v, got %v", Requested(test.Header), got) 46 } 47 got = got && S3.IsRequested(test.Header) 48 if got != test.Expected { 49 t.Errorf("SSE-S3: Test %d: Wanted %v but got %v", i, test.Expected, got) 50 } 51 } 52 for i, test := range ssecIsRequestedTests { 53 _, got := IsRequested(test.Header) 54 if Requested(test.Header) != got { 55 // Test if result matches. 56 t.Errorf("Requested mismatch, want %v, got %v", Requested(test.Header), got) 57 } 58 got = got && SSEC.IsRequested(test.Header) 59 if got != test.Expected { 60 t.Errorf("SSE-C: Test %d: Wanted %v but got %v", i, test.Expected, got) 61 } 62 } 63 } 64 65 var kmsIsRequestedTests = []struct { 66 Header http.Header 67 Expected bool 68 }{ 69 {Header: http.Header{}, Expected: false}, // 0 70 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"aws:kms"}}, Expected: true}, // 1 71 {Header: http.Header{"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"0839-9047947-844842874-481"}}, Expected: true}, // 2 72 {Header: http.Header{"X-Amz-Server-Side-Encryption-Context": []string{"7PpPLAK26ONlVUGOWlusfg=="}}, Expected: true}, // 3 73 { 74 Header: http.Header{ 75 "X-Amz-Server-Side-Encryption": []string{""}, 76 "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{""}, 77 "X-Amz-Server-Side-Encryption-Context": []string{""}, 78 }, 79 Expected: true, 80 }, // 4 81 { 82 Header: http.Header{ 83 "X-Amz-Server-Side-Encryption": []string{"AES256"}, 84 "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{""}, 85 }, 86 Expected: true, 87 }, // 5 88 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES256"}}, Expected: false}, // 6 89 } 90 91 func TestKMSIsRequested(t *testing.T) { 92 for i, test := range kmsIsRequestedTests { 93 if got := S3KMS.IsRequested(test.Header); got != test.Expected { 94 t.Errorf("Test %d: Wanted %v but got %v", i, test.Expected, got) 95 } 96 } 97 } 98 99 var kmsParseHTTPTests = []struct { 100 Header http.Header 101 ShouldFail bool 102 }{ 103 {Header: http.Header{}, ShouldFail: true}, // 0 104 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"aws:kms"}}, ShouldFail: false}, // 1 105 {Header: http.Header{ 106 "X-Amz-Server-Side-Encryption": []string{"aws:kms"}, 107 "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"}, 108 }, ShouldFail: false}, // 2 109 {Header: http.Header{ 110 "X-Amz-Server-Side-Encryption": []string{"aws:kms"}, 111 "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"}, 112 "X-Amz-Server-Side-Encryption-Context": []string{base64.StdEncoding.EncodeToString([]byte("{}"))}, 113 }, ShouldFail: false}, // 3 114 {Header: http.Header{ 115 "X-Amz-Server-Side-Encryption": []string{"aws:kms"}, 116 "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"}, 117 "X-Amz-Server-Side-Encryption-Context": []string{base64.StdEncoding.EncodeToString([]byte(`{"bucket": "some-bucket"}`))}, 118 }, ShouldFail: false}, // 4 119 {Header: http.Header{ 120 "X-Amz-Server-Side-Encryption": []string{"aws:kms"}, 121 "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"}, 122 "X-Amz-Server-Side-Encryption-Context": []string{base64.StdEncoding.EncodeToString([]byte(`{"bucket": "some-bucket"}`))}, 123 }, ShouldFail: false}, // 5 124 {Header: http.Header{ 125 "X-Amz-Server-Side-Encryption": []string{"AES256"}, 126 "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"}, 127 "X-Amz-Server-Side-Encryption-Context": []string{base64.StdEncoding.EncodeToString([]byte(`{"bucket": "some-bucket"}`))}, 128 }, ShouldFail: true}, // 6 129 {Header: http.Header{ 130 "X-Amz-Server-Side-Encryption": []string{"aws:kms"}, 131 "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"}, 132 "X-Amz-Server-Side-Encryption-Context": []string{base64.StdEncoding.EncodeToString([]byte(`{"bucket": "some-bucket"`))}, // invalid JSON 133 }, ShouldFail: true}, // 7 134 135 } 136 137 func TestKMSParseHTTP(t *testing.T) { 138 for i, test := range kmsParseHTTPTests { 139 _, _, err := S3KMS.ParseHTTP(test.Header) 140 if err == nil && test.ShouldFail { 141 t.Errorf("Test %d: should fail but succeeded", i) 142 } 143 if err != nil && !test.ShouldFail { 144 t.Errorf("Test %d: should pass but failed with: %v", i, err) 145 } 146 } 147 } 148 149 var s3IsRequestedTests = []struct { 150 Header http.Header 151 Expected bool 152 }{ 153 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES256"}}, Expected: true}, // 0 154 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES-256"}}, Expected: true}, // 1 155 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{""}}, Expected: true}, // 2 156 {Header: http.Header{"X-Amz-Server-Side-Encryptio": []string{"AES256"}}, Expected: false}, // 3 157 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{xhttp.AmzEncryptionKMS}}, Expected: false}, // 4 158 } 159 160 func TestS3IsRequested(t *testing.T) { 161 for i, test := range s3IsRequestedTests { 162 if got := S3.IsRequested(test.Header); got != test.Expected { 163 t.Errorf("Test %d: Wanted %v but got %v", i, test.Expected, got) 164 } 165 } 166 } 167 168 var s3ParseTests = []struct { 169 Header http.Header 170 ExpectedErr error 171 }{ 172 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES256"}}, ExpectedErr: nil}, // 0 173 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES-256"}}, ExpectedErr: ErrInvalidEncryptionMethod}, // 1 174 {Header: http.Header{"X-Amz-Server-Side-Encryption": []string{""}}, ExpectedErr: ErrInvalidEncryptionMethod}, // 2 175 {Header: http.Header{"X-Amz-Server-Side-Encryptio": []string{"AES256"}}, ExpectedErr: ErrInvalidEncryptionMethod}, // 3 176 } 177 178 func TestS3Parse(t *testing.T) { 179 for i, test := range s3ParseTests { 180 if err := S3.ParseHTTP(test.Header); err != test.ExpectedErr { 181 t.Errorf("Test %d: Wanted '%v' but got '%v'", i, test.ExpectedErr, err) 182 } 183 } 184 } 185 186 var ssecIsRequestedTests = []struct { 187 Header http.Header 188 Expected bool 189 }{ 190 {Header: http.Header{}, Expected: false}, // 0 191 {Header: http.Header{"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}}, Expected: true}, // 1 192 {Header: http.Header{"X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}}, Expected: true}, // 2 193 {Header: http.Header{"X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}}, Expected: true}, // 3 194 { 195 Header: http.Header{ 196 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{""}, 197 "X-Amz-Server-Side-Encryption-Customer-Key": []string{""}, 198 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{""}, 199 }, 200 Expected: true, 201 }, // 4 202 { 203 Header: http.Header{ 204 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 205 "X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 206 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 207 }, 208 Expected: true, 209 }, // 5 210 { 211 Header: http.Header{ 212 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 213 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 214 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 215 }, 216 Expected: false, 217 }, // 6 218 } 219 220 func TestSSECIsRequested(t *testing.T) { 221 for i, test := range ssecIsRequestedTests { 222 if got := SSEC.IsRequested(test.Header); got != test.Expected { 223 t.Errorf("Test %d: Wanted %v but got %v", i, test.Expected, got) 224 } 225 } 226 } 227 228 var ssecCopyIsRequestedTests = []struct { 229 Header http.Header 230 Expected bool 231 }{ 232 {Header: http.Header{}, Expected: false}, // 0 233 {Header: http.Header{"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}}, Expected: true}, // 1 234 {Header: http.Header{"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}}, Expected: true}, // 2 235 {Header: http.Header{"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}}, Expected: true}, // 3 236 { 237 Header: http.Header{ 238 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{""}, 239 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{""}, 240 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{""}, 241 }, 242 Expected: true, 243 }, // 4 244 { 245 Header: http.Header{ 246 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 247 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 248 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 249 }, 250 Expected: true, 251 }, // 5 252 { 253 Header: http.Header{ 254 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 255 "X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 256 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 257 }, 258 Expected: false, 259 }, // 6 260 } 261 262 func TestSSECopyIsRequested(t *testing.T) { 263 for i, test := range ssecCopyIsRequestedTests { 264 if got := SSECopy.IsRequested(test.Header); got != test.Expected { 265 t.Errorf("Test %d: Wanted %v but got %v", i, test.Expected, got) 266 } 267 } 268 } 269 270 var ssecParseTests = []struct { 271 Header http.Header 272 ExpectedErr error 273 }{ 274 { 275 Header: http.Header{ 276 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 277 "X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 278 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 279 }, 280 ExpectedErr: nil, // 0 281 }, 282 { 283 Header: http.Header{ 284 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES-256"}, // invalid algorithm 285 "X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 286 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 287 }, 288 ExpectedErr: ErrInvalidCustomerAlgorithm, // 1 289 }, 290 { 291 Header: http.Header{ 292 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 293 "X-Amz-Server-Side-Encryption-Customer-Key": []string{""}, // no client key 294 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 295 }, 296 ExpectedErr: ErrMissingCustomerKey, // 2 297 }, 298 { 299 Header: http.Header{ 300 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 301 "X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRr.ZXltdXN0cHJvdmlkZWQ="}, // invalid key 302 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 303 }, 304 ExpectedErr: ErrInvalidCustomerKey, // 3 305 }, 306 { 307 Header: http.Header{ 308 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 309 "X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 310 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{""}, // no key MD5 311 }, 312 ExpectedErr: ErrMissingCustomerKeyMD5, // 4 313 }, 314 { 315 Header: http.Header{ 316 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 317 "X-Amz-Server-Side-Encryption-Customer-Key": []string{"DzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, // wrong client key 318 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 319 }, 320 ExpectedErr: ErrCustomerKeyMD5Mismatch, // 5 321 }, 322 { 323 Header: http.Header{ 324 "X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 325 "X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 326 "X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{".7PpPLAK26ONlVUGOWlusfg=="}, // wrong key MD5 327 }, 328 ExpectedErr: ErrCustomerKeyMD5Mismatch, // 6 329 }, 330 } 331 332 func TestSSECParse(t *testing.T) { 333 var zeroKey [32]byte 334 for i, test := range ssecParseTests { 335 key, err := SSEC.ParseHTTP(test.Header) 336 if err != test.ExpectedErr { 337 t.Errorf("Test %d: want error '%v' but got '%v'", i, test.ExpectedErr, err) 338 } 339 340 if err != nil && key != zeroKey { 341 t.Errorf("Test %d: parsing failed and client key is not zero key", i) 342 } 343 if err == nil && key == zeroKey { 344 t.Errorf("Test %d: parsed client key is zero key", i) 345 } 346 } 347 } 348 349 var ssecCopyParseTests = []struct { 350 Header http.Header 351 ExpectedErr error 352 }{ 353 { 354 Header: http.Header{ 355 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 356 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 357 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 358 }, 359 ExpectedErr: nil, // 0 360 }, 361 { 362 Header: http.Header{ 363 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES-256"}, // invalid algorithm 364 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 365 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 366 }, 367 ExpectedErr: ErrInvalidCustomerAlgorithm, // 1 368 }, 369 { 370 Header: http.Header{ 371 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 372 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{""}, // no client key 373 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 374 }, 375 ExpectedErr: ErrMissingCustomerKey, // 2 376 }, 377 { 378 Header: http.Header{ 379 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 380 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRr.ZXltdXN0cHJvdmlkZWQ="}, // invalid key 381 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 382 }, 383 ExpectedErr: ErrInvalidCustomerKey, // 3 384 }, 385 { 386 Header: http.Header{ 387 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 388 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 389 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{""}, // no key MD5 390 }, 391 ExpectedErr: ErrMissingCustomerKeyMD5, // 4 392 }, 393 { 394 Header: http.Header{ 395 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 396 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"DzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, // wrong client key 397 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}, 398 }, 399 ExpectedErr: ErrCustomerKeyMD5Mismatch, // 5 400 }, 401 { 402 Header: http.Header{ 403 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}, 404 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 405 "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{".7PpPLAK26ONlVUGOWlusfg=="}, // wrong key MD5 406 }, 407 ExpectedErr: ErrCustomerKeyMD5Mismatch, // 6 408 }, 409 } 410 411 func TestSSECopyParse(t *testing.T) { 412 var zeroKey [32]byte 413 for i, test := range ssecCopyParseTests { 414 key, err := SSECopy.ParseHTTP(test.Header) 415 if err != test.ExpectedErr { 416 t.Errorf("Test %d: want error '%v' but got '%v'", i, test.ExpectedErr, err) 417 } 418 419 if err != nil && key != zeroKey { 420 t.Errorf("Test %d: parsing failed and client key is not zero key", i) 421 } 422 if err == nil && key == zeroKey { 423 t.Errorf("Test %d: parsed client key is zero key", i) 424 } 425 if _, ok := test.Header[xhttp.AmzServerSideEncryptionCustomerKey]; ok { 426 t.Errorf("Test %d: client key is not removed from HTTP headers after parsing", i) 427 } 428 } 429 } 430 431 var removeSensitiveHeadersTests = []struct { 432 Header, ExpectedHeader http.Header 433 }{ 434 { 435 Header: http.Header{ 436 xhttp.AmzServerSideEncryptionCustomerKey: []string{""}, 437 xhttp.AmzServerSideEncryptionCopyCustomerKey: []string{""}, 438 }, 439 ExpectedHeader: http.Header{}, 440 }, 441 { // Standard SSE-C request headers 442 Header: http.Header{ 443 xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}, 444 xhttp.AmzServerSideEncryptionCustomerKey: []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 445 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}, 446 }, 447 ExpectedHeader: http.Header{ 448 xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}, 449 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}, 450 }, 451 }, 452 { // Standard SSE-C + SSE-C-copy request headers 453 Header: http.Header{ 454 xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}, 455 xhttp.AmzServerSideEncryptionCustomerKey: []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 456 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}, 457 xhttp.AmzServerSideEncryptionCopyCustomerKey: []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 458 xhttp.AmzServerSideEncryptionCopyCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}, 459 }, 460 ExpectedHeader: http.Header{ 461 xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}, 462 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}, 463 xhttp.AmzServerSideEncryptionCopyCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}, 464 }, 465 }, 466 { // Standard SSE-C + metadata request headers 467 Header: http.Header{ 468 xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}, 469 xhttp.AmzServerSideEncryptionCustomerKey: []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 470 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}, 471 "X-Amz-Meta-Test-1": []string{"Test-1"}, 472 }, 473 ExpectedHeader: http.Header{ 474 xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}, 475 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}, 476 "X-Amz-Meta-Test-1": []string{"Test-1"}, 477 }, 478 }, 479 { // https://github.com/google/security-research/security/advisories/GHSA-76wf-9vgp-pj7w 480 Header: http.Header{ 481 "X-Amz-Meta-X-Amz-Unencrypted-Content-Md5": []string{"value"}, 482 "X-Amz-Meta-X-Amz-Unencrypted-Content-Length": []string{"value"}, 483 "X-Amz-Meta-Test-1": []string{"Test-1"}, 484 }, 485 ExpectedHeader: http.Header{ 486 "X-Amz-Meta-Test-1": []string{"Test-1"}, 487 }, 488 }, 489 } 490 491 func TestRemoveSensitiveHeaders(t *testing.T) { 492 isEqual := func(x, y http.Header) bool { 493 if len(x) != len(y) { 494 return false 495 } 496 for k, v := range x { 497 u, ok := y[k] 498 if !ok || len(v) != len(u) { 499 return false 500 } 501 sort.Strings(v) 502 sort.Strings(u) 503 for j := range v { 504 if v[j] != u[j] { 505 return false 506 } 507 } 508 } 509 return true 510 } 511 areKeysEqual := func(h http.Header, metadata map[string]string) bool { 512 if len(h) != len(metadata) { 513 return false 514 } 515 for k := range h { 516 if _, ok := metadata[k]; !ok { 517 return false 518 } 519 } 520 return true 521 } 522 523 for i, test := range removeSensitiveHeadersTests { 524 metadata := make(map[string]string, len(test.Header)) 525 for k := range test.Header { 526 metadata[k] = "" // set metadata key - we don't care about the value 527 } 528 529 RemoveSensitiveHeaders(test.Header) 530 if !isEqual(test.ExpectedHeader, test.Header) { 531 t.Errorf("Test %d: filtered headers do not match expected headers - got: %v , want: %v", i, test.Header, test.ExpectedHeader) 532 } 533 RemoveSensitiveEntries(metadata) 534 if !areKeysEqual(test.ExpectedHeader, metadata) { 535 t.Errorf("Test %d: filtered headers do not match expected headers - got: %v , want: %v", i, test.Header, test.ExpectedHeader) 536 } 537 } 538 }