We announced
Creating Pre-Signed URLs for Amazon S3 Buckets
This Go example shows you how to obtain a pre-signed URL for an Amazon S3 bucket. You can download complete
versions of these example files from the aws-doc-sdk-examples
Scenario
In this example, a series of Go routines are used to obtain a pre-signed URL for an Amazon S3 bucket using either GetObject or a PUT operation. A pre-signed URL allows you to grant temporary access to users who don’t have permission to directly run AWS operations in your account. A pre-signed URL is signed with your credentials and can be used by any user.
Prerequisites
-
You have set up and configured the SDK.
-
You are familiar with pre-signed URLs. To learn more, see Uploading Objects Using Pre-Signed URLs in the Amazon S3 Developer Guide.
Generate a Pre-Signed URL for a GetObject Operation
To generate a pre-signed URL, use the Presign method on the
request
object. You must set an expiration value because the AWS SDK for Go doesn’t set one by
default.
The following example generates a pre-signed URL that enables you to temporarily share a file without making it public. Anyone with access to the URL can view the file.
package main import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "log" "time" ) // Downloads an item from an S3 Bucket // // Usage: // go run s3_download.go func main() { // Initialize a session in us-west-2 that the SDK will use to load // credentials from the shared credentials file ~/.aws/credentials. sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-west-2")}, ) // Create S3 service client svc := s3.New(sess) req, _ := svc.GetObjectRequest(&s3.GetObjectInput{ Bucket: aws.String("amzn-s3-demo-bucket"), Key: aws.String("myKey"), }) urlStr, err := req.Presign(15 * time.Minute) if err != nil { log.Println("Failed to sign request", err) } log.Println("The URL is", urlStr) }
If the SDK has not retrieved your credentials before calling Presign
, it will get them
to generate the pre-signed URL.
Generate a Pre-Signed URL for an Amazon S3 PUT Operation with a Specific Payload
You can generate a pre-signed URL for a PUT operation that checks whether users upload the correct content. When the SDK pre-signs a request, it computes the checksum of the request body and generates an MD5 checksum that is included in the pre-signed URL. Users must upload the same content that produces the same MD5 checksum generated by the SDK; otherwise, the operation fails. This is not the Content-MD5, but the signature. To enforce Content-MD5, simply add the header to the request.
The following example adds a Body
field to generate a pre-signed PUT operation that
requires a specific payload to be uploaded by users.
package main import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "log" "strings" "time" ) func main() { // Initialize a session in us-west-2 that the SDK will use to load // credentials from the shared credentials file ~/.aws/credentials. sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-west-2")}, ) // Create S3 service client svc := s3.New(sess) req, _ := svc.PutObjectRequest(&s3.PutObjectInput{ Bucket: aws.String("amzn-s3-demo-bucket"), Key: aws.String("myKey"), Body: strings.NewReader("EXPECTED CONTENTS"), }) str, err := req.Presign(15 * time.Minute) log.Println("The URL is:", str, " err:", err) }
If you omit the Body
field, users can write any contents to the given object.
The following example shows the enforcing of Content-MD5.
package main import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "encoding/base64" "fmt" "crypto/md5" "strings" "time" "net/http" ) // Downloads an item from an S3 Bucket in the region configured in the shared config // or AWS_REGION environment variable. // // Usage: // go run s3_download.go func main() { h := md5.New() content := strings.NewReader("") content.WriteTo(h) // Initialize a session in us-west-2 that the SDK will use to load // credentials from the shared credentials file ~/.aws/credentials. sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-west-2")}, ) // Create S3 service client svc := s3.New(sess) resp, _ := svc.PutObjectRequest(&s3.PutObjectInput{ Bucket: aws.String("amzn-s3-demo-bucket"), Key: aws.String("testKey"), }) md5s := base64.StdEncoding.EncodeToString(h.Sum(nil)) resp.HTTPRequest.Header.Set("Content-MD5", md5s) url, err := resp.Presign(15 * time.Minute) if err != nil { fmt.Println("error presigning request", err) return } req, err := http.NewRequest("PUT", url, strings.NewReader("")) req.Header.Set("Content-MD5", md5s) if err != nil { fmt.Println("error creating request", url) return } defClient, err := http.DefaultClient.Do(req) fmt.Println(defClient, err) }