Skip to content

Instantly share code, notes, and snippets.

@sgswtky
Created June 15, 2018 02:10
Show Gist options
  • Save sgswtky/ccee5eefba65aedc1dd7817b72143118 to your computer and use it in GitHub Desktop.
Save sgswtky/ccee5eefba65aedc1dd7817b72143118 to your computer and use it in GitHub Desktop.
aws-sig-v4-s3-upload
package main
import (
"fmt"
"os"
"time"
"strings"
"crypto/hmac"
"encoding/hex"
"encoding/base64"
"crypto/sha256"
)
const (
region = "ap-northeast-1"
)
const (
// args
LOCAL_TARGET_FILE = iota + 1
ACCESS_KEY
SECRET_ACCESS_KEY
BUCKET
PUT_FILE_NAME
)
func main() {
if len(os.Args) != 6 {
fmt.Println("Argument is missing.")
os.Exit(1)
}
localTargetFile := os.Args[LOCAL_TARGET_FILE]
accessKey := os.Args[ACCESS_KEY]
secretAccessKey := os.Args[SECRET_ACCESS_KEY]
bucket := os.Args[BUCKET]
putFileName := os.Args[PUT_FILE_NAME]
location, _ := time.LoadLocation("UTC")
nowTime := time.Now().In(location)
date := nowTime.Format("20060102")
expiration := nowTime.Add(time.Minute * 10).Format(time.RFC3339)
xAmzAlgorithm := "AWS4-HMAC-SHA256"
xAmzCredential := fmt.Sprintf("%s/%s/%s/s3/aws4_request", accessKey, date, region)
xAmzDate := nowTime.Format("20060102T1504050700Z")
acl := "private"
policyDocument := fmt.Sprintf(strings.Join(strings.Split(getPolicyDocumentBase(), "\n"), ""),
expiration,
acl,
bucket,
putFileName,
xAmzAlgorithm,
xAmzCredential,
xAmzDate)
policyDocument = base64.StdEncoding.EncodeToString([]byte(policyDocument))
// https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/API/sig-v4-header-based-auth.html
// date
kDate := makeHmac([]byte("AWS4"+secretAccessKey), []byte(date))
// region
kRegion := makeHmac(kDate, []byte(region))
// service
kService := makeHmac(kRegion, []byte("s3"))
// signing
kCredential := makeHmac(kService, []byte("aws4_request"))
// signature
signatureBody := makeHmac(kCredential, []byte(policyDocument))
signature := hex.EncodeToString(signatureBody)
curl := fmt.Sprintf(`
curl -v -X POST \
-F acl="%s" \
-F key="%s" \
-F policy="%s" \
-F x-amz-algorithm="AWS4-HMAC-SHA256" \
-F x-amz-credential="%s" \
-F x-amz-date="%s" \
-F x-amz-signature="%s" \
-F x-amz-server-side-encryption="AES256" \
-F "file=@%s" \
https://%s.s3.amazonaws.com/`,
acl,
putFileName,
policyDocument,
xAmzCredential,
xAmzDate,
signature,
localTargetFile,
bucket)
fmt.Println(curl)
}
func getPolicyDocumentBase() string {
// https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
return `
{"expiration":"%s","conditions":[{"acl": "%s"},{"bucket":"%s"},["starts-with","$key","%s"],{"x-amz-algorithm":"%s"},{"x-amz-credential":"%s"},{"x-amz-date":"%s"},{"x-amz-server-side-encryption":"AES256"}]}
`
}
func makeHmac(key []byte, data []byte) []byte {
hash := hmac.New(sha256.New, key)
hash.Write(data)
return hash.Sum(nil)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment