Files
flex-account-management/auth_header.go

106 lines
3.4 KiB
Go
Raw Normal View History

2019-02-14 09:39:45 -07:00
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)
}