/* * * Mint, (C) 2017 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 ( "bytes" "encoding/json" "encoding/xml" "errors" "fmt" "math/rand" "net/http" "os" "strings" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" log "github.com/sirupsen/logrus" ) const letterBytes = "abcdefghijklmnopqrstuvwxyz01234569" const ( letterIdxBits = 6 // 6 bits to represent a letter index letterIdxMask = 1<= 0; { if remain == 0 { cache, remain = src.Int63(), letterIdxMax } if idx := int(cache & letterIdxMask); idx < len(letterBytes) { b[i] = letterBytes[idx] i-- } cache >>= letterIdxBits remain-- } return prefix + string(b[0:30-len(prefix)]) } func cleanup(s3Client *s3.S3, bucket string, object string, function string, args map[string]interface{}, startTime time.Time, deleteBucket bool) { // Deleting the object, just in case it was created. Will not check for errors. s3Client.DeleteObject(&s3.DeleteObjectInput{ Bucket: aws.String(bucket), Key: aws.String(object), }) if deleteBucket { _, err := s3Client.DeleteBucket(&s3.DeleteBucketInput{ Bucket: aws.String(bucket), }) if err != nil { failureLog(function, args, startTime, "", "AWS SDK Go DeleteBucket Failed", err).Fatal() return } } } func testPresignedPutInvalidHash(s3Client *s3.S3) { startTime := time.Now() function := "PresignedPut" bucket := randString(60, rand.NewSource(time.Now().UnixNano()), "aws-sdk-go-test-") object := "presignedTest" expiry := 1 * time.Minute args := map[string]interface{}{ "bucketName": bucket, "objectName": object, "expiry": expiry, } _, err := s3Client.CreateBucket(&s3.CreateBucketInput{ Bucket: aws.String(bucket), }) if err != nil { failureLog(function, args, startTime, "", "AWS SDK Go CreateBucket Failed", err).Fatal() return } defer cleanup(s3Client, bucket, object, function, args, startTime, true) req, _ := s3Client.PutObjectRequest(&s3.PutObjectInput{ Bucket: aws.String(bucket), Key: aws.String(object), ContentType: aws.String("application/octet-stream"), }) req.HTTPRequest.Header.Set("X-Amz-Content-Sha256", "invalid-sha256") url, err := req.Presign(expiry) if err != nil { failureLog(function, args, startTime, "", "AWS SDK Go presigned Put request creation failed", err).Fatal() return } rreq, err := http.NewRequest("PUT", url, bytes.NewReader([]byte(""))) rreq.Header.Add("X-Amz-Content-Sha256", "invalid-sha256") rreq.Header.Add("Content-Type", "application/octet-stream") resp, err := http.DefaultClient.Do(rreq) if err != nil { failureLog(function, args, startTime, "", "AWS SDK Go presigned put request failed", err).Fatal() return } defer resp.Body.Close() dec := xml.NewDecoder(resp.Body) errResp := ErrorResponse{} err = dec.Decode(&errResp) if err != nil { failureLog(function, args, startTime, "", "AWS SDK Go unmarshalling xml failed", err).Fatal() return } if errResp.Code != "XAmzContentSHA256Mismatch" { failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go presigned PUT expected to fail with XAmzContentSHA256Mismatch but got %v", errResp.Code), errors.New("AWS S3 error code mismatch")).Fatal() return } successLogger(function, args, startTime).Info() } func testListObjects(s3Client *s3.S3) { startTime := time.Now() function := "testListObjects" bucket := randString(60, rand.NewSource(time.Now().UnixNano()), "aws-sdk-go-test-") object1 := "testObject1" object2 := "testObject2" expiry := 1 * time.Minute args := map[string]interface{}{ "bucketName": bucket, "objectName1": object1, "objectName2": object2, "expiry": expiry, } getKeys := func(objects []*s3.Object) []string { var rv []string for _, obj := range objects { rv = append(rv, *obj.Key) } return rv } _, err := s3Client.CreateBucket(&s3.CreateBucketInput{ Bucket: aws.String(bucket), }) if err != nil { failureLog(function, args, startTime, "", "AWS SDK Go CreateBucket Failed", err).Fatal() return } defer cleanup(s3Client, bucket, object1, function, args, startTime, true) defer cleanup(s3Client, bucket, object2, function, args, startTime, false) listInput := &s3.ListObjectsV2Input{ Bucket: aws.String(bucket), MaxKeys: aws.Int64(1000), Prefix: aws.String(""), } result, err := s3Client.ListObjectsV2(listInput) if err != nil { failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go listobjects expected to success but got %v", err), err).Fatal() return } if *result.KeyCount != 0 { failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go listobjects with prefix '' expected 0 key but got %v, %v", result.KeyCount, getKeys(result.Contents)), errors.New("AWS S3 key count mismatch")).Fatal() return } putInput1 := &s3.PutObjectInput{ Body: aws.ReadSeekCloser(strings.NewReader("filetoupload")), Bucket: aws.String(bucket), Key: aws.String(object1), } _, err = s3Client.PutObject(putInput1) if err != nil { failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to success but got %v", err), err).Fatal() return } putInput2 := &s3.PutObjectInput{ Body: aws.ReadSeekCloser(strings.NewReader("filetoupload")), Bucket: aws.String(bucket), Key: aws.String(object2), } _, err = s3Client.PutObject(putInput2) if err != nil { failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to success but got %v", err), err).Fatal() return } result, err = s3Client.ListObjectsV2(listInput) if err != nil { failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go listobjects expected to success but got %v", err), err).Fatal() return } if *result.KeyCount != 2 { failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go listobjects with prefix '' expected 2 key but got %v, %v", *result.KeyCount, getKeys(result.Contents)), errors.New("AWS S3 key count mismatch")).Fatal() return } successLogger(function, args, startTime).Info() } func main() { endpoint := os.Getenv("SERVER_ENDPOINT") accessKey := os.Getenv("ACCESS_KEY") secretKey := os.Getenv("SECRET_KEY") secure := os.Getenv("ENABLE_HTTPS") sdkEndpoint := "http://" + endpoint if secure == "1" { sdkEndpoint = "https://" + endpoint } creds := credentials.NewStaticCredentials(accessKey, secretKey, "") newSession := session.New() s3Config := &aws.Config{ Credentials: creds, Endpoint: aws.String(sdkEndpoint), Region: aws.String("us-east-1"), S3ForcePathStyle: aws.Bool(true), } // Create an S3 service object in the default region. s3Client := s3.New(newSession, s3Config) // Output to stdout instead of the default stderr log.SetOutput(os.Stdout) // create custom formatter mintFormatter := mintJSONFormatter{} // set custom formatter log.SetFormatter(&mintFormatter) // log Info or above -- success cases are Info level, failures are Fatal level log.SetLevel(log.InfoLevel) // execute tests testPresignedPutInvalidHash(s3Client) testListObjects(s3Client) }