2021-04-18 15:41:13 -04:00
// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
2016-08-11 20:49:40 -04:00
2016-08-18 19:23:42 -04:00
package cmd
2016-08-11 20:49:40 -04:00
import (
2021-03-25 16:57:57 -04:00
"bytes"
2016-10-25 02:47:03 -04:00
"encoding/base64"
2019-03-05 15:10:47 -05:00
"fmt"
2017-03-13 17:41:13 -04:00
"net/http"
2021-03-25 16:57:57 -04:00
"strings"
2016-08-11 20:49:40 -04:00
"testing"
2017-12-31 20:58:10 -05:00
2020-07-14 12:38:05 -04:00
minio "github.com/minio/minio-go/v7"
2016-08-11 20:49:40 -04:00
)
2021-03-21 01:16:30 -04:00
func TestParsePostPolicyForm ( t * testing . T ) {
testCases := [ ] struct {
policy string
success bool
} {
// missing expiration, will fail.
{
policy : ` { "conditions":[["eq","$bucket","asdf"],["eq","$key","hello.txt"]],"conditions":[["eq","$success_action_status","201"],["eq","$Content-Type","plain/text"],["eq","$success_action_status","201"],["eq","$x-amz-algorithm","AWS4-HMAC-SHA256"],["eq","$x-amz-credential","Q3AM3UQ867SPQQA43P2F/20210315/us-east-1/s3/aws4_request"],["eq","$x-amz-date","20210315T091621Z"]]} ` ,
success : false ,
} ,
// invalid json.
{
policy : ` { "conditions":[["eq","$bucket","asdf"],["eq","$key","hello.txt"]],"conditions":[["eq","$success_action_status","201"],["eq","$Content-Type","plain/text"],["eq","$success_action_status","201"],["eq","$x-amz-algorithm","AWS4-HMAC-SHA256"],["eq","$x-amz-credential","Q3AM3UQ867SPQQA43P2F/20210315/us-east-1/s3/aws4_request"],["eq","$x-amz-date","20210315T091621Z"]] ` ,
success : false ,
} ,
2021-03-25 16:57:57 -04:00
// duplicate 'expiration' reject
{
policy : ` { "expiration":"2021-03-22T09:16:21.310Z","expiration":"2021-03-22T09:16:21.310Z","conditions":[["eq","$bucket","evil"],["eq","$key","hello.txt"],["eq","$success_action_status","201"],["eq","$Content-Type","plain/text"],["eq","$success_action_status","201"],["eq","$x-amz-algorithm","AWS4-HMAC-SHA256"],["eq","$x-amz-credential","Q3AM3UQ867SPQQA43P2F/20210315/us-east-1/s3/aws4_request"],["eq","$x-amz-date","20210315T091621Z"]]} ` ,
} ,
// duplicate '$bucket' reject
{
policy : ` { "expiration":"2021-03-22T09:16:21.310Z","conditions":[["eq","$bucket","good"],["eq","$key","hello.txt"]],"conditions":[["eq","$bucket","evil"],["eq","$key","hello.txt"],["eq","$success_action_status","201"],["eq","$Content-Type","plain/text"],["eq","$success_action_status","201"],["eq","$x-amz-algorithm","AWS4-HMAC-SHA256"],["eq","$x-amz-credential","Q3AM3UQ867SPQQA43P2F/20210315/us-east-1/s3/aws4_request"],["eq","$x-amz-date","20210315T091621Z"]]} ` ,
success : false ,
} ,
// duplicate conditions, reject
2021-03-21 01:16:30 -04:00
{
policy : ` { "expiration":"2021-03-22T09:16:21.310Z","conditions":[["eq","$bucket","asdf"],["eq","$key","hello.txt"]],"conditions":[["eq","$success_action_status","201"],["eq","$Content-Type","plain/text"],["eq","$success_action_status","201"],["eq","$x-amz-algorithm","AWS4-HMAC-SHA256"],["eq","$x-amz-credential","Q3AM3UQ867SPQQA43P2F/20210315/us-east-1/s3/aws4_request"],["eq","$x-amz-date","20210315T091621Z"]]} ` ,
2021-03-25 16:57:57 -04:00
success : false ,
2021-03-21 01:16:30 -04:00
} ,
// no duplicates, shall be parsed properly.
{
policy : ` { "expiration":"2021-03-27T20:35:28.458Z","conditions":[["eq","$bucket","testbucket"],["eq","$key","wtf.txt"],["eq","$x-amz-date","20210320T203528Z"],["eq","$x-amz-algorithm","AWS4-HMAC-SHA256"],["eq","$x-amz-credential","Q3AM3UQ867SPQQA43P2F/20210320/us-east-1/s3/aws4_request"]]} ` ,
success : true ,
} ,
}
for _ , testCase := range testCases {
testCase := testCase
t . Run ( "" , func ( t * testing . T ) {
2021-03-25 16:57:57 -04:00
_ , err := parsePostPolicyForm ( strings . NewReader ( testCase . policy ) )
2021-03-21 01:16:30 -04:00
if testCase . success && err != nil {
t . Errorf ( "Expected success but failed with %s" , err )
}
if ! testCase . success && err == nil {
t . Errorf ( "Expected failed but succeeded" )
}
} )
}
}
2016-08-11 20:49:40 -04:00
// Test Post Policy parsing and checking conditions
func TestPostPolicyForm ( t * testing . T ) {
2017-12-31 20:58:10 -05:00
pp := minio . NewPostPolicy ( )
pp . SetBucket ( "testbucket" )
pp . SetContentType ( "image/jpeg" )
pp . SetUserMetadata ( "uuid" , "14365123651274" )
pp . SetKeyStartsWith ( "user/user1/filename" )
pp . SetContentLengthRange ( 1048579 , 10485760 )
pp . SetSuccessStatusAction ( "201" )
2016-08-11 20:49:40 -04:00
type testCase struct {
2017-12-31 20:58:10 -05:00
Bucket string
Key string
XAmzDate string
XAmzAlgorithm string
XAmzCredential string
XAmzMetaUUID string
ContentType string
SuccessActionStatus string
Policy string
Expired bool
2019-03-05 15:10:47 -05:00
expectedErr error
2016-08-11 20:49:40 -04:00
}
2017-12-31 20:58:10 -05:00
2016-08-11 20:49:40 -04:00
testCases := [ ] testCase {
2016-12-03 15:41:07 -05:00
// Everything is fine with this test
2019-03-05 15:10:47 -05:00
{ Bucket : "testbucket" , Key : "user/user1/filename/${filename}/myfile.txt" , XAmzMetaUUID : "14365123651274" , SuccessActionStatus : "201" , XAmzCredential : "KVGKMDUQ23TCZXTLTHLP/20160727/us-east-1/s3/aws4_request" , XAmzDate : "20160727T000000Z" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "image/jpeg" , expectedErr : nil } ,
2016-12-03 15:41:07 -05:00
// Expired policy document
2019-03-05 15:10:47 -05:00
{ Bucket : "testbucket" , Key : "user/user1/filename/${filename}/myfile.txt" , XAmzMetaUUID : "14365123651274" , SuccessActionStatus : "201" , XAmzCredential : "KVGKMDUQ23TCZXTLTHLP/20160727/us-east-1/s3/aws4_request" , XAmzDate : "20160727T000000Z" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "image/jpeg" , Expired : true , expectedErr : fmt . Errorf ( "Invalid according to Policy: Policy expired" ) } ,
2016-08-11 20:49:40 -04:00
// Different AMZ date
2019-03-05 15:10:47 -05:00
{ Bucket : "testbucket" , Key : "user/user1/filename/${filename}/myfile.txt" , XAmzMetaUUID : "14365123651274" , XAmzDate : "2017T000000Z" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "image/jpeg" , expectedErr : fmt . Errorf ( "Invalid according to Policy: Policy Condition failed" ) } ,
2016-08-11 20:49:40 -04:00
// Key which doesn't start with user/user1/filename
2019-03-05 15:10:47 -05:00
{ Bucket : "testbucket" , Key : "myfile.txt" , XAmzDate : "20160727T000000Z" , XAmzMetaUUID : "14365123651274" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "image/jpeg" , expectedErr : fmt . Errorf ( "Invalid according to Policy: Policy Condition failed" ) } ,
2016-10-26 13:15:57 -04:00
// Incorrect bucket name.
2019-03-05 15:10:47 -05:00
{ Bucket : "incorrect" , Key : "user/user1/filename/myfile.txt" , XAmzMetaUUID : "14365123651274" , XAmzDate : "20160727T000000Z" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "image/jpeg" , expectedErr : fmt . Errorf ( "Invalid according to Policy: Policy Condition failed" ) } ,
2016-10-26 13:15:57 -04:00
// Incorrect key name
2019-03-05 15:10:47 -05:00
{ Bucket : "testbucket" , Key : "incorrect" , XAmzDate : "20160727T000000Z" , XAmzMetaUUID : "14365123651274" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "image/jpeg" , expectedErr : fmt . Errorf ( "Invalid according to Policy: Policy Condition failed" ) } ,
2016-10-26 13:15:57 -04:00
// Incorrect date
2019-03-05 15:10:47 -05:00
{ Bucket : "testbucket" , Key : "user/user1/filename/${filename}/myfile.txt" , XAmzMetaUUID : "14365123651274" , XAmzDate : "incorrect" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "image/jpeg" , expectedErr : fmt . Errorf ( "Invalid according to Policy: Policy Condition failed" ) } ,
2016-10-26 13:15:57 -04:00
// Incorrect ContentType
2019-03-05 15:10:47 -05:00
{ Bucket : "testbucket" , Key : "user/user1/filename/${filename}/myfile.txt" , XAmzMetaUUID : "14365123651274" , XAmzDate : "20160727T000000Z" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "incorrect" , expectedErr : fmt . Errorf ( "Invalid according to Policy: Policy Condition failed" ) } ,
// Incorrect Metadata
{ Bucket : "testbucket" , Key : "user/user1/filename/${filename}/myfile.txt" , XAmzMetaUUID : "151274" , SuccessActionStatus : "201" , XAmzCredential : "KVGKMDUQ23TCZXTLTHLP/20160727/us-east-1/s3/aws4_request" , XAmzDate : "20160727T000000Z" , XAmzAlgorithm : "AWS4-HMAC-SHA256" , ContentType : "image/jpeg" , expectedErr : fmt . Errorf ( "Invalid according to Policy: Policy Condition failed: [eq, $x-amz-meta-uuid, 14365123651274]" ) } ,
2016-08-11 20:49:40 -04:00
}
// Validate all the test cases.
for i , tt := range testCases {
2017-03-13 17:41:13 -04:00
formValues := make ( http . Header )
formValues . Set ( "Bucket" , tt . Bucket )
formValues . Set ( "Key" , tt . Key )
2017-12-31 20:58:10 -05:00
formValues . Set ( "Content-Type" , tt . ContentType )
2017-03-13 17:41:13 -04:00
formValues . Set ( "X-Amz-Date" , tt . XAmzDate )
formValues . Set ( "X-Amz-Meta-Uuid" , tt . XAmzMetaUUID )
formValues . Set ( "X-Amz-Algorithm" , tt . XAmzAlgorithm )
formValues . Set ( "X-Amz-Credential" , tt . XAmzCredential )
2017-12-31 20:58:10 -05:00
if tt . Expired {
// Expired already.
pp . SetExpires ( UTCNow ( ) . AddDate ( 0 , 0 , - 10 ) )
} else {
// Expires in 10 days.
pp . SetExpires ( UTCNow ( ) . AddDate ( 0 , 0 , 10 ) )
}
formValues . Set ( "Policy" , base64 . StdEncoding . EncodeToString ( [ ] byte ( pp . String ( ) ) ) )
formValues . Set ( "Success_action_status" , tt . SuccessActionStatus )
policyBytes , err := base64 . StdEncoding . DecodeString ( base64 . StdEncoding . EncodeToString ( [ ] byte ( pp . String ( ) ) ) )
2016-10-25 02:47:03 -04:00
if err != nil {
t . Fatal ( err )
}
2016-08-11 20:49:40 -04:00
2021-03-25 16:57:57 -04:00
postPolicyForm , err := parsePostPolicyForm ( bytes . NewReader ( policyBytes ) )
2016-10-25 02:47:03 -04:00
if err != nil {
t . Fatal ( err )
}
2017-12-31 20:58:10 -05:00
2019-03-05 15:10:47 -05:00
err = checkPostPolicy ( formValues , postPolicyForm )
if err != nil && tt . expectedErr != nil && err . Error ( ) != tt . expectedErr . Error ( ) {
t . Fatalf ( "Test %d:, Expected %s, got %s" , i + 1 , tt . expectedErr . Error ( ) , err . Error ( ) )
2016-08-11 20:49:40 -04:00
}
}
}