Documentation
¶
Overview ¶
Package sigv4 implements AWS Signature Version 4 (sigv4) signer. See authoritative documentation at https://docs.aws.amazon.com/IAM/latest/UserGuide/signing-elements.html for details.
The sigv4 algorithm is briefly described here.
Step 1: make a canonical request string in the format "<METHOD>\n<URI>\n<QUERY>\n<HEADERS>\n<SIGNED_HEADERS>\n<PAYLOAD_HASH>".
- METHOD: HTTP method in upper case.
- URI: the URL path component (between host and query), such as "/foo/bar". It must be URI-encoded. Use "/" if this component is empty.
- QUERY: the URL query component (after the first "?"), such as "Foo=A&Bar=B". For each key-value pair, reserved characters (including space) in both name and value must be percent-encoded. If value is empty, it should end with the "=" character, such as "Foo=". Lastly, sort by key name. If there are multiple key-value pairs with the same key name, they are sorted by their values. Use an empty string if there is no query component.
- HEADERS: for each header in request that should be protected by the signature, its name and value, followed by newline ("\n"). Header names must be in lower-case and sorted. Values are separated from its header name by ":". Multiple values must be comma separated, with leading and trailing spaces removed. Multiple spaces must be replaced with single space. The "host" header (or ":authority" if HTTP/2) must be included. If the request contains any header with "x-amz-" prefix, they must be included as well. Do not include "authorization" or "x-amzn-trace-id". All other headers are optional.
- SIGNED_HEADERS: semi-colon (";") delimited list of header names in HEADERS. Like HEADERS, it must be sorted and in lower-case.
- PAYLOAD_HASH: the value of hex(sha256(BODY)), where BODY is HTTP request body content. If HTTP request body is empty, use the hash value of an empty string.
Step 2: calculate hex(sha256(CANON_REQ_STR)), where CANON_REQ_STR is result of step 1.
Step 3: calculate string to sign "<ALGO>\n<TIMESTAMP>\n<CRED_SCOPE>\n<HASH>", where:
- ALGO: hardcoded AWS4-HMAC-SHA256
- TIMESTAMP: ISO8601 format time
- CRED_SCOPE: "<YYYYMMDD>/<region>/<service>/aws4_request", where "<YYYYMMDD>" is date portion of TIMESTAMP
- HASH: value from step 2
Step 4: calculate signature "<sig>" per pseudo code here:
// Secret is user secret key // Date is YYYYMMDD date from CRED_SCOPE in step 3 hDate = hmacsha256("AWS4"+Secret, Date) // region and service are the same values in CRED_SCOPE hRegion = hmacsha256(hDate, Region) hService = hmacsha256(hRegion, Service) hSig = hmacsha256(hService, "aws4_request") // StringToSign is value from step 3 // sig is the final result for this step sig = hex(hmacsha256(hSig, StringToSign))
Step 5: *either* add signature to request header or query string:
- Header: add header "Authorization: AWS4-HMAC-SHA256 Credential=<ACCESS_ID>/<CRED_SCOPE>, SignedHeaders=<SIGNED_HEADERS>, Signature=<SIG>"
- Query string: add these query parameters: "X-Amz-Algorithm=AWS4-HMAC-SHA256", "X-Amz-Credential=<ACCESS_ID>/<CRED_SCOPE>", "X-Amz-Date=<TIMESTAMP>", "X-Amz-SignedHeaders=<SIGNED_HEADERS>", "X-Amz-Signature=<SIG>"
Index ¶
Constants ¶
const ( // SigningAlgorithm is the name of the algorithm used in this package. SigningAlgorithm = "AWS4-HMAC-SHA256" // EmptyStringSHA256 is the hex encoded sha256 value of an empty string. EmptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855` // UnsignedPayload indicates that the request payload body is unsigned. UnsignedPayload = "UNSIGNED-PAYLOAD" // AmzAlgorithmKey indicates the signing algorithm. AmzAlgorithmKey = "X-Amz-Algorithm" // AmzSecurityTokenKey indicates the security token to be used with temporary // credentials. AmzSecurityTokenKey = "X-Amz-Security-Token" // AmzDateKey is the UTC timestamp for the request in the format YYYYMMDD'T'HHMMSS'Z'. AmzDateKey = "X-Amz-Date" // AmzCredentialKey is the access key ID and credential scope. AmzCredentialKey = "X-Amz-Credential" // AmzSignedHeadersKey is the set of headers signed for the request. AmzSignedHeadersKey = "X-Amz-SignedHeaders" // AmzSignatureKey is the query parameter to store the SigV4 signature. AmzSignatureKey = "X-Amz-Signature" // TimeFormat is the time format to be used in the X-Amz-Date header or query // parameter. TimeFormat = "20060102T150405Z" // ShortTimeFormat is the shorten time format used in the credential scope. ShortTimeFormat = "20060102" // ContentSHAKey is the SHA256 of request body. ContentSHAKey = "X-Amz-Content-Sha256" // StreamingEventsPayload indicates that the request payload body is a signed // event stream. StreamingEventsPayload = "STREAMING-AWS4-HMAC-SHA256-EVENTS" )
Signature Version 4 (SigV4) Constants
Variables ¶
var ErrInvalidOption = errors.New("cannot apply option to HTTPSigner")
ErrInvalidOption means the option parameter is incompatible with the HTTPSigner.
Functions ¶
Types ¶
type HTTPSigner ¶
type HTTPSigner interface { // Sign AWS v4 requests with the provided payload hash, service name, region // the request is made to, and time the request is signed at. Set sigtime // to the future to create a request that cannot be used until the future time. // // payloadHash is the hex encoded SHA-256 hash of the request payload, and must // not be empty, even if the request has no payload (aka body). If the request // has no payload, use the hex encoded SHA-256 of an empty string, or the constant // EmptyStringSHA256. You can use the utility function ContentSHA256Sum to // calculate the hash of a http.Request body. // // Some services such as Amazon S3 accept alternative values for the payload // hash, such as "UNSIGNED-PAYLOAD" for requests where the body will not be // protected by sigv4. See https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html. // // Sign differs from Presign in that it will sign the request using HTTP headers. // The passed in request r will be modified in place: modified fields include // r.Host and r.Header. Sign(r *http.Request, payloadHash string, sigtime Time) error // Presign is like Sign, but does not modify request r. It returns a copy of // r.URL with additional query parameters that contains signing information. // The URL can be used to recreate an authenticated request without specifying // headers. It also returns http.Header as a second result, which must be // included in the reconstructed request. // // Header hoisting: use WithHeaderHoisting option function to specify whether // headers in request r should be added as query parameters. Some headers cannot // be hoisted, and are returned as the second result. // // Presign will not set the expires time of the presigned request automatically. // To specify the expire duration for a request, add the "X-Amz-Expires" query // parameter on the request with the value as the duration in seconds the // presigned URL should be considered valid for. This parameter is not used // by all AWS services, and is most notable used by Amazon S3 APIs. // // expires := 20*time.Minute // query := req.URL.Query() // query.Set("X-Amz-Expires", strconv.FormatInt(int64(expires/time.Second), 10) // req.URL.RawQuery = query.Encode() Presign(r *http.Request, payloadHash string, sigtime Time) (*url.URL, http.Header, error) }
HTTPSigner is an AWS SigV4 signer that can sign HTTP requests.
type HTTPSignerOption ¶
type HTTPSignerOption func(HTTPSigner) error
HTTPSignerOption is an option parameter for HTTPSigner constructor function.
func WithCredential ¶
func WithCredential(accessKey, secret, sessionToken string) HTTPSignerOption
WithCredential sets HTTPSigner credential fields.
func WithEscapeURLPath ¶
func WithEscapeURLPath(enable bool) HTTPSignerOption
WithEscapeURLPath specifies whether HTTPSigner automatically escapes URL paths. Default is enabled.
func WithHeaderHoisting ¶
func WithHeaderHoisting(enable bool) HTTPSignerOption
WithHeaderHoisting specifies whether HTTPSigner automatically hoist headers. Default is enabled.
func WithRegionService ¶
func WithRegionService(region, service string) HTTPSignerOption
WithRegionService sets HTTPSigner region and service fields.
type Time ¶
Time wraps time.Time to cache its string format result.
func (*Time) ShortTimeFormat ¶
ShortTimeFormat provides a time formatted in short time format.
func (*Time) TimeFormat ¶
TimeFormat provides a time formatted in the X-Amz-Date format.