Copyright | Copyright © 2014 AlephCloud Systems, Inc. |
---|---|
License | MIT |
Maintainer | Lars Kuhtz <lars@alephcloud.com> |
Stability | experimental |
Safe Haskell | None |
Language | Haskell2010 |
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 -> a Source
parseGeneralVersion :: CharParsing m => m GeneralVersion Source
Signature Version
signatureVersion :: IsString a => a Source
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), andcontent-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 -> AuthorizationInfo Source
Internal
dateNormalizationEnabled :: Bool Source
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 => a Source
We only support SHA256 since SHA1 has been deprecated
Canoncial URI
normalizeUriPath :: UriPath -> UriPath Source
Normalize URI Path according to RFC 3986 (6.2.2)
normalizeUriQuery :: UriQuery -> UriQuery Source
Normalize URI Query according to RFC 3986 (6.2.2)
newtype CanonicalUri Source
canonicalUri :: UriPath -> UriQuery -> CanonicalUri Source
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 -> CanonicalHeaders Source
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 -> SignedHeaders Source
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 -> a Source
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 -> SigningKey Source
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 -> Signature Source
Compute an AWS Signature Version 4
http://docs.aws.amazon.com/general/1.0/gr/sigv4-calculate-signature.html