mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
signature: use region from Auth header if server's region not configured (#4329)
This commit is contained in:
parent
465274cd21
commit
5db1e9f3dd
@ -17,6 +17,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/minio/minio-go/pkg/set"
|
"github.com/minio/minio-go/pkg/set"
|
||||||
@ -111,20 +112,21 @@ func checkARN(arn, arnType string) APIErrorCode {
|
|||||||
if !strings.HasPrefix(arn, arnType) {
|
if !strings.HasPrefix(arn, arnType) {
|
||||||
return ErrARNNotification
|
return ErrARNNotification
|
||||||
}
|
}
|
||||||
if !strings.HasPrefix(arn, arnType+serverConfig.GetRegion()+":") {
|
strs := strings.SplitN(arn, ":", -1)
|
||||||
return ErrRegionNotification
|
if len(strs) != 6 {
|
||||||
}
|
|
||||||
account := strings.SplitN(strings.TrimPrefix(arn, arnType+serverConfig.GetRegion()+":"), ":", 2)
|
|
||||||
switch len(account) {
|
|
||||||
case 1:
|
|
||||||
// This means ARN is malformed, account should have min of 2elements.
|
|
||||||
return ErrARNNotification
|
return ErrARNNotification
|
||||||
case 2:
|
}
|
||||||
// Account topic id or topic name cannot be empty.
|
if serverConfig.GetRegion() != "" {
|
||||||
if account[0] == "" || account[1] == "" {
|
region := strs[3]
|
||||||
return ErrARNNotification
|
if region != serverConfig.GetRegion() {
|
||||||
|
return ErrRegionNotification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
accountID := strs[4]
|
||||||
|
resource := strs[5]
|
||||||
|
if accountID == "" || resource == "" {
|
||||||
|
return ErrARNNotification
|
||||||
|
}
|
||||||
return ErrNone
|
return ErrNone
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,28 +260,39 @@ func validateNotificationConfig(nConfig notificationConfig) APIErrorCode {
|
|||||||
// - webhook
|
// - webhook
|
||||||
func unmarshalSqsARN(queueARN string) (mSqs arnSQS) {
|
func unmarshalSqsARN(queueARN string) (mSqs arnSQS) {
|
||||||
mSqs = arnSQS{}
|
mSqs = arnSQS{}
|
||||||
if !strings.HasPrefix(queueARN, minioSqs+serverConfig.GetRegion()+":") {
|
strs := strings.SplitN(queueARN, ":", -1)
|
||||||
|
if len(strs) != 6 {
|
||||||
return mSqs
|
return mSqs
|
||||||
}
|
}
|
||||||
sqsType := strings.TrimPrefix(queueARN, minioSqs+serverConfig.GetRegion()+":")
|
if serverConfig.GetRegion() != "" {
|
||||||
switch {
|
region := strs[3]
|
||||||
case hasSuffix(sqsType, queueTypeAMQP):
|
if region != serverConfig.GetRegion() {
|
||||||
|
return mSqs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqsType := strs[5]
|
||||||
|
switch sqsType {
|
||||||
|
case queueTypeAMQP:
|
||||||
mSqs.Type = queueTypeAMQP
|
mSqs.Type = queueTypeAMQP
|
||||||
case hasSuffix(sqsType, queueTypeNATS):
|
case queueTypeNATS:
|
||||||
mSqs.Type = queueTypeNATS
|
mSqs.Type = queueTypeNATS
|
||||||
case hasSuffix(sqsType, queueTypeElastic):
|
case queueTypeElastic:
|
||||||
mSqs.Type = queueTypeElastic
|
mSqs.Type = queueTypeElastic
|
||||||
case hasSuffix(sqsType, queueTypeRedis):
|
case queueTypeRedis:
|
||||||
mSqs.Type = queueTypeRedis
|
mSqs.Type = queueTypeRedis
|
||||||
case hasSuffix(sqsType, queueTypePostgreSQL):
|
case queueTypePostgreSQL:
|
||||||
mSqs.Type = queueTypePostgreSQL
|
mSqs.Type = queueTypePostgreSQL
|
||||||
case hasSuffix(sqsType, queueTypeMySQL):
|
case queueTypeMySQL:
|
||||||
mSqs.Type = queueTypeMySQL
|
mSqs.Type = queueTypeMySQL
|
||||||
case hasSuffix(sqsType, queueTypeKafka):
|
case queueTypeKafka:
|
||||||
mSqs.Type = queueTypeKafka
|
mSqs.Type = queueTypeKafka
|
||||||
case hasSuffix(sqsType, queueTypeWebhook):
|
case queueTypeWebhook:
|
||||||
mSqs.Type = queueTypeWebhook
|
mSqs.Type = queueTypeWebhook
|
||||||
|
default:
|
||||||
|
errorIf(errors.New("invalid SQS type"), "SQS type: %s", sqsType)
|
||||||
} // Add more queues here.
|
} // Add more queues here.
|
||||||
mSqs.AccountID = strings.TrimSuffix(sqsType, ":"+mSqs.Type)
|
|
||||||
|
mSqs.AccountID = strs[4]
|
||||||
|
|
||||||
return mSqs
|
return mSqs
|
||||||
}
|
}
|
||||||
|
@ -259,11 +259,6 @@ func TestQueueARN(t *testing.T) {
|
|||||||
queueARN: "arn:minio:sns:us-east-1:1:listen",
|
queueARN: "arn:minio:sns:us-east-1:1:listen",
|
||||||
errCode: ErrARNNotification,
|
errCode: ErrARNNotification,
|
||||||
},
|
},
|
||||||
// Invalid region 'us-west-1' in queue arn.
|
|
||||||
{
|
|
||||||
queueARN: "arn:minio:sqs:us-west-1:1:redis",
|
|
||||||
errCode: ErrRegionNotification,
|
|
||||||
},
|
|
||||||
// Invalid queue name empty in queue arn.
|
// Invalid queue name empty in queue arn.
|
||||||
{
|
{
|
||||||
queueARN: "arn:minio:sqs:us-east-1:1:",
|
queueARN: "arn:minio:sqs:us-east-1:1:",
|
||||||
@ -298,6 +293,37 @@ func TestQueueARN(t *testing.T) {
|
|||||||
t.Errorf("Test %d: Expected \"%d\", got \"%d\"", i+1, testCase.errCode, errCode)
|
t.Errorf("Test %d: Expected \"%d\", got \"%d\"", i+1, testCase.errCode, errCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test when server region is set.
|
||||||
|
rootPath, err = newTestConfig("us-east-1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable initialize config file, %s", err)
|
||||||
|
}
|
||||||
|
defer removeAll(rootPath)
|
||||||
|
|
||||||
|
testCases = []struct {
|
||||||
|
queueARN string
|
||||||
|
errCode APIErrorCode
|
||||||
|
}{
|
||||||
|
// Incorrect region should produce error.
|
||||||
|
{
|
||||||
|
queueARN: "arn:minio:sqs:us-west-1:1:webhook",
|
||||||
|
errCode: ErrRegionNotification,
|
||||||
|
},
|
||||||
|
// Correct region should not produce error.
|
||||||
|
{
|
||||||
|
queueARN: "arn:minio:sqs:us-east-1:1:webhook",
|
||||||
|
errCode: ErrNone,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate all tests for queue arn.
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
errCode := checkQueueARN(testCase.queueARN)
|
||||||
|
if testCase.errCode != errCode {
|
||||||
|
t.Errorf("Test %d: Expected \"%d\", got \"%d\"", i+1, testCase.errCode, errCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test unmarshal queue arn.
|
// Test unmarshal queue arn.
|
||||||
@ -337,11 +363,6 @@ func TestUnmarshalSQSARN(t *testing.T) {
|
|||||||
queueARN: "",
|
queueARN: "",
|
||||||
Type: "",
|
Type: "",
|
||||||
},
|
},
|
||||||
// Invalid region 'us-west-1' in queue arn.
|
|
||||||
{
|
|
||||||
queueARN: "arn:minio:sqs:us-west-1:1:redis",
|
|
||||||
Type: "",
|
|
||||||
},
|
|
||||||
// Partial queue arn.
|
// Partial queue arn.
|
||||||
{
|
{
|
||||||
queueARN: "arn:minio:sqs:",
|
queueARN: "arn:minio:sqs:",
|
||||||
@ -361,4 +382,33 @@ func TestUnmarshalSQSARN(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test when the server region is set.
|
||||||
|
rootPath, err = newTestConfig("us-east-1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable initialize config file, %s", err)
|
||||||
|
}
|
||||||
|
defer removeAll(rootPath)
|
||||||
|
|
||||||
|
testCases = []struct {
|
||||||
|
queueARN string
|
||||||
|
Type string
|
||||||
|
}{
|
||||||
|
// Incorrect region in ARN returns empty mSqs.Type
|
||||||
|
{
|
||||||
|
queueARN: "arn:minio:sqs:us-west-1:1:webhook",
|
||||||
|
Type: "",
|
||||||
|
},
|
||||||
|
// Correct regionin ARN returns valid mSqs.Type
|
||||||
|
{
|
||||||
|
queueARN: "arn:minio:sqs:us-east-1:1:webhook",
|
||||||
|
Type: "webhook",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
mSqs := unmarshalSqsARN(testCase.queueARN)
|
||||||
|
if testCase.Type != mSqs.Type {
|
||||||
|
t.Errorf("Test %d: Expected \"%s\", got \"%s\"", i+1, testCase.Type, mSqs.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,11 +261,6 @@ func getValidConfig() (*serverConfigV18, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate region field
|
|
||||||
if srvCfg.Region == "" {
|
|
||||||
return nil, errors.New("Region config value cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate credential fields only when
|
// Validate credential fields only when
|
||||||
// they are not set via the environment
|
// they are not set via the environment
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
globalMinioCertExpireWarnDays = time.Hour * 24 * 30 // 30 days.
|
globalMinioCertExpireWarnDays = time.Hour * 24 * 30 // 30 days.
|
||||||
|
|
||||||
globalMinioDefaultRegion = "us-east-1"
|
globalMinioDefaultRegion = ""
|
||||||
globalMinioDefaultOwnerID = "minio"
|
globalMinioDefaultOwnerID = "minio"
|
||||||
globalMinioDefaultStorageClass = "STANDARD"
|
globalMinioDefaultStorageClass = "STANDARD"
|
||||||
globalWindowsOSName = "windows"
|
globalWindowsOSName = "windows"
|
||||||
|
@ -38,7 +38,7 @@ func parseLocationConstraint(r *http.Request) (location string, s3Error APIError
|
|||||||
} // else for both err as nil or io.EOF
|
} // else for both err as nil or io.EOF
|
||||||
location = locationConstraint.Location
|
location = locationConstraint.Location
|
||||||
if location == "" {
|
if location == "" {
|
||||||
location = globalMinioDefaultRegion
|
location = serverConfig.GetRegion()
|
||||||
}
|
}
|
||||||
return location, ErrNone
|
return location, ErrNone
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func parseLocationConstraint(r *http.Request) (location string, s3Error APIError
|
|||||||
// Validates input location is same as configured region
|
// Validates input location is same as configured region
|
||||||
// of Minio server.
|
// of Minio server.
|
||||||
func isValidLocation(location string) bool {
|
func isValidLocation(location string) bool {
|
||||||
return serverConfig.GetRegion() == location
|
return serverConfig.GetRegion() == "" || serverConfig.GetRegion() == location
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supported headers that needs to be extracted.
|
// Supported headers that needs to be extracted.
|
||||||
|
@ -246,6 +246,7 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
region := "us-east-1"
|
||||||
// Test cases for signature-V4.
|
// Test cases for signature-V4.
|
||||||
testCasesV4BadData := []struct {
|
testCasesV4BadData := []struct {
|
||||||
objectName string
|
objectName string
|
||||||
@ -330,7 +331,7 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr
|
|||||||
testCase.policy = fmt.Sprintf(testCase.policy, testCase.dates...)
|
testCase.policy = fmt.Sprintf(testCase.policy, testCase.dates...)
|
||||||
|
|
||||||
req, perr := newPostRequestV4Generic("", bucketName, testCase.objectName, testCase.data, testCase.accessKey,
|
req, perr := newPostRequestV4Generic("", bucketName, testCase.objectName, testCase.data, testCase.accessKey,
|
||||||
testCase.secretKey, curTime, []byte(testCase.policy), nil, testCase.corruptedBase64, testCase.corruptedMultipart)
|
testCase.secretKey, region, curTime, []byte(testCase.policy), nil, testCase.corruptedBase64, testCase.corruptedMultipart)
|
||||||
if perr != nil {
|
if perr != nil {
|
||||||
t.Fatalf("Test %d: %s: Failed to create HTTP request for PostPolicyHandler: <ERROR> %v", i+1, instanceType, perr)
|
t.Fatalf("Test %d: %s: Failed to create HTTP request for PostPolicyHandler: <ERROR> %v", i+1, instanceType, perr)
|
||||||
}
|
}
|
||||||
@ -473,9 +474,10 @@ func testPostPolicyBucketHandlerRedirect(obj ObjectLayer, instanceType string, t
|
|||||||
// Generate the final policy document
|
// Generate the final policy document
|
||||||
policy = fmt.Sprintf(policy, dates...)
|
policy = fmt.Sprintf(policy, dates...)
|
||||||
|
|
||||||
|
region := "us-east-1"
|
||||||
// Create a new POST request with success_action_redirect field specified
|
// Create a new POST request with success_action_redirect field specified
|
||||||
req, perr := newPostRequestV4Generic("", bucketName, keyName, []byte("objData"),
|
req, perr := newPostRequestV4Generic("", bucketName, keyName, []byte("objData"),
|
||||||
credentials.AccessKey, credentials.SecretKey, curTime,
|
credentials.AccessKey, credentials.SecretKey, region, curTime,
|
||||||
[]byte(policy), map[string]string{"success_action_redirect": redirectURL.String()}, false, false)
|
[]byte(policy), map[string]string{"success_action_redirect": redirectURL.String()}, false, false)
|
||||||
|
|
||||||
if perr != nil {
|
if perr != nil {
|
||||||
@ -565,11 +567,11 @@ func newPostRequestV2(endPoint, bucketName, objectName string, accessKey, secret
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildGenericPolicy(t time.Time, accessKey, bucketName, objectName string, contentLengthRange bool) []byte {
|
func buildGenericPolicy(t time.Time, accessKey, region, bucketName, objectName string, contentLengthRange bool) []byte {
|
||||||
// Expire the request five minutes from now.
|
// Expire the request five minutes from now.
|
||||||
expirationTime := t.Add(time.Minute * 5)
|
expirationTime := t.Add(time.Minute * 5)
|
||||||
|
|
||||||
credStr := getCredentialString(accessKey, serverConfig.GetRegion(), t)
|
credStr := getCredentialString(accessKey, region, t)
|
||||||
// Create a new post policy.
|
// Create a new post policy.
|
||||||
policy := newPostPolicyBytesV4(credStr, bucketName, objectName, expirationTime)
|
policy := newPostPolicyBytesV4(credStr, bucketName, objectName, expirationTime)
|
||||||
if contentLengthRange {
|
if contentLengthRange {
|
||||||
@ -578,10 +580,10 @@ func buildGenericPolicy(t time.Time, accessKey, bucketName, objectName string, c
|
|||||||
return policy
|
return policy
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData []byte, accessKey, secretKey string,
|
func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData []byte, accessKey, secretKey string, region string,
|
||||||
t time.Time, policy []byte, addFormData map[string]string, corruptedB64 bool, corruptedMultipart bool) (*http.Request, error) {
|
t time.Time, policy []byte, addFormData map[string]string, corruptedB64 bool, corruptedMultipart bool) (*http.Request, error) {
|
||||||
// Get the user credential.
|
// Get the user credential.
|
||||||
credStr := getCredentialString(accessKey, serverConfig.GetRegion(), t)
|
credStr := getCredentialString(accessKey, region, t)
|
||||||
|
|
||||||
// Only need the encoding.
|
// Only need the encoding.
|
||||||
encodedPolicy := base64.StdEncoding.EncodeToString(policy)
|
encodedPolicy := base64.StdEncoding.EncodeToString(policy)
|
||||||
@ -591,7 +593,7 @@ func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData []
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Presign with V4 signature based on the policy.
|
// Presign with V4 signature based on the policy.
|
||||||
signature := postPresignSignatureV4(encodedPolicy, t, secretKey, serverConfig.GetRegion())
|
signature := postPresignSignatureV4(encodedPolicy, t, secretKey, region)
|
||||||
|
|
||||||
formData := map[string]string{
|
formData := map[string]string{
|
||||||
"bucket": bucketName,
|
"bucket": bucketName,
|
||||||
@ -645,12 +647,14 @@ func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData []
|
|||||||
|
|
||||||
func newPostRequestV4WithContentLength(endPoint, bucketName, objectName string, objData []byte, accessKey, secretKey string) (*http.Request, error) {
|
func newPostRequestV4WithContentLength(endPoint, bucketName, objectName string, objData []byte, accessKey, secretKey string) (*http.Request, error) {
|
||||||
t := UTCNow()
|
t := UTCNow()
|
||||||
policy := buildGenericPolicy(t, accessKey, bucketName, objectName, true)
|
region := "us-east-1"
|
||||||
return newPostRequestV4Generic(endPoint, bucketName, objectName, objData, accessKey, secretKey, t, policy, nil, false, false)
|
policy := buildGenericPolicy(t, accessKey, region, bucketName, objectName, true)
|
||||||
|
return newPostRequestV4Generic(endPoint, bucketName, objectName, objData, accessKey, secretKey, region, t, policy, nil, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPostRequestV4(endPoint, bucketName, objectName string, objData []byte, accessKey, secretKey string) (*http.Request, error) {
|
func newPostRequestV4(endPoint, bucketName, objectName string, objData []byte, accessKey, secretKey string) (*http.Request, error) {
|
||||||
t := UTCNow()
|
t := UTCNow()
|
||||||
policy := buildGenericPolicy(t, accessKey, bucketName, objectName, false)
|
region := "us-east-1"
|
||||||
return newPostRequestV4Generic(endPoint, bucketName, objectName, objData, accessKey, secretKey, t, policy, nil, false, false)
|
policy := buildGenericPolicy(t, accessKey, region, bucketName, objectName, false)
|
||||||
|
return newPostRequestV4Generic(endPoint, bucketName, objectName, objData, accessKey, secretKey, region, t, policy, nil, false, false)
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,9 @@ func printServerCommonMsg(apiEndpoints []string) {
|
|||||||
log.Println(colorBlue("\nEndpoint: ") + colorBold(fmt.Sprintf(getFormatStr(len(apiEndpointStr), 1), apiEndpointStr)))
|
log.Println(colorBlue("\nEndpoint: ") + colorBold(fmt.Sprintf(getFormatStr(len(apiEndpointStr), 1), apiEndpointStr)))
|
||||||
log.Println(colorBlue("AccessKey: ") + colorBold(fmt.Sprintf("%s ", cred.AccessKey)))
|
log.Println(colorBlue("AccessKey: ") + colorBold(fmt.Sprintf("%s ", cred.AccessKey)))
|
||||||
log.Println(colorBlue("SecretKey: ") + colorBold(fmt.Sprintf("%s ", cred.SecretKey)))
|
log.Println(colorBlue("SecretKey: ") + colorBold(fmt.Sprintf("%s ", cred.SecretKey)))
|
||||||
log.Println(colorBlue("Region: ") + colorBold(fmt.Sprintf(getFormatStr(len(region), 3), region)))
|
if region != "" {
|
||||||
|
log.Println(colorBlue("Region: ") + colorBold(fmt.Sprintf(getFormatStr(len(region), 3), region)))
|
||||||
|
}
|
||||||
printEventNotifiers()
|
printEventNotifiers()
|
||||||
|
|
||||||
log.Println(colorBlue("\nBrowser Access:"))
|
log.Println(colorBlue("\nBrowser Access:"))
|
||||||
@ -92,12 +94,12 @@ func printEventNotifiers() {
|
|||||||
// In case initEventNotifier() was not done or failed.
|
// In case initEventNotifier() was not done or failed.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
arnMsg := colorBlue("SQS ARNs: ")
|
|
||||||
// Get all configured external notification targets
|
// Get all configured external notification targets
|
||||||
externalTargets := globalEventNotifier.GetAllExternalTargets()
|
externalTargets := globalEventNotifier.GetAllExternalTargets()
|
||||||
if len(externalTargets) == 0 {
|
if len(externalTargets) == 0 {
|
||||||
arnMsg += colorBold(fmt.Sprintf(getFormatStr(len("<none>"), 1), "<none>"))
|
return
|
||||||
}
|
}
|
||||||
|
arnMsg := colorBlue("SQS ARNs: ")
|
||||||
for queueArn := range externalTargets {
|
for queueArn := range externalTargets {
|
||||||
arnMsg += colorBold(fmt.Sprintf(getFormatStr(len(queueArn), 1), queueArn))
|
arnMsg += colorBold(fmt.Sprintf(getFormatStr(len(queueArn), 1), queueArn))
|
||||||
}
|
}
|
||||||
|
@ -69,9 +69,6 @@ func parseCredentialHeader(credElement string) (credentialHeader, APIErrorCode)
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
return credentialHeader{}, ErrMalformedCredentialDate
|
return credentialHeader{}, ErrMalformedCredentialDate
|
||||||
}
|
}
|
||||||
if credElements[2] == "" {
|
|
||||||
return credentialHeader{}, ErrMalformedCredentialRegion
|
|
||||||
}
|
|
||||||
cred.scope.region = credElements[2]
|
cred.scope.region = credElements[2]
|
||||||
if credElements[3] != "s3" {
|
if credElements[3] != "s3" {
|
||||||
return credentialHeader{}, ErrInvalidService
|
return credentialHeader{}, ErrInvalidService
|
||||||
|
@ -141,19 +141,6 @@ func TestParseCredentialHeader(t *testing.T) {
|
|||||||
expectedErrCode: ErrMalformedCredentialDate,
|
expectedErrCode: ErrMalformedCredentialDate,
|
||||||
},
|
},
|
||||||
// Test Case - 6.
|
// Test Case - 6.
|
||||||
// Test case with invalid region.
|
|
||||||
// region should a non empty string.
|
|
||||||
{
|
|
||||||
inputCredentialStr: generateCredentialStr(
|
|
||||||
"Z7IXGOO6BZ0REAN1Q26I",
|
|
||||||
UTCNow().Format(yyyymmdd),
|
|
||||||
"",
|
|
||||||
"ABCD",
|
|
||||||
"ABCD"),
|
|
||||||
expectedCredentials: credentialHeader{},
|
|
||||||
expectedErrCode: ErrMalformedCredentialRegion,
|
|
||||||
},
|
|
||||||
// Test Case - 7.
|
|
||||||
// Test case with invalid service.
|
// Test case with invalid service.
|
||||||
// "s3" is the valid service string.
|
// "s3" is the valid service string.
|
||||||
{
|
{
|
||||||
@ -166,7 +153,7 @@ func TestParseCredentialHeader(t *testing.T) {
|
|||||||
expectedCredentials: credentialHeader{},
|
expectedCredentials: credentialHeader{},
|
||||||
expectedErrCode: ErrInvalidService,
|
expectedErrCode: ErrInvalidService,
|
||||||
},
|
},
|
||||||
// Test Case - 8.
|
// Test Case - 7.
|
||||||
// Test case with invalid request version.
|
// Test case with invalid request version.
|
||||||
// "aws4_request" is the valid request version.
|
// "aws4_request" is the valid request version.
|
||||||
{
|
{
|
||||||
@ -179,7 +166,7 @@ func TestParseCredentialHeader(t *testing.T) {
|
|||||||
expectedCredentials: credentialHeader{},
|
expectedCredentials: credentialHeader{},
|
||||||
expectedErrCode: ErrInvalidRequestVersion,
|
expectedErrCode: ErrInvalidRequestVersion,
|
||||||
},
|
},
|
||||||
// Test Case - 9.
|
// Test Case - 8.
|
||||||
// Test case with right inputs. Expected to return a valid CredentialHeader.
|
// Test case with right inputs. Expected to return a valid CredentialHeader.
|
||||||
// "aws4_request" is the valid request version.
|
// "aws4_request" is the valid request version.
|
||||||
{
|
{
|
||||||
@ -204,7 +191,7 @@ func TestParseCredentialHeader(t *testing.T) {
|
|||||||
actualCredential, actualErrCode := parseCredentialHeader(testCase.inputCredentialStr)
|
actualCredential, actualErrCode := parseCredentialHeader(testCase.inputCredentialStr)
|
||||||
// validating the credential fields.
|
// validating the credential fields.
|
||||||
if testCase.expectedErrCode != actualErrCode {
|
if testCase.expectedErrCode != actualErrCode {
|
||||||
t.Fatalf("Test %d: Expected the APIErrCode to be %d, got %d", i+1, testCase.expectedErrCode, actualErrCode)
|
t.Fatalf("Test %d: Expected the APIErrCode to be %s, got %s", i+1, errorCodeResponse[testCase.expectedErrCode].Code, errorCodeResponse[actualErrCode].Code)
|
||||||
}
|
}
|
||||||
if actualErrCode == ErrNone {
|
if actualErrCode == ErrNone {
|
||||||
validateCredentialfields(t, i+1, testCase.expectedCredentials, actualCredential)
|
validateCredentialfields(t, i+1, testCase.expectedCredentials, actualCredential)
|
||||||
|
@ -68,7 +68,10 @@ func getContentSha256Cksum(r *http.Request) string {
|
|||||||
|
|
||||||
// isValidRegion - verify if incoming region value is valid with configured Region.
|
// isValidRegion - verify if incoming region value is valid with configured Region.
|
||||||
func isValidRegion(reqRegion string, confRegion string) bool {
|
func isValidRegion(reqRegion string, confRegion string) bool {
|
||||||
if confRegion == "" || confRegion == "US" {
|
if confRegion == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if confRegion == "US" {
|
||||||
confRegion = globalMinioDefaultRegion
|
confRegion = globalMinioDefaultRegion
|
||||||
}
|
}
|
||||||
// Some older s3 clients set region as "US" instead of
|
// Some older s3 clients set region as "US" instead of
|
||||||
|
@ -80,7 +80,7 @@ func TestIsValidRegion(t *testing.T) {
|
|||||||
expectedResult bool
|
expectedResult bool
|
||||||
}{
|
}{
|
||||||
|
|
||||||
{"", "", false},
|
{"", "", true},
|
||||||
{globalMinioDefaultRegion, "", true},
|
{globalMinioDefaultRegion, "", true},
|
||||||
{globalMinioDefaultRegion, "US", true},
|
{globalMinioDefaultRegion, "US", true},
|
||||||
{"us-west-1", "US", false},
|
{"us-west-1", "US", false},
|
||||||
|
@ -175,7 +175,7 @@ func doesPolicySignatureV4Match(formValues http.Header) APIErrorCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get signing key.
|
// Get signing key.
|
||||||
signingKey := getSigningKey(cred.SecretKey, credHeader.scope.date, region)
|
signingKey := getSigningKey(cred.SecretKey, credHeader.scope.date, sRegion)
|
||||||
|
|
||||||
// Get signature.
|
// Get signature.
|
||||||
newSignature := getSignature(signingKey, formValues.Get("Policy"))
|
newSignature := getSignature(signingKey, formValues.Get("Policy"))
|
||||||
|
@ -54,14 +54,7 @@ func TestDoesPolicySignatureMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: ErrInvalidAccessKeyID,
|
expected: ErrInvalidAccessKeyID,
|
||||||
},
|
},
|
||||||
// (2) It should fail if the region is invalid.
|
// (2) It should fail with a bad signature.
|
||||||
{
|
|
||||||
form: http.Header{
|
|
||||||
"X-Amz-Credential": []string{fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), "invalidregion")},
|
|
||||||
},
|
|
||||||
expected: ErrInvalidRegion,
|
|
||||||
},
|
|
||||||
// (3) It should fail with a bad signature.
|
|
||||||
{
|
{
|
||||||
form: http.Header{
|
form: http.Header{
|
||||||
"X-Amz-Credential": []string{fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), globalMinioDefaultRegion)},
|
"X-Amz-Credential": []string{fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), globalMinioDefaultRegion)},
|
||||||
@ -71,7 +64,7 @@ func TestDoesPolicySignatureMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: ErrSignatureDoesNotMatch,
|
expected: ErrSignatureDoesNotMatch,
|
||||||
},
|
},
|
||||||
// (4) It should succeed if everything is correct.
|
// (3) It should succeed if everything is correct.
|
||||||
{
|
{
|
||||||
form: http.Header{
|
form: http.Header{
|
||||||
"X-Amz-Credential": []string{
|
"X-Amz-Credential": []string{
|
||||||
@ -135,21 +128,7 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
|||||||
region: "us-west-1",
|
region: "us-west-1",
|
||||||
expected: ErrInvalidAccessKeyID,
|
expected: ErrInvalidAccessKeyID,
|
||||||
},
|
},
|
||||||
// (2) Should fail with an invalid region.
|
// (2) Should NOT fail with an invalid region if it doesn't verify it.
|
||||||
{
|
|
||||||
queryParams: map[string]string{
|
|
||||||
"X-Amz-Algorithm": signV4Algorithm,
|
|
||||||
"X-Amz-Date": now.Format(iso8601Format),
|
|
||||||
"X-Amz-Expires": "60",
|
|
||||||
"X-Amz-Signature": "badsignature",
|
|
||||||
"X-Amz-SignedHeaders": "host;x-amz-content-sha256;x-amz-date",
|
|
||||||
"X-Amz-Credential": fmt.Sprintf(credentialTemplate, accessKeyID, now.Format(yyyymmdd), "us-west-1"),
|
|
||||||
"X-Amz-Content-Sha256": payloadSHA256,
|
|
||||||
},
|
|
||||||
region: globalMinioDefaultRegion,
|
|
||||||
expected: ErrInvalidRegion,
|
|
||||||
},
|
|
||||||
// (3) Should NOT fail with an invalid region if it doesn't verify it.
|
|
||||||
{
|
{
|
||||||
queryParams: map[string]string{
|
queryParams: map[string]string{
|
||||||
"X-Amz-Algorithm": signV4Algorithm,
|
"X-Amz-Algorithm": signV4Algorithm,
|
||||||
@ -163,7 +142,7 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
|||||||
region: "us-west-1",
|
region: "us-west-1",
|
||||||
expected: ErrUnsignedHeaders,
|
expected: ErrUnsignedHeaders,
|
||||||
},
|
},
|
||||||
// (4) Should fail to extract headers if the host header is not signed.
|
// (3) Should fail to extract headers if the host header is not signed.
|
||||||
{
|
{
|
||||||
queryParams: map[string]string{
|
queryParams: map[string]string{
|
||||||
"X-Amz-Algorithm": signV4Algorithm,
|
"X-Amz-Algorithm": signV4Algorithm,
|
||||||
@ -177,7 +156,7 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
|||||||
region: region,
|
region: region,
|
||||||
expected: ErrUnsignedHeaders,
|
expected: ErrUnsignedHeaders,
|
||||||
},
|
},
|
||||||
// (5) Should give an expired request if it has expired.
|
// (4) Should give an expired request if it has expired.
|
||||||
{
|
{
|
||||||
queryParams: map[string]string{
|
queryParams: map[string]string{
|
||||||
"X-Amz-Algorithm": signV4Algorithm,
|
"X-Amz-Algorithm": signV4Algorithm,
|
||||||
@ -195,7 +174,7 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
|||||||
region: region,
|
region: region,
|
||||||
expected: ErrExpiredPresignRequest,
|
expected: ErrExpiredPresignRequest,
|
||||||
},
|
},
|
||||||
// (6) Should error if the signature is incorrect.
|
// (5) Should error if the signature is incorrect.
|
||||||
{
|
{
|
||||||
queryParams: map[string]string{
|
queryParams: map[string]string{
|
||||||
"X-Amz-Algorithm": signV4Algorithm,
|
"X-Amz-Algorithm": signV4Algorithm,
|
||||||
@ -213,7 +192,7 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
|||||||
region: region,
|
region: region,
|
||||||
expected: ErrSignatureDoesNotMatch,
|
expected: ErrSignatureDoesNotMatch,
|
||||||
},
|
},
|
||||||
// (7) Should error if the request is not ready yet, ie X-Amz-Date is in the future.
|
// (6) Should error if the request is not ready yet, ie X-Amz-Date is in the future.
|
||||||
{
|
{
|
||||||
queryParams: map[string]string{
|
queryParams: map[string]string{
|
||||||
"X-Amz-Algorithm": signV4Algorithm,
|
"X-Amz-Algorithm": signV4Algorithm,
|
||||||
@ -231,7 +210,7 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
|||||||
region: region,
|
region: region,
|
||||||
expected: ErrRequestNotReadyYet,
|
expected: ErrRequestNotReadyYet,
|
||||||
},
|
},
|
||||||
// (8) Should not error with invalid region instead, call should proceed
|
// (7) Should not error with invalid region instead, call should proceed
|
||||||
// with sigature does not match.
|
// with sigature does not match.
|
||||||
{
|
{
|
||||||
queryParams: map[string]string{
|
queryParams: map[string]string{
|
||||||
@ -250,7 +229,7 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
|||||||
region: "",
|
region: "",
|
||||||
expected: ErrSignatureDoesNotMatch,
|
expected: ErrSignatureDoesNotMatch,
|
||||||
},
|
},
|
||||||
// (9) Should error with signature does not match. But handles
|
// (8) Should error with signature does not match. But handles
|
||||||
// query params which do not precede with "x-amz-" header.
|
// query params which do not precede with "x-amz-" header.
|
||||||
{
|
{
|
||||||
queryParams: map[string]string{
|
queryParams: map[string]string{
|
||||||
@ -270,7 +249,7 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
|||||||
region: "",
|
region: "",
|
||||||
expected: ErrSignatureDoesNotMatch,
|
expected: ErrSignatureDoesNotMatch,
|
||||||
},
|
},
|
||||||
// (10) Should error with unsigned headers.
|
// (9) Should error with unsigned headers.
|
||||||
{
|
{
|
||||||
queryParams: map[string]string{
|
queryParams: map[string]string{
|
||||||
"X-Amz-Algorithm": signV4Algorithm,
|
"X-Amz-Algorithm": signV4Algorithm,
|
||||||
|
Loading…
Reference in New Issue
Block a user