Stability | experimental |
---|---|
Maintainer | Lars Kuhtz <lars@alephcloud.com> |
Safe Haskell | None |
AWS Signature Version 4
API Version: 1.0
http://docs.aws.amazon.com/general/1.0/gr/signature-version-4.html
- data GeneralVersion = GeneralVersion_1_0
- generalVersionToText :: IsString a => GeneralVersion -> a
- parseGeneralVersion :: CharParsing m => m GeneralVersion
- signatureVersion :: IsString a => a
- data SignatureV4Credentials = SignatureV4Credentials {
- sigV4AccessKeyId :: ByteString
- sigV4SecretAccessKey :: ByteString
- sigV4SigningKeys :: IORef [SigV4Key]
- newCredentials :: (Functor m, MonadIO m) => ByteString -> ByteString -> m SignatureV4Credentials
- signPostRequest :: SignatureV4Credentials -> Region -> ServiceNamespace -> UTCTime -> Method -> UriPath -> UriQuery -> RequestHeaders -> ByteString -> Either String RequestHeaders
- signGetRequest :: SignatureV4Credentials -> Region -> ServiceNamespace -> UTCTime -> Method -> UriPath -> UriQuery -> RequestHeaders -> ByteString -> Either String UriQuery
- signPostRequestIO :: SignatureV4Credentials -> Region -> ServiceNamespace -> UTCTime -> Method -> UriPath -> UriQuery -> RequestHeaders -> ByteString -> IO (Either String RequestHeaders)
- signGetRequestIO :: SignatureV4Credentials -> Region -> ServiceNamespace -> UTCTime -> Method -> UriPath -> UriQuery -> RequestHeaders -> ByteString -> IO (Either String UriQuery)
- data AuthorizationInfo = AuthorizationInfo {}
- authorizationInfo :: SignatureV4Credentials -> CredentialScope -> SignedHeaders -> UTCTime -> Signature -> AuthorizationInfo
- authorizationInfoQuery :: AuthorizationInfo -> UriQuery
- authorizationInfoHeader :: AuthorizationInfo -> RequestHeaders
- dateNormalizationEnabled :: Bool
- signingAlgorithm :: IsString a => a
- type UriPath = [Text]
- type UriQuery = QueryText
- normalizeUriPath :: UriPath -> UriPath
- normalizeUriQuery :: UriQuery -> UriQuery
- newtype CanonicalUri = CanonicalUri ByteString
- canonicalUri :: UriPath -> UriQuery -> CanonicalUri
- newtype CanonicalHeaders = CanonicalHeaders ByteString
- canonicalHeaders :: RequestHeaders -> CanonicalHeaders
- data SignedHeaders
- signedHeaders :: RequestHeaders -> SignedHeaders
- newtype CanonicalRequest = CanonicalRequest ByteString
- canonicalRequest :: Method -> UriPath -> UriQuery -> RequestHeaders -> ByteString -> CanonicalRequest
- data HashedCanonicalRequest
- hashedCanonicalRequest :: CanonicalRequest -> HashedCanonicalRequest
- data CredentialScope = CredentialScope {}
- credentialScopeToText :: (IsString a, Monoid a) => CredentialScope -> a
- newtype StringToSign = StringToSign ByteString
- stringToSign :: UTCTime -> CredentialScope -> CanonicalRequest -> StringToSign
- newtype SigningKey = SigningKey ByteString
- signingKey :: SignatureV4Credentials -> CredentialScope -> SigningKey
- newtype Signature = Signature ByteString
- requestSignature :: SigningKey -> StringToSign -> Signature
AWS General API Version
data GeneralVersion Source
generalVersionToText :: IsString a => GeneralVersion -> aSource
Signature Version
signatureVersion :: IsString a => aSource
AWS Credentials
data SignatureV4Credentials Source
AWS access credentials.
This type is compatible with the Credential
type from the
aws package. You may
use the following function to get a SignatureV4Credential
from a Credential
:
cred2credv4 :: Credential -> SignatureV4Credential #if MIN_VERSION_aws(0,9,2) cred2credv4 (Credential a b c _) = SignatureV4Credential a b c #else cred2credv4 (Credential a b c) = SignatureV4Credential a b c #endif
SignatureV4Credentials | |
|
:: (Functor m, MonadIO m) | |
=> ByteString | Access Key ID |
-> ByteString | Secret Access Key |
-> m SignatureV4Credentials |
= AWS Signature 4 Request Types
There are two types of version 4 signed requests for GET and for POST requests
http://docs.aws.amazon.com/general/1.0/gr/sigv4-signed-request-examples.html
== Common Parameters
Both request types must include the following information in some way
http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
- Host * Action * Date * Authorization parameters:
- Algorithm * Credential * Signed headers * signature
== POST Request
Computed by signPostRequest
or signPostRequestIO
.
Headers:
-
host
, *x-amz-date
(ordate
), *authorization
(containing all authorization parameters), and *content-type: application/x-www-form-urlencoded. charset=utf-8
.
The query parameters (including Action
and Version
) are placed in the body.
== GET Request
Computed with signGetRequest
or signGetRequestIO
.
Headers:
host
TODO why is this content-type
required?
Query:
-
Action
, *Version
, *X-Amz-Algorithm
, *X-Amz-Credential
, * Authorization parameters: -
X-Amz-Date
, *X-Amz-SignedHeaders
, *X-Amz-Signature
, *SignedHeaders
, *Signature
.
(NOTE that the AWS specification considers X-Amz-Date
an authorization parameter
only for URI requests. So for URI requests there are five authorization parameters
whereas otherwise there are just four.)
Somewhat surprisingly (and covered neither by the AWS Signature V4 test suite nor by the AWS API reference) the canonical request includes all authorization parameters except for the signature.
TODO: is it possible to do a POST with this style and place the query in the body?
Pure signing
:: SignatureV4Credentials | AWS credentials |
-> Region | request region |
-> ServiceNamespace | service of the request |
-> UTCTime | request time |
-> Method | HTTP method of request |
-> UriPath | URI Path of request |
-> UriQuery | URI Query of request |
-> RequestHeaders | request headers |
-> ByteString | request payload |
-> Either String RequestHeaders |
Compute an AWS Signature Version 4
This version computes the derivied signing key each time it is invoked
The request headers must include the host
header.
The query must include the Action
parameter.
The x-amz-date
header is generated by the code. A possibly existing
x-amz-date
header or date
header is replaced.
:: SignatureV4Credentials | AWS credentials |
-> Region | request region |
-> ServiceNamespace | service of the request |
-> UTCTime | request time |
-> Method | HTTP method of request |
-> UriPath | URI Path of request |
-> UriQuery | URI Query of request |
-> RequestHeaders | request headers |
-> ByteString | request payload |
-> Either String UriQuery |
Compute an AWS Signature Version 4
This version computes the derivied signing key each time it is invoked
The request headers must include the host
header.
The query must include the Action
parameter.
Signing With Cached Key
:: SignatureV4Credentials | AWS credentials |
-> Region | |
-> ServiceNamespace | |
-> UTCTime | |
-> Method | HTTP method of request |
-> UriPath | URI Path of request |
-> UriQuery | URI Query of request |
-> RequestHeaders | request headers |
-> ByteString | request payload |
-> IO (Either String RequestHeaders) |
The request headers must include the host
header.
The query must include the Action
parameter.
The x-amz-date
header is generated by the code. A possibly existing
x-amz-date
header or date
header is replaced.
:: SignatureV4Credentials | AWS credentials |
-> Region | |
-> ServiceNamespace | |
-> UTCTime | |
-> Method | HTTP method of request |
-> UriPath | URI Path of request |
-> UriQuery | URI Query of request |
-> RequestHeaders | request headers |
-> ByteString | request payload |
-> IO (Either String UriQuery) |
The request headers must include the host
header.
The query must include the Action
parameter.
Authorization Info
data AuthorizationInfo Source
authorizationInfo :: SignatureV4Credentials -> CredentialScope -> SignedHeaders -> UTCTime -> Signature -> AuthorizationInfoSource
Internal
dateNormalizationEnabled :: BoolSource
Normalization of the date header breaks the AWS test suite, since the tests in that test suite use an invalid date.
Date normalization is enabled by default but can be turned of via the cabal
(compiletime) flag normalize-signature-v4-date
.
Constants
signingAlgorithm :: IsString a => aSource
We only support SHA256 since SHA1 has been deprecated
Canoncial URI
normalizeUriPath :: UriPath -> UriPathSource
Normalize URI Path according to RFC 3986 (6.2.2)
normalizeUriQuery :: UriQuery -> UriQuerySource
Normalize URI Query according to RFC 3986 (6.2.2)
newtype CanonicalUri Source
canonicalUri :: UriPath -> UriQuery -> CanonicalUriSource
Compute canonical URI
http://docs.aws.amazon.com/general/1.0/gr/sigv4-create-canonical-request.html
The input is assumed to be an absolute URI. If the first segment is ..
it
is kept as is. Most likely such an URI is invalid.
Canonical Headers
newtype CanonicalHeaders Source
canonicalHeaders :: RequestHeaders -> CanonicalHeadersSource
Compute canonical HTTP headers
http://docs.aws.amazon.com/general/1.0/gr/sigv4-create-canonical-request.html
It is assumed (and not checked) that the header values comform with the definitions in RFC 2661. In particular non-comformant usage of quotation characters may lead to invalid results.
SignedHeaders
data SignedHeaders Source
signedHeaders :: RequestHeaders -> SignedHeadersSource
Compute signed headers
http://docs.aws.amazon.com/general/1.0/gr/sigv4-create-canonical-request.html
Canonical Request
newtype CanonicalRequest Source
:: Method | HTTP method of request |
-> UriPath | canonical URI Path of request |
-> UriQuery | canonical URI Query of request |
-> RequestHeaders | canonical request headers |
-> ByteString | Request payload |
-> CanonicalRequest |
Create Canonical Request for AWS Signature Version 4
http://docs.aws.amazon.com/general/1.0/gr/sigv4-create-canonical-request.html
This functions performs normalization of the URI and the Headers which is expensive. We should consider providing an alternate version of this function that bypasses these steps and simply assumes that the input is already canonical.
Credenital Scope
credentialScopeToText :: (IsString a, Monoid a) => CredentialScope -> aSource
String to Sign
newtype StringToSign Source
:: UTCTime | request date |
-> CredentialScope | credential scope for the request |
-> CanonicalRequest | canonical request |
-> StringToSign |
Create the String to Sign for AWS Signature Version 4
http://docs.aws.amazon.com/general/1.0/gr/sigv4-create-string-to-sign.html
Signing Key
newtype SigningKey Source
This key can be computed once and cached. It is valid for all requests to the same service and the region till 00:00:00 UTC time.
signingKey :: SignatureV4Credentials -> CredentialScope -> SigningKeySource
Derive the signing key
http://docs.aws.amazon.com/general/1.0/gr/sigv4-calculate-signature.html
Signature
Low level signing function
requestSignature :: SigningKey -> StringToSign -> SignatureSource
Compute an AWS Signature Version 4
http://docs.aws.amazon.com/general/1.0/gr/sigv4-calculate-signature.html