Package: v4

import "../ibm-cos-sdk-go-v2/aws/signer/v4"

Overview

Package v4 implements the AWS signature version 4 algorithm (commonly known as SigV4).

For more information about SigV4, see Signing AWS API requests in the IAM user guide.

While this implementation CAN work in an external context, it is developed primarily for SDK use and you may encounter fringe behaviors around header canonicalization.

Pre-escaping a request URI

AWS v4 signature validation requires that the canonical string’s URI path component must be the escaped form of the HTTP request’s path.

The Go HTTP client will perform escaping automatically on the HTTP request. This may cause signature validation errors because the request differs from the URI path or query from which the signature was generated.

Because of this, we recommend that you explicitly escape the request when using this signer outside of the SDK to prevent possible signature mismatch. This can be done by setting URL.Opaque on the request. The signer will prefer that value, falling back to the return of URL.EscapedPath if unset.

When setting URL.Opaque you must do so in the form of:

"///" // e.g. "//example.com/some/path"

The leading “//” and hostname are required or the escaping will not work correctly.

The TestStandaloneSign unit test provides a complete example of using the signer outside of the SDK and pre-escaping the URI path.

Constants

const Version = readonly

Version of signing v4

Value:

"SigV4"

Type Summary collapse

Interface Summary collapse

Function Summary collapse

Type Details

PresignHTTPRequestMiddlewareOptions struct

PresignHTTPRequestMiddlewareOptions is the options for the PresignHTTPRequestMiddleware middleware.

Structure Fields:

CredentialsProvider aws.CredentialsProvider
Presigner HTTPPresigner
LogSigning bool

PresignedHTTPRequest struct

PresignedHTTPRequest provides the URL and signed headers that are included in the presigned URL.

Structure Fields:

URL string
Method string
SignedHeader http.Header

SignHTTPRequestMiddlewareOptions struct

SignHTTPRequestMiddlewareOptions is the configuration options for [SignHTTPRequestMiddleware].

Deprecated: [SignHTTPRequestMiddleware] is deprecated.

Structure Fields:

CredentialsProvider aws.CredentialsProvider
Signer HTTPSigner
LogSigning bool

SignerOptions struct

SignerOptions is the SigV4 Signer options.

Structure Fields:

DisableHeaderHoisting bool

Disables the Signer’s moving HTTP header key/value pairs from the HTTP request header to the request’s query string. This is most commonly used with pre-signed requests preventing headers from being added to the request’s query string.

DisableURIPathEscaping bool

Disables the automatic escaping of the URI path of the request for the siganture’s canonical string’s path. For services that do not need additional escaping then use this to disable the signer escaping the path.

S3 is an example of a service that does not need additional escaping.

docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html

Logger logging.Logger

The logger to send log messages to.

LogSigning bool

Enable logging of signed requests. This will enable logging of the canonical request, the string to sign, and for presigning the subsequent presigned URL.

DisableSessionToken bool

Disables setting the session token on the request as part of signing through X-Amz-Security-Token. This is needed for variations of v4 that present the token elsewhere.

Function Details

func AddComputePayloadSHA256Middleware(stack *middleware.Stack) error

AddComputePayloadSHA256Middleware adds computePayloadSHA256 to the operation middleware stack



137
138
139
// File 'aws/signer/v4/middleware.go', line 137

func AddComputePayloadSHA256Middleware(stack *middleware.Stack) error { return stack.Finalize.Insert(&ComputePayloadSHA256{}, "ResolveEndpointV2", middleware.After) }

func AddContentSHA256HeaderMiddleware(stack *middleware.Stack) error

AddContentSHA256HeaderMiddleware adds ContentSHA256Header to the operation middleware stack



212
213
214
// File 'aws/signer/v4/middleware.go', line 212

func AddContentSHA256HeaderMiddleware(stack *middleware.Stack) error { return stack.Finalize.Insert(&ContentSHA256Header{}, computePayloadHashMiddlewareID, middleware.After) }

func AddStreamingEventsPayload(stack *middleware.Stack) error

AddStreamingEventsPayload adds the streamingEventsPayload middleware to the stack.



342
343
344
// File 'aws/signer/v4/middleware.go', line 342

func AddStreamingEventsPayload(stack *middleware.Stack) error { return stack.Finalize.Add(&StreamingEventsPayload{}, middleware.Before) }

func AddUnsignedPayloadMiddleware(stack *middleware.Stack) error

AddUnsignedPayloadMiddleware adds unsignedPayload to the operation middleware stack



104
105
106
// File 'aws/signer/v4/middleware.go', line 104

func AddUnsignedPayloadMiddleware(stack *middleware.Stack) error { return stack.Finalize.Insert(&UnsignedPayload{}, "ResolveEndpointV2", middleware.After) }

func GetPayloadHash(ctx context.Context) (v string)

GetPayloadHash retrieves the payload hash to use for signing

Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues to clear all stack values.



408
409
410
411
// File 'aws/signer/v4/middleware.go', line 408

func GetPayloadHash(ctx context.Context) (v string) { v, _ = middleware.GetStackValue(ctx, payloadHashKey{}).(string) return v }

func GetSignedRequestSignature(r *http.Request) ([]byte, error)

GetSignedRequestSignature attempts to extract the signature of the request. Returning an error if the request is unsigned, or unable to extract the signature.



370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
// File 'aws/signer/v4/middleware.go', line 370

func GetSignedRequestSignature(r *http.Request) ([]byte, error) { const authHeaderSignatureElem = "Signature=" if auth := r.Header.Get(authorizationHeader); len(auth) != 0 { ps := strings.Split(auth, ",") for _, p := range ps { p = strings.TrimSpace(p) if idx := strings.Index(p, authHeaderSignatureElem); idx >= 0 { sig := p[len(authHeaderSignatureElem):] if len(sig) == 0 { return nil, fmt.Errorf("invalid request signature authorization header") } return hex.DecodeString(sig) } } } if sig := r.URL.Query().Get("X-Amz-Signature"); len(sig) != 0 { return hex.DecodeString(sig) } return nil, fmt.Errorf("request not signed") }

func NewSigner(optFns ...func(signer *SignerOptions)) *Signer

NewSigner returns a new SigV4 Signer



118
119
120
121
122
123
124
125
126
// File 'aws/signer/v4/v4.go', line 118

func NewSigner(optFns ...func(signer *SignerOptions)) *Signer { options := SignerOptions{} for _, fn := range optFns { fn(&options) } return &Signer{options: options, keyDerivator: v4Internal.NewSigningKeyDeriver()} }

func NewStreamSigner(credentials aws.Credentials, service, region string, seedSignature []byte, optFns ...func(*StreamSignerOptions)) *StreamSigner

NewStreamSigner returns a new AWS EventStream protocol signer.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// File 'aws/signer/v4/stream.go', line 34

func NewStreamSigner(credentials aws.Credentials, service, region string, seedSignature []byte, optFns ...func(*StreamSignerOptions)) *StreamSigner { o := StreamSignerOptions{} for _, fn := range optFns { fn(&o) } return &StreamSigner{ options: o, credentials: credentials, service: service, region: region, signingKeyDeriver: v4Internal.NewSigningKeyDeriver(), prevSignature: seedSignature, } }

func RemoveComputePayloadSHA256Middleware(stack *middleware.Stack) error

RemoveComputePayloadSHA256Middleware removes computePayloadSHA256 from the operation middleware stack



143
144
145
146
// File 'aws/signer/v4/middleware.go', line 143

func RemoveComputePayloadSHA256Middleware(stack *middleware.Stack) error { _, err := stack.Finalize.Remove(computePayloadHashMiddlewareID) return err }

func RemoveContentSHA256HeaderMiddleware(stack *middleware.Stack) error

RemoveContentSHA256HeaderMiddleware removes contentSHA256Header middleware from the operation middleware stack



218
219
220
221
// File 'aws/signer/v4/middleware.go', line 218

func RemoveContentSHA256HeaderMiddleware(stack *middleware.Stack) error { _, err := stack.Finalize.Remove((*ContentSHA256Header)(nil).ID()) return err }

func SetPayloadHash(ctx context.Context, hash string) context.Context

SetPayloadHash sets the payload hash to be used for signing the request

Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues to clear all stack values.



417
418
419
// File 'aws/signer/v4/middleware.go', line 417

func SetPayloadHash(ctx context.Context, hash string) context.Context { return middleware.WithStackValue(ctx, payloadHashKey{}, hash) }

func SwapComputePayloadSHA256ForUnsignedPayloadMiddleware(stack *middleware.Stack) error

SwapComputePayloadSHA256ForUnsignedPayloadMiddleware replaces the ComputePayloadSHA256 middleware with the UnsignedPayload middleware.

Use this to disable computing the Payload SHA256 checksum and instead use UNSIGNED-PAYLOAD for the SHA256 value.



201
202
203
204
// File 'aws/signer/v4/middleware.go', line 201

func SwapComputePayloadSHA256ForUnsignedPayloadMiddleware(stack *middleware.Stack) error { _, err := stack.Finalize.Swap(computePayloadHashMiddlewareID, &UnsignedPayload{}) return err }

func UseDynamicPayloadSigningMiddleware(stack *middleware.Stack) error

UseDynamicPayloadSigningMiddleware swaps the compute payload sha256 middleware with a resolver middleware that switches between unsigned and signed payload based on TLS state for request. This middleware should not be used for AWS APIs that do not support unsigned payload signing auth. By default, SDK uses this middleware for known AWS APIs that support such TLS based auth selection .

Usage example - S3 PutObject API allows unsigned payload signing auth usage when TLS is enabled, and uses this middleware to dynamically switch between unsigned and signed payload based on TLS state for request.



60
61
62
63
// File 'aws/signer/v4/middleware.go', line 60

func UseDynamicPayloadSigningMiddleware(stack *middleware.Stack) error { _, err := stack.Finalize.Swap(computePayloadHashMiddlewareID, &dynamicPayloadSigningMiddleware{}) return err }