1package main 2 3import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "time" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/service/s3" 12) 13 14// It's not clear from the docs what S3 does when versioning has been enabled, 15// then suspended, then you request a version ID that exists. 16// 17// Turns out it continues to work just fine. 18// 19// This script also revealed that a bucket that has never had versioning will 20// return empty strings for Status and MFADelete. 21type S300001GetVersionAfterVersioningSuspended struct{} 22 23func (t *S300001GetVersionAfterVersioningSuspended) Run(ctx *Context) error { 24 client := ctx.S3Client() 25 config := ctx.Config() 26 27 bucket := aws.String(config.BucketStandard()) 28 29 if err := ctx.EnsureVersioningEnabled(client, config.BucketStandard()); err != nil { 30 return err 31 } 32 33 // FIXME: defer delete object 34 35 key := fmt.Sprintf("%d/%s", time.Now().UnixNano(), ctx.RandString(32)) 36 37 var versions = map[string][]byte{} 38 39 for i := 0; i < 3; i++ { 40 body := ctx.RandBytes(32) 41 rs, err := client.PutObject(&s3.PutObjectInput{ 42 Key: aws.String(key), 43 Body: bytes.NewReader(body), 44 Bucket: bucket, 45 }) 46 if err != nil { 47 return err 48 } 49 50 ver := aws.StringValue(rs.VersionId) 51 if ver == "" { 52 return fmt.Errorf("missing version ID") 53 } 54 versions[ver] = body 55 } 56 57 if _, err := client.PutBucketVersioning(&s3.PutBucketVersioningInput{ 58 Bucket: bucket, 59 VersioningConfiguration: &s3.VersioningConfiguration{ 60 Status: aws.String("Suspended"), 61 }, 62 }); err != nil { 63 return err 64 } 65 66 { 67 vers, err := client.GetBucketVersioning(&s3.GetBucketVersioningInput{Bucket: bucket}) 68 if err != nil { 69 return err 70 } 71 status := aws.StringValue(vers.Status) 72 if status != "Suspended" { 73 return fmt.Errorf("unexpected status %q", status) 74 } 75 } 76 77 readCloseBody := func(rdr io.ReadCloser) ([]byte, error) { 78 defer rdr.Close() 79 return ioutil.ReadAll(rdr) 80 } 81 82 for ver, body := range versions { 83 rs, err := client.GetObject(&s3.GetObjectInput{ 84 Key: aws.String(key), 85 Bucket: bucket, 86 VersionId: aws.String(ver), 87 }) 88 if err != nil { 89 return err 90 } 91 rbody, err := readCloseBody(rs.Body) 92 if err != nil { 93 return err 94 } 95 96 if !bytes.Equal(body, rbody) { 97 return fmt.Errorf("version not equal") 98 } 99 } 100 101 return nil 102} 103