-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathsigv4.go
119 lines (109 loc) · 3.72 KB
/
sigv4.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package appsync
import (
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"log/slog"
"net/http"
"strconv"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
sdkv2_v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
sdkv1_v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
)
type sigv4 interface {
signHTTP(payload []byte) (http.Header, error)
signWS(payload []byte) (map[string]string, error)
}
type _signer struct {
sdkSigner any
region string
url string
creds *aws.Credentials
}
func (s *_signer) signHTTP(payload []byte) (http.Header, error) {
slog.Debug("signing http request", "payload", string(payload))
req, err := http.NewRequest("POST", s.url, bytes.NewBuffer(payload))
if err != nil {
slog.Error("error creating signing request", "error", err)
return nil, err
}
switch signer := s.sdkSigner.(type) {
case *sdkv1_v4.Signer:
slog.Debug("signing request using sdk v1")
_, err = signer.Sign(req, bytes.NewReader(payload), "appsync", s.region, time.Now())
if err != nil {
slog.Error("error signing request using sdk v1", "error", err)
return nil, err
}
case *sdkv2_v4.Signer:
slog.Debug("signing request using sdk v2")
hash := sha256.Sum256(payload)
if err := signer.SignHTTP(context.TODO(), *s.creds, req, hex.EncodeToString(hash[:]), "appsync", s.region, time.Now()); err != nil {
slog.Error("error signing request using sdk v2", "error", err)
return nil, err
}
default:
return http.Header{}, errors.New("unsupported signer")
}
return req.Header, nil
}
func (s *_signer) signWS(payload []byte) (map[string]string, error) {
slog.Debug("signing ws", "payload", string(payload))
url := s.url
if bytes.Equal(payload, []byte("{}")) {
url = url + "/connect"
}
slog.Debug("signing ws url", "url", url)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload))
if err != nil {
slog.Error("error creating request", "error", err)
return nil, err
}
req.Header.Add("accept", "application/json, text/javascript")
req.Header.Add("content-encoding", "amz-1.0")
req.Header.Add("content-type", "application/json; charset=UTF-8")
switch signer := s.sdkSigner.(type) {
case *sdkv1_v4.Signer:
slog.Debug("signing ws using sdk v1")
_, err = signer.Sign(req, bytes.NewReader(payload), "appsync", s.region, time.Now())
if err != nil {
slog.Error("error signing request", "error", err)
return nil, err
}
return map[string]string{
"accept": req.Header.Get("accept"),
"content-encoding": req.Header.Get("content-encoding"),
"content-type": req.Header.Get("content-type"),
"host": req.Host,
"x-amz-date": req.Header.Get("x-amz-date"),
"Authorization": req.Header.Get("Authorization"),
"X-Amz-Security-Token": req.Header.Get("X-Amz-Security-Token"),
}, nil
case *sdkv2_v4.Signer:
slog.Debug("signing ws using sdk v2")
hash := sha256.Sum256(payload)
if err := signer.SignHTTP(context.TODO(), *s.creds, req, hex.EncodeToString(hash[:]), "appsync", s.region, time.Now()); err != nil {
slog.Error("error signing request", "error", err)
return nil, err
}
headers := map[string]string{
"accept": req.Header.Get("accept"),
"content-encoding": req.Header.Get("content-encoding"),
"content-type": req.Header.Get("content-type"),
"content-length": strconv.FormatInt(req.ContentLength, 10),
"host": req.Host,
"x-amz-date": req.Header.Get("x-amz-date"),
"Authorization": req.Header.Get("Authorization"),
}
token := req.Header.Get("X-Amz-Security-Token")
if token != "" {
headers["X-Amz-Security-Token"] = token
}
slog.Debug("signed ws headers", "headers", headers)
return headers, nil
}
return map[string]string{}, errors.New("unsupported signer")
}