-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsign-s3-object-url.go
75 lines (66 loc) · 2.34 KB
/
sign-s3-object-url.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package main
import (
"bytes"
"crypto/x509"
"encoding/pem"
"log"
"os"
"strconv"
// "strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudfront/sign"
"github.com/aws/aws-sdk-go/service/s3"
)
/**
* Step by step instructions at:
* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html
*
* @param objectKey The path and filename key of the uploaded object with no leading slash
* @return The signed URL for the object
*
* Required environment variables:
* CLOUDFRONT_PRIVATE_URL - The URL of the distribution sitting in front of the S3 PDF bucket
* CLOUDFRONT_KEY_PAIR_ID - The public key used to create signed URLs for cloudfront
* APP_KEYS_BUCKET_NAME - The name of the S3 bucket that contains private keys for signing URLs
* CLOUDFRONT_PRIVATE_KEY_OBJECT_NAME - The object key name of the private key for signing URLs
*
* Final URL format:
* <cloudfrontUrl>/<objectKey>? \
* Expires=<unixTimestamp>&
* Signature=<hashedAndSignedVersionOfPolicy>&
* Key-Pair-Id=<CloudfrontKeyPairId>
*/
func SignS3ObjectUrl(objectKey string) string {
baseURL := os.Getenv("CLOUDFRONT_PRIVATE_URL")
cloudfrontKeyPairId := os.Getenv("CLOUDFRONT_KEY_PAIR_ID")
// retrieve private key from s3 bucket
s3Service := s3.New(sess)
result, err := s3Service.GetObject(&s3.GetObjectInput {
Bucket: aws.String(os.Getenv("APP_KEYS_BUCKET_NAME")),
Key: aws.String(os.Getenv("CLOUDFRONT_PRIVATE_KEY_OBJECT_NAME")),
})
if err != nil {
log.Fatalf("Unable to download cloudfront private key from S3: %v", err)
}
// get the object as a string
buffer := new(bytes.Buffer)
buffer.ReadFrom(result.Body)
cloudfrontPrivateKey := buffer.String()
pem, _ := pem.Decode([]byte(cloudfrontPrivateKey))
rsaPrivateKey, _ := x509.ParsePKCS1PrivateKey(pem.Bytes)
// time.Time 15 minutes from now
expiryTime := time.Now().UTC().Add(time.Minute * time.Duration(15))
resource := baseURL + "/" + objectKey
newCannedPolicy := sign.NewCannedPolicy(resource, expiryTime)
// get b64 encoded signature
b64Signature, _, err := newCannedPolicy.Sign(rsaPrivateKey)
if (err != nil) {
log.Fatalln(err)
}
expiryString := strconv.FormatInt(expiryTime.Unix(), 10)
return resource +
"?Expires=" + expiryString +
"&Signature=" + string(b64Signature) +
"&Key-Pair-Id=" + cloudfrontKeyPairId
}