-
Notifications
You must be signed in to change notification settings - Fork 597
/
express_signer.go
109 lines (93 loc) · 3.71 KB
/
express_signer.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
package customizations
import (
"context"
"net/http"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
"github.com/aws/smithy-go/middleware"
)
const (
s3ExpressSignerVersion = "com.amazonaws.s3#sigv4express"
headerAmzSessionToken = "x-amz-s3session-token"
)
// adapts a v4 signer for S3Express
type s3ExpressSignerAdapter struct {
v4 v4.HTTPSigner
}
// SignHTTP performs S3Express signing on a request, which is identical to
// SigV4 signing save for an additional header containing the S3Express
// session token.
func (s *s3ExpressSignerAdapter) SignHTTP(ctx context.Context, credentials aws.Credentials, r *http.Request, payloadHash string, service string, region string, signingTime time.Time, optFns ...func(*v4.SignerOptions)) error {
r.Header.Set(headerAmzSessionToken, credentials.SessionToken)
optFns = append(optFns, func(o *v4.SignerOptions) {
o.DisableSessionToken = true
})
return s.v4.SignHTTP(ctx, credentials, r, payloadHash, service, region, signingTime, optFns...)
}
// adapts S3ExpressCredentialsProvider to the standard AWS
// CredentialsProvider interface
type s3ExpressCredentialsAdapter struct {
provider S3ExpressCredentialsProvider
bucket string
}
func (c *s3ExpressCredentialsAdapter) Retrieve(ctx context.Context) (aws.Credentials, error) {
return c.provider.Retrieve(ctx, c.bucket)
}
// S3ExpressSignHTTPRequestMiddleware signs S3 S3Express requests.
//
// This is NOT mutually exclusive with existing v4 or v4a signer handling on
// the stack itself, but only one handler will actually perform signing based
// on the provided signing version in the context.
type S3ExpressSignHTTPRequestMiddleware struct {
Credentials S3ExpressCredentialsProvider
Signer v4.HTTPSigner
LogSigning bool
}
// ID identifies S3ExpressSignHTTPRequestMiddleware.
func (*S3ExpressSignHTTPRequestMiddleware) ID() string {
return "S3ExpressSigning"
}
// HandleFinalize will sign the request if the S3Express signer has been
// selected.
func (m *S3ExpressSignHTTPRequestMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
) {
if GetSignerVersion(ctx) != s3ExpressSignerVersion {
return next.HandleFinalize(ctx, in)
}
mw := v4.NewSignHTTPRequestMiddleware(v4.SignHTTPRequestMiddlewareOptions{
CredentialsProvider: m.credentialsAdapter(ctx),
Signer: m.signerAdapter(),
LogSigning: m.LogSigning,
})
return mw.HandleFinalize(ctx, in, next)
}
func (m *S3ExpressSignHTTPRequestMiddleware) credentialsAdapter(ctx context.Context) aws.CredentialsProvider {
return &s3ExpressCredentialsAdapter{
provider: m.Credentials,
bucket: GetBucket(ctx),
}
}
func (m *S3ExpressSignHTTPRequestMiddleware) signerAdapter() v4.HTTPSigner {
return &s3ExpressSignerAdapter{v4: m.Signer}
}
type s3ExpressPresignerAdapter struct {
v4 v4.HTTPPresigner
}
// SignHTTP performs S3Express signing on a request, which is identical to
// SigV4 signing save for an additional header containing the S3Express
// session token.
func (s *s3ExpressPresignerAdapter) PresignHTTP(ctx context.Context, credentials aws.Credentials, r *http.Request, payloadHash string, service string, region string, signingTime time.Time, optFns ...func(*v4.SignerOptions)) (
string, http.Header, error,
) {
r.Header.Set(headerAmzSessionToken, credentials.SessionToken)
optFns = append(optFns, func(o *v4.SignerOptions) {
o.DisableSessionToken = true
})
return s.v4.PresignHTTP(ctx, credentials, r, payloadHash, service, region, signingTime, optFns...)
}
var (
_ aws.CredentialsProvider = &s3ExpressCredentialsAdapter{}
_ v4.HTTPSigner = &s3ExpressSignerAdapter{}
)