| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- package v4a
- import (
- "context"
- "fmt"
- "net/http"
- "time"
- awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
- v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
- "github.com/aws/aws-sdk-go-v2/internal/sdk"
- "github.com/aws/smithy-go/middleware"
- smithyHTTP "github.com/aws/smithy-go/transport/http"
- )
- // HTTPPresigner is an interface to a SigV4a signer that can sign create a
- // presigned URL for a HTTP requests.
- type HTTPPresigner interface {
- PresignHTTP(
- ctx context.Context, credentials Credentials, r *http.Request,
- payloadHash string, service string, regionSet []string, signingTime time.Time,
- optFns ...func(*SignerOptions),
- ) (url string, signedHeader http.Header, err error)
- }
- // PresignHTTPRequestMiddlewareOptions is the options for the PresignHTTPRequestMiddleware middleware.
- type PresignHTTPRequestMiddlewareOptions struct {
- CredentialsProvider CredentialsProvider
- Presigner HTTPPresigner
- LogSigning bool
- }
- // PresignHTTPRequestMiddleware provides the Finalize middleware for creating a
- // presigned URL for an HTTP request.
- //
- // Will short circuit the middleware stack and not forward onto the next
- // Finalize handler.
- type PresignHTTPRequestMiddleware struct {
- credentialsProvider CredentialsProvider
- presigner HTTPPresigner
- logSigning bool
- }
- // NewPresignHTTPRequestMiddleware returns a new PresignHTTPRequestMiddleware
- // initialized with the presigner.
- func NewPresignHTTPRequestMiddleware(options PresignHTTPRequestMiddlewareOptions) *PresignHTTPRequestMiddleware {
- return &PresignHTTPRequestMiddleware{
- credentialsProvider: options.CredentialsProvider,
- presigner: options.Presigner,
- logSigning: options.LogSigning,
- }
- }
- // ID provides the middleware ID.
- func (*PresignHTTPRequestMiddleware) ID() string { return "PresignHTTPRequest" }
- // HandleFinalize will take the provided input and create a presigned url for
- // the http request using the SigV4 presign authentication scheme.
- func (s *PresignHTTPRequestMiddleware) HandleFinalize(
- ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler,
- ) (
- out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
- ) {
- req, ok := in.Request.(*smithyHTTP.Request)
- if !ok {
- return out, metadata, &SigningError{
- Err: fmt.Errorf("unexpected request middleware type %T", in.Request),
- }
- }
- httpReq := req.Build(ctx)
- if !hasCredentialProvider(s.credentialsProvider) {
- out.Result = &v4.PresignedHTTPRequest{
- URL: httpReq.URL.String(),
- Method: httpReq.Method,
- SignedHeader: http.Header{},
- }
- return out, metadata, nil
- }
- signingName := awsmiddleware.GetSigningName(ctx)
- signingRegion := awsmiddleware.GetSigningRegion(ctx)
- payloadHash := v4.GetPayloadHash(ctx)
- if len(payloadHash) == 0 {
- return out, metadata, &SigningError{
- Err: fmt.Errorf("computed payload hash missing from context"),
- }
- }
- credentials, err := s.credentialsProvider.RetrievePrivateKey(ctx)
- if err != nil {
- return out, metadata, &SigningError{
- Err: fmt.Errorf("failed to retrieve credentials: %w", err),
- }
- }
- u, h, err := s.presigner.PresignHTTP(ctx, credentials,
- httpReq, payloadHash, signingName, []string{signingRegion}, sdk.NowTime(),
- func(o *SignerOptions) {
- o.Logger = middleware.GetLogger(ctx)
- o.LogSigning = s.logSigning
- })
- if err != nil {
- return out, metadata, &SigningError{
- Err: fmt.Errorf("failed to sign http request, %w", err),
- }
- }
- out.Result = &v4.PresignedHTTPRequest{
- URL: u,
- Method: httpReq.Method,
- SignedHeader: h,
- }
- return out, metadata, nil
- }
|