File: express_signer.go

package info (click to toggle)
golang-github-aws-aws-sdk-go-v2 1.24.1-2~bpo12%2B1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-backports
  • size: 554,032 kB
  • sloc: java: 15,941; makefile: 419; sh: 175
file content (109 lines) | stat: -rw-r--r-- 3,794 bytes parent folder | download | duplicates (6)
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{}
)