mirror of
https://github.com/qdm12/ddns-updater.git
synced 2026-03-31 06:24:00 -04:00
94 lines
2.5 KiB
Go
94 lines
2.5 KiB
Go
package route53
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
route53Domain = "route53.amazonaws.com"
|
|
dateTimeFormat = "20060102T150405Z"
|
|
dateFormat = "20060102"
|
|
)
|
|
|
|
// signer implements the signature v4 header based to upsert route53 domains
|
|
// https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
|
|
type signer struct {
|
|
accessKey string
|
|
secretkey string
|
|
region string
|
|
service string
|
|
signatureVersion string
|
|
}
|
|
|
|
func (s *signer) sign(method, urlPath string, payload []byte, date time.Time) (
|
|
headerValue string,
|
|
) {
|
|
credentialScope := fmt.Sprintf("%s/%s/%s/%s", date.Format(dateFormat),
|
|
s.region, s.service, s.signatureVersion)
|
|
credential := fmt.Sprintf("%s/%s", s.accessKey, credentialScope)
|
|
const signedHeaders = "content-type;host"
|
|
canonicalRequest := buildCanonicalRequest(method, urlPath, signedHeaders, payload)
|
|
stringToSign := buildStringToSign(date, canonicalRequest, credentialScope)
|
|
signingKey := s.buildPrivateKey(date)
|
|
signature := hmacSha256Sum([]byte(signingKey), []byte(stringToSign))
|
|
signatureString := hex.EncodeToString(signature)
|
|
return fmt.Sprintf("AWS4-HMAC-SHA256 Credential=%s,SignedHeaders=%s,Signature=%s",
|
|
credential, signedHeaders, signatureString)
|
|
}
|
|
|
|
func buildCanonicalRequest(method, path, headers string, payload []byte) (
|
|
canonicalRequest string,
|
|
) {
|
|
canonicalHeaders := "content-type:application/xml\nhost:" + route53Domain + "\n"
|
|
const canonicalQuery = "" // no query arg used
|
|
payloadHashDigest := hex.EncodeToString(sha256Sum(payload))
|
|
canonicalRequest = strings.Join([]string{
|
|
strings.ToUpper(method),
|
|
path,
|
|
canonicalQuery,
|
|
canonicalHeaders,
|
|
headers,
|
|
payloadHashDigest,
|
|
}, "\n")
|
|
return canonicalRequest
|
|
}
|
|
|
|
func buildStringToSign(date time.Time,
|
|
canonicalRequest, credentialScope string,
|
|
) string {
|
|
return "AWS4-HMAC-SHA256\n" +
|
|
date.Format(dateTimeFormat) + "\n" +
|
|
credentialScope + "\n" +
|
|
hex.EncodeToString(sha256Sum([]byte(canonicalRequest)))
|
|
}
|
|
|
|
func (s *signer) buildPrivateKey(date time.Time) string {
|
|
signingKey := []byte("AWS4" + s.secretkey)
|
|
for _, value := range [][]byte{
|
|
[]byte(date.Format(dateFormat)),
|
|
[]byte(s.region),
|
|
[]byte(s.service),
|
|
[]byte(s.signatureVersion),
|
|
} {
|
|
signingKey = hmacSha256Sum(signingKey, value)
|
|
}
|
|
return string(signingKey)
|
|
}
|
|
|
|
func sha256Sum(d []byte) []byte {
|
|
hasher := sha256.New()
|
|
hasher.Write(d)
|
|
return hasher.Sum(nil)
|
|
}
|
|
|
|
func hmacSha256Sum(key, value []byte) []byte {
|
|
hasher := hmac.New(sha256.New, key)
|
|
hasher.Write(value)
|
|
return hasher.Sum(nil)
|
|
}
|