package main import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "fmt" "net/http" "strconv" "strings" "time" "unicode/utf8" "github.com/google/uuid" ) type FlexHeader struct { UserAgent string `header:"User-Agent"` Host string `header:"Host"` Connection string `header:"Connection"` Encoding string `header:"Accept-Encoding"` ContentType string `header:"Content-Type"` RequestId string `header:"X-Amzn-RequestId"` ClientTime string `header:"X-Flex-Client-Time"` Instance string `header:"x-flex-instance-id"` AccessToken string `header:"x-amz-access-token"` Authorization string `header:"Authorization,omitempty"` Date string `header:"X-Amz-Date,omitempty"` } var ( FlexHead = new(FlexHeader) FlexClient = &http.Client{} ) func (h *FlexHeader) Setup() { h.UserAgent = api.Headers.Main h.Connection = "Keep-Alive" h.Encoding = "gzip" h.ContentType = "application/json" h.Host = "flex-capacity-na.amazon.com" h.Instance = api.Headers.Instance h.AccessToken = bearer.Tokens.Bearer.AccessToken } func (h *FlexHeader) Auth(method string, path string, host string) (head http.Header) { h.Host = host uuid, _ := uuid.NewRandom() h.RequestId = uuid.String() timenow := time.Now() h.ClientTime = strconv.FormatInt(timenow.UnixNano()/1000000, 10) h.Date = timenow.Format("20060102T150405Z") filteredHeaders := []string{"Host", "x-amz-access-token", "X-Amz-Date", "X-Amzn-RequestId"} canonicalRequestB := strings.ToLower(strings.Join(filteredHeaders, ";")) keylist := make([]string, len(filteredHeaders)) for pos, hkey := range filteredHeaders { switch hkey { case "Host": keylist[pos] = fmt.Sprintf("%s:%s\n", "host", h.Host) case "x-amz-access-token": keylist[pos] = fmt.Sprintf("%s:%s\n", "x-amz-access-token", h.AccessToken) case "X-Amz-Date": keylist[pos] = fmt.Sprintf("%s:%s\n", "x-amz-date", h.Date) case "X-Amzn-RequestId": keylist[pos] = fmt.Sprintf("%s:%s\n", "x-amzn-requestid", h.RequestId) } } canonicalRequestA := strings.Join([]string{method, path, strings.Join(keylist, ""), canonicalRequestB}, "\n") canhash := sha256.New() canhash.Write([]byte(canonicalRequestA)) stringToSign := strings.Join([]string{"RABBIT3-HMAC-SHA256", h.Date, hex.EncodeToString(canhash.Sum(nil))}, "\n") key := []byte("RABBIT" + Reverse(h.AccessToken)) msgs := [3]string{h.Date[:8], "rabbit_request", stringToSign} for _, msg := range msgs { hash := hmac.New(sha256.New, key) hash.Write([]byte(msg)) key = hash.Sum(nil) } h.Authorization = "RABBIT3-HMAC-SHA256 SignedHeaders=" + canonicalRequestB + ",Signature=" + hex.EncodeToString(key) head = http.Header{ "Authorization": []string{h.Authorization}, "User-Agent": []string{h.UserAgent}, "Host": []string{h.Host}, "Connection": []string{h.Connection}, "Accept-Encoding": []string{h.Encoding}, "Content-Type": []string{h.ContentType}, "X-Amzn-RequestId": []string{h.RequestId}, "X-Flex-Client-Time": []string{h.ClientTime}, "x-flex-instance-id": []string{h.Instance}, "x-amz-access-token": []string{h.AccessToken}, "X-Amz-Date": []string{h.Date}, } return } func Reverse(s string) string { size := len(s) buf := make([]byte, size) for start := 0; start < size; { r, n := utf8.DecodeRuneInString(s[start:]) start += n utf8.EncodeRune(buf[size-start:], r) } return string(buf) }