mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
tests: signature-utils test (#2342)
This commit is contained in:
parent
c1d70f1f9e
commit
1494af485e
@ -23,6 +23,74 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestIsRequestUnsignedPayload - Test validates the Unsigned payload detection logic.
|
||||
func TestIsRequestUnsignedPayload(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputAmzContentHeader string
|
||||
expectedResult bool
|
||||
}{
|
||||
// Test case - 1.
|
||||
// Test case with "X-Amz-Content-Sha256" header set to empty value.
|
||||
{"", false},
|
||||
// Test case - 2.
|
||||
// Test case with "X-Amz-Content-Sha256" header set to "UNSIGNED-PAYLOAD"
|
||||
// The payload is flagged as unsigned When "X-Amz-Content-Sha256" header is set to "UNSIGNED-PAYLOAD".
|
||||
{"UNSIGNED-PAYLOAD", true},
|
||||
// Test case - 3.
|
||||
// set to a random value.
|
||||
{"abcd", false},
|
||||
}
|
||||
|
||||
// creating an input HTTP request.
|
||||
// Only the headers are relevant for this particular test.
|
||||
inputReq, err := http.NewRequest("GET", "http://example.com", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error initializing input HTTP request: %v", err)
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
inputReq.Header.Set("X-Amz-Content-Sha256", testCase.inputAmzContentHeader)
|
||||
actualResult := isRequestUnsignedPayload(inputReq)
|
||||
if testCase.expectedResult != actualResult {
|
||||
t.Errorf("Test %d: Expected the result to `%v`, but instead got `%v`", i+1, testCase.expectedResult, actualResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestIsRequestPresignedSignatureV4 - Test validates the logic for presign signature verision v4 detection.
|
||||
func TestIsRequestPresignedSignatureV4(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputQueryKey string
|
||||
inputQueryValue string
|
||||
expectedResult bool
|
||||
}{
|
||||
// Test case - 1.
|
||||
// Test case with query key ""X-Amz-Credential" set.
|
||||
{"", "", false},
|
||||
// Test case - 2.
|
||||
{"X-Amz-Credential", "", true},
|
||||
// Test case - 3.
|
||||
{"X-Amz-Content-Sha256", "", false},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
// creating an input HTTP request.
|
||||
// Only the query parameters are relevant for this particular test.
|
||||
inputReq, err := http.NewRequest("GET", "http://example.com", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error initializing input HTTP request: %v", err)
|
||||
}
|
||||
q := inputReq.URL.Query()
|
||||
q.Add(testCase.inputQueryKey, testCase.inputQueryValue)
|
||||
inputReq.URL.RawQuery = q.Encode()
|
||||
|
||||
actualResult := isRequestPresignedSignatureV4(inputReq)
|
||||
if testCase.expectedResult != actualResult {
|
||||
t.Errorf("Test %d: Expected the result to `%v`, but instead got `%v`", i+1, testCase.expectedResult, actualResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Provides a fully populated http request instance, fails otherwise.
|
||||
func mustNewRequest(method string, urlStr string, contentLength int64, body io.ReadSeeker, t *testing.T) *http.Request {
|
||||
req, err := newTestRequest(method, urlStr, contentLength, body)
|
||||
|
176
signature-v4-utils_test.go
Normal file
176
signature-v4-utils_test.go
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015, 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestSkipContentSha256Cksum - Test validate the logic which decides whether to skip checksum validation based on the request header.
|
||||
func TestSkipContentSha256Cksum(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputHeaderKey string
|
||||
inputHeaderValue string
|
||||
|
||||
inputQueryKey string
|
||||
inputQueryValue string
|
||||
|
||||
expectedResult bool
|
||||
}{
|
||||
// Test case - 1.
|
||||
// Test case with "X-Amz-Content-Sha256" header set to empty value.
|
||||
{"X-Amz-Content-Sha256", "", "", "", false},
|
||||
// Test case - 2.
|
||||
// Test case with "X-Amz-Content-Sha256" header set to "UNSIGNED-PAYLOAD"
|
||||
// When "X-Amz-Content-Sha256" header is set to "UNSIGNED-PAYLOAD", validation of content sha256 has to be skipped.
|
||||
{"X-Amz-Content-Sha256", "UNSIGNED-PAYLOAD", "", "", true},
|
||||
// Test case - 3.
|
||||
// Enabling PreSigned Signature v4.
|
||||
{"", "", "X-Amz-Credential", "", true},
|
||||
// Test case - 4.
|
||||
// "X-Amz-Content-Sha256" not set and PreSigned Signature v4 not enabled, sha256 checksum calculation is not skipped.
|
||||
{"", "", "X-Amz-Credential", "", true},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
// creating an input HTTP request.
|
||||
// Only the headers are relevant for this particular test.
|
||||
inputReq, err := http.NewRequest("GET", "http://example.com", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error initializing input HTTP request: %v", err)
|
||||
}
|
||||
if testCase.inputHeaderKey != "" {
|
||||
inputReq.Header.Set(testCase.inputHeaderKey, testCase.inputHeaderValue)
|
||||
}
|
||||
if testCase.inputQueryKey != "" {
|
||||
q := inputReq.URL.Query()
|
||||
q.Add(testCase.inputQueryKey, testCase.inputQueryValue)
|
||||
inputReq.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
actualResult := skipContentSha256Cksum(inputReq)
|
||||
if testCase.expectedResult != actualResult {
|
||||
t.Errorf("Test %d: Expected the result to `%v`, but instead got `%v`", i+1, testCase.expectedResult, actualResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestIsValidRegion - Tests validate the comparison logic for asserting whether the region from http request is valid.
|
||||
func TestIsValidRegion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputReqRegion string
|
||||
inputConfRegion string
|
||||
|
||||
expectedResult bool
|
||||
}{
|
||||
|
||||
{"", "", false},
|
||||
{"us-east-1", "", true},
|
||||
{"us-east-1", "US", true},
|
||||
{"us-west-1", "US", false},
|
||||
{"us-west-1", "us-west-1", true},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
|
||||
actualResult := isValidRegion(testCase.inputReqRegion, testCase.inputConfRegion)
|
||||
if testCase.expectedResult != actualResult {
|
||||
t.Errorf("Test %d: Expected the result to `%v`, but instead got `%v`", i+1, testCase.expectedResult, actualResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests validate the URL path encoder.
|
||||
func TestGetURLEncodedName(t *testing.T) {
|
||||
testCases := []struct {
|
||||
// Input.
|
||||
inputStr string
|
||||
// Expected result.
|
||||
result string
|
||||
}{
|
||||
// % should be encoded as %25
|
||||
{"thisisthe%url", "thisisthe%25url"},
|
||||
// UTF-8 encoding.
|
||||
{"本語", "%E6%9C%AC%E8%AA%9E"},
|
||||
// UTF-8 encoding with ASCII.
|
||||
{"本語.1", "%E6%9C%AC%E8%AA%9E.1"},
|
||||
// Unusual ASCII characters.
|
||||
{">123", "%3E123"},
|
||||
// Fragment path characters.
|
||||
{"myurl#link", "myurl%23link"},
|
||||
// Space should be set to %20 not '+'.
|
||||
{"space in url", "space%20in%20url"},
|
||||
// '+' shouldn't be treated as space.
|
||||
{"url+path", "url%2Bpath"},
|
||||
}
|
||||
|
||||
// Tests generated values from url encoded name.
|
||||
for i, testCase := range testCases {
|
||||
result := getURLEncodedName(testCase.inputStr)
|
||||
if testCase.result != result {
|
||||
t.Errorf("Test %d: Expected queryEncode result to be \"%s\", but found it to be \"%s\" instead", i+1, testCase.result, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestExtractSignedHeaders - Tests validate extraction of signed headers using list of signed header keys.
|
||||
func TestExtractSignedHeaders(t *testing.T) {
|
||||
signedHeaders := []string{"host", "x-amz-content-sha256", "x-amz-date"}
|
||||
|
||||
for i, key := range signedHeaders {
|
||||
signedHeaders[i] = http.CanonicalHeaderKey(key)
|
||||
}
|
||||
|
||||
// If the `expect` key exists in the signed headers then golang server would have stripped out the value, expecting the `expect` header set to `100-continue` in the result.
|
||||
signedHeaders = append(signedHeaders, "expect")
|
||||
// expected header values.
|
||||
expectedHost := "play.minio.io:9000"
|
||||
expectedContentSha256 := "1234abcd"
|
||||
expectedTime := time.Now().UTC().Format(iso8601Format)
|
||||
|
||||
// Creating input http header.
|
||||
inputHeader := make(http.Header)
|
||||
inputHeader.Set(signedHeaders[0], expectedHost)
|
||||
inputHeader.Set(signedHeaders[1], expectedContentSha256)
|
||||
inputHeader.Set(signedHeaders[2], expectedTime)
|
||||
// calling the function being tested.
|
||||
extractedSignedHeaders := extractSignedHeaders(signedHeaders, inputHeader)
|
||||
// "x-amz-content-sha256" header value from the extracted result.
|
||||
extractedContentSha256 := extractedSignedHeaders.Get(signedHeaders[1])
|
||||
// "host" header value from the extracted result.
|
||||
extractedHost := extractedSignedHeaders.Get(signedHeaders[0])
|
||||
// "x-amz-date" header from the extracted result.
|
||||
extractedDate := extractedSignedHeaders.Get(signedHeaders[2])
|
||||
// extracted `expect` header.
|
||||
extractedExpect := extractedSignedHeaders["expect"][0]
|
||||
// assert the result with the expected value.
|
||||
if expectedContentSha256 != extractedContentSha256 {
|
||||
t.Errorf("x-amz-content-sha256 header mismatch: expected `%s`, got `%s`", expectedContentSha256, extractedContentSha256)
|
||||
}
|
||||
if expectedTime != extractedDate {
|
||||
t.Errorf("x-amz-date header mismatch: expected `%s`, got `%s`", expectedTime, extractedDate)
|
||||
}
|
||||
if expectedHost != extractedHost {
|
||||
t.Errorf("host header mismatch: expected `%s`, got `%s`", expectedHost, extractedHost)
|
||||
}
|
||||
// Since the list of signed headers value contained `expect`, the default value of `100-continue` will be added to extracted signed headers.
|
||||
if extractedExpect != "100-continue" {
|
||||
t.Errorf("expect header incorrect value: expected `%s`, got `%s`", "100-continue", extractedExpect)
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
// Tests validate the URL path encoder.
|
||||
func TestUrlEncodePath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
// Input.
|
||||
inputStr string
|
||||
// Expected result.
|
||||
result string
|
||||
}{
|
||||
// % should be encoded as %25
|
||||
{"thisisthe%url", "thisisthe%25url"},
|
||||
// UTF-8 encoding.
|
||||
{"本語", "%E6%9C%AC%E8%AA%9E"},
|
||||
// UTF-8 encoding with ASCII.
|
||||
{"本語.1", "%E6%9C%AC%E8%AA%9E.1"},
|
||||
// Unusual ASCII characters.
|
||||
{">123", "%3E123"},
|
||||
// Fragment path characters.
|
||||
{"myurl#link", "myurl%23link"},
|
||||
// Space should be set to %20 not '+'.
|
||||
{"space in url", "space%20in%20url"},
|
||||
// '+' shouldn't be treated as space.
|
||||
{"url+path", "url%2Bpath"},
|
||||
}
|
||||
|
||||
// Tests generated values from url encoded name.
|
||||
for i, testCase := range testCases {
|
||||
result := getURLEncodedName(testCase.inputStr)
|
||||
if testCase.result != result {
|
||||
t.Errorf("Test %d: Expected queryEncode result to be \"%s\", but found it to be \"%s\" instead", i+1, testCase.result, result)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user