Documentation ¶
Overview ¶
goamz - Go packages to interact with the Amazon Web Services.
https://wiki.ubuntu.com/goamz
Copyright (c) 2011 Canonical Ltd.
Written by Gustavo Niemeyer <gustavo.niemeyer@canonical.com>
Index ¶
- Constants
- Variables
- func Encode(s string) string
- func ExpBackoff(try int)
- func GetMetaData(path string) (contents []byte, err error)
- func LinearBackoff(try int)
- func MakeParams(action string) map[string]string
- func NewClient(rt *ResilientTransport) *http.Client
- type AWSService
- type Attempt
- type AttemptStrategy
- type Auth
- type BaseResponse
- type DeadlineFunc
- type Error
- type ErrorResponse
- type Region
- type ResilientTransport
- type ResponseMetadata
- type RetryableFunc
- type Route53Signer
- type Service
- type ServiceInfo
- type Signer
- type V2Signer
- type V4Signer
- type WaitFunc
Examples ¶
Constants ¶
const ( V2Signature = iota V4Signature = iota Route53Signature = iota )
Defines the valid signers
const ( ISO8601BasicFormat = "20060102T150405Z" ISO8601BasicFormatShort = "20060102" )
Common date formats for signing requests
Variables ¶
var APNortheast = Region{ "ap-northeast-1", "https://ec2.ap-northeast-1.amazonaws.com", "https://s3-ap-northeast-1.amazonaws.com", "", true, true, "https://sdb.ap-northeast-1.amazonaws.com", "", "https://sns.ap-northeast-1.amazonaws.com", "https://sqs.ap-northeast-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.ap-northeast-1.amazonaws.com", "https://dynamodb.ap-northeast-1.amazonaws.com", ServiceInfo{"https://monitoring.ap-northeast-1.amazonaws.com", V2Signature}, "https://autoscaling.ap-northeast-1.amazonaws.com", ServiceInfo{"https://rds.ap-northeast-1.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.ap-northeast-1.amazonaws.com", "https://ecs.ap-northeast-1.amazonaws.com", "https://streams.dynamodb.ap-northeast-1.amazonaws.com", }
var APNortheast2 = Region{ "ap-northeast-2", "https://ec2.ap-northeast-2.amazonaws.com", "https://s3-ap-northeast-2.amazonaws.com", "", true, true, "https://sdb.ap-northeast-2.amazonaws.com", "", "https://sns.ap-northeast-2.amazonaws.com", "https://sqs.ap-northeast-2.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.ap-northeast-2.amazonaws.com", "https://dynamodb.ap-northeast-2.amazonaws.com", ServiceInfo{"https://monitoring.ap-northeast-2.amazonaws.com", V2Signature}, "https://autoscaling.ap-northeast-2.amazonaws.com", ServiceInfo{"https://rds.ap-northeast-2.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.ap-northeast-2.amazonaws.com", "https://ecs.ap-northeast-2.amazonaws.com", "https://streams.dynamodb.ap-northeast-2.amazonaws.com", }
var APSoutheast = Region{ "ap-southeast-1", "https://ec2.ap-southeast-1.amazonaws.com", "https://s3-ap-southeast-1.amazonaws.com", "", true, true, "https://sdb.ap-southeast-1.amazonaws.com", "", "https://sns.ap-southeast-1.amazonaws.com", "https://sqs.ap-southeast-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.ap-southeast-1.amazonaws.com", "https://dynamodb.ap-southeast-1.amazonaws.com", ServiceInfo{"https://monitoring.ap-southeast-1.amazonaws.com", V2Signature}, "https://autoscaling.ap-southeast-1.amazonaws.com", ServiceInfo{"https://rds.ap-southeast-1.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.ap-southeast-1.amazonaws.com", "https://ecs.ap-southeast-1.amazonaws.com", "https://streams.dynamodb.ap-southeast-1.amazonaws.com", }
var APSoutheast2 = Region{ "ap-southeast-2", "https://ec2.ap-southeast-2.amazonaws.com", "https://s3-ap-southeast-2.amazonaws.com", "", true, true, "https://sdb.ap-southeast-2.amazonaws.com", "", "https://sns.ap-southeast-2.amazonaws.com", "https://sqs.ap-southeast-2.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.ap-southeast-2.amazonaws.com", "https://dynamodb.ap-southeast-2.amazonaws.com", ServiceInfo{"https://monitoring.ap-southeast-2.amazonaws.com", V2Signature}, "https://autoscaling.ap-southeast-2.amazonaws.com", ServiceInfo{"https://rds.ap-southeast-2.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.ap-southeast-2.amazonaws.com", "https://ecs.ap-southeast-2.amazonaws.com", "https://streams.dynamodb.ap-southeast-2.amazonaws.com", }
var CNNorth = Region{ "cn-north-1", "https://ec2.cn-north-1.amazonaws.com.cn", "https://s3.cn-north-1.amazonaws.com.cn", "", true, true, "https://sdb.cn-north-1.amazonaws.com.cn", "", "https://sns.cn-north-1.amazonaws.com.cn", "https://sqs.cn-north-1.amazonaws.com.cn", "https://iam.cn-north-1.amazonaws.com.cn", "https://elasticloadbalancing.cn-north-1.amazonaws.com.cn", "https://dynamodb.cn-north-1.amazonaws.com.cn", ServiceInfo{"https://monitoring.cn-north-1.amazonaws.com.cn", V4Signature}, "https://autoscaling.cn-north-1.amazonaws.com.cn", ServiceInfo{"https://rds.cn-north-1.amazonaws.com.cn", V4Signature}, "https://sts.cn-north-1.amazonaws.com.cn", "https://cloudformation.cn-north-1.amazonaws.com.cn", "https://ecs.cn-north-1.amazonaws.com.cn", "https://streams.dynamodb.cn-north-1.amazonaws.com.cn", }
var EUCentral = Region{ "eu-central-1", "https://ec2.eu-central-1.amazonaws.com", "https://s3-eu-central-1.amazonaws.com", "", true, true, "https://sdb.eu-central-1.amazonaws.com", "https://email.eu-central-1.amazonaws.com", "https://sns.eu-central-1.amazonaws.com", "https://sqs.eu-central-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.eu-central-1.amazonaws.com", "https://dynamodb.eu-central-1.amazonaws.com", ServiceInfo{"https://monitoring.eu-central-1.amazonaws.com", V2Signature}, "https://autoscaling.eu-central-1.amazonaws.com", ServiceInfo{"https://rds.eu-central-1.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.eu-central-1.amazonaws.com", "https://ecs.eu-central-1.amazonaws.com", "https://streams.dynamodb.eu-central-1.amazonaws.com", }
var EUWest = Region{ "eu-west-1", "https://ec2.eu-west-1.amazonaws.com", "https://s3-eu-west-1.amazonaws.com", "", true, true, "https://sdb.eu-west-1.amazonaws.com", "https://email.eu-west-1.amazonaws.com", "https://sns.eu-west-1.amazonaws.com", "https://sqs.eu-west-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.eu-west-1.amazonaws.com", "https://dynamodb.eu-west-1.amazonaws.com", ServiceInfo{"https://monitoring.eu-west-1.amazonaws.com", V2Signature}, "https://autoscaling.eu-west-1.amazonaws.com", ServiceInfo{"https://rds.eu-west-1.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.eu-west-1.amazonaws.com", "https://ecs.eu-west-1.amazonaws.com", "https://streams.dynamodb.eu-west-1.amazonaws.com", }
var Regions = map[string]Region{ APNortheast.Name: APNortheast, APNortheast2.Name: APNortheast2, APSoutheast.Name: APSoutheast, APSoutheast2.Name: APSoutheast2, EUCentral.Name: EUCentral, EUWest.Name: EUWest, USEast.Name: USEast, USEast2.Name: USEast2, USWest.Name: USWest, USWest2.Name: USWest2, USGovWest.Name: USGovWest, SAEast.Name: SAEast, CNNorth.Name: CNNorth, }
var RetryingClient = NewClient(retryingTransport)
Exported default client
var SAEast = Region{ "sa-east-1", "https://ec2.sa-east-1.amazonaws.com", "https://s3-sa-east-1.amazonaws.com", "", true, true, "https://sdb.sa-east-1.amazonaws.com", "", "https://sns.sa-east-1.amazonaws.com", "https://sqs.sa-east-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.sa-east-1.amazonaws.com", "https://dynamodb.sa-east-1.amazonaws.com", ServiceInfo{"https://monitoring.sa-east-1.amazonaws.com", V2Signature}, "https://autoscaling.sa-east-1.amazonaws.com", ServiceInfo{"https://rds.sa-east-1.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.sa-east-1.amazonaws.com", "https://ecs.sa-east-1.amazonaws.com", "https://streams.dynamodb.sa-east-1.amazonaws.com", }
var USEast = Region{ "us-east-1", "https://ec2.us-east-1.amazonaws.com", "https://s3.amazonaws.com", "", false, false, "https://sdb.amazonaws.com", "https://email.us-east-1.amazonaws.com", "https://sns.us-east-1.amazonaws.com", "https://sqs.us-east-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.us-east-1.amazonaws.com", "https://dynamodb.us-east-1.amazonaws.com", ServiceInfo{"https://monitoring.us-east-1.amazonaws.com", V2Signature}, "https://autoscaling.us-east-1.amazonaws.com", ServiceInfo{"https://rds.us-east-1.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.us-east-1.amazonaws.com", "https://ecs.us-east-1.amazonaws.com", "https://streams.dynamodb.us-east-1.amazonaws.com", }
var USEast2 = Region{ "us-east-2", "https://ec2.us-east-2.amazonaws.com", "https://s3.amazonaws.com", "", true, true, "", "", "https://sns.us-east-2.amazonaws.com", "https://sqs.us-east-2.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.us-east-2.amazonaws.com", "https://dynamodb.us-east-2.amazonaws.com", ServiceInfo{"https://monitoring.us-east-2.amazonaws.com", V2Signature}, "https://autoscaling.us-east-1.amazonaws.com", ServiceInfo{"https://rds.us-east-2.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.us-east-2.amazonaws.com", "https://ecs.us-east-2.amazonaws.com", "https://streams.dynamodb.us-east-2.amazonaws.com", }
var USGovWest = Region{ "us-gov-west-1", "https://ec2.us-gov-west-1.amazonaws.com", "https://s3-fips-us-gov-west-1.amazonaws.com", "", true, true, "", "", "https://sns.us-gov-west-1.amazonaws.com", "https://sqs.us-gov-west-1.amazonaws.com", "https://iam.us-gov.amazonaws.com", "https://elasticloadbalancing.us-gov-west-1.amazonaws.com", "https://dynamodb.us-gov-west-1.amazonaws.com", ServiceInfo{"https://monitoring.us-gov-west-1.amazonaws.com", V2Signature}, "https://autoscaling.us-gov-west-1.amazonaws.com", ServiceInfo{"https://rds.us-gov-west-1.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.us-gov-west-1.amazonaws.com", "https://ecs.us-gov-west-1.amazonaws.com", "https://streams.dynamodb.us-gov-west-1.amazonaws.com", }
var USWest = Region{ "us-west-1", "https://ec2.us-west-1.amazonaws.com", "https://s3-us-west-1.amazonaws.com", "", true, true, "https://sdb.us-west-1.amazonaws.com", "", "https://sns.us-west-1.amazonaws.com", "https://sqs.us-west-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.us-west-1.amazonaws.com", "https://dynamodb.us-west-1.amazonaws.com", ServiceInfo{"https://monitoring.us-west-1.amazonaws.com", V2Signature}, "https://autoscaling.us-west-1.amazonaws.com", ServiceInfo{"https://rds.us-west-1.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.us-west-1.amazonaws.com", "https://ecs.us-west-1.amazonaws.com", "https://streams.dynamodb.us-west-1.amazonaws.com", }
var USWest2 = Region{ "us-west-2", "https://ec2.us-west-2.amazonaws.com", "https://s3-us-west-2.amazonaws.com", "", true, true, "https://sdb.us-west-2.amazonaws.com", "https://email.us-west-2.amazonaws.com", "https://sns.us-west-2.amazonaws.com", "https://sqs.us-west-2.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.us-west-2.amazonaws.com", "https://dynamodb.us-west-2.amazonaws.com", ServiceInfo{"https://monitoring.us-west-2.amazonaws.com", V2Signature}, "https://autoscaling.us-west-2.amazonaws.com", ServiceInfo{"https://rds.us-west-2.amazonaws.com", V2Signature}, "https://sts.amazonaws.com", "https://cloudformation.us-west-2.amazonaws.com", "https://ecs.us-west-2.amazonaws.com", "https://streams.dynamodb.us-west-2.amazonaws.com", }
Functions ¶
func Encode ¶
Encode takes a string and URI-encodes it in a way suitable to be used in AWS signatures.
func ExpBackoff ¶
func ExpBackoff(try int)
func GetMetaData ¶
GetMetaData retrieves instance metadata about the current machine.
See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html for more details.
func LinearBackoff ¶
func LinearBackoff(try int)
func MakeParams ¶
Create a base set of params for an action
func NewClient ¶
func NewClient(rt *ResilientTransport) *http.Client
Convenience method for creating an http client
Types ¶
type AWSService ¶
type AWSService interface { // Queries the AWS service at a given method/path with the params and // returns an http.Response and error Query(method, path string, params map[string]string) (*http.Response, error) // Builds an error given an XML payload in the http.Response, can be used // to process an error if the status code is not 200 for example. BuildError(r *http.Response) error }
An AWS Service interface with the API to query the AWS service
Supplied as an easy way to mock out service calls during testing.
type Attempt ¶
type Attempt struct {
// contains filtered or unexported fields
}
type AttemptStrategy ¶
type AttemptStrategy struct { Total time.Duration // total duration of attempt. Delay time.Duration // interval between each try in the burst. Min int // minimum number of retries; overrides Total }
AttemptStrategy represents a strategy for waiting for an action to complete successfully. This is an internal type used by the implementation of other goamz packages.
func (AttemptStrategy) Start ¶
func (s AttemptStrategy) Start() *Attempt
Start begins a new sequence of attempts for the given strategy.
type Auth ¶
type Auth struct {
AccessKey, SecretKey string
// contains filtered or unexported fields
}
func EnvAuth ¶
EnvAuth creates an Auth based on environment information. The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables are used. AWS_SESSION_TOKEN is used if present.
func GetAuth ¶
func GetAuth(accessKey string, secretKey, token string, expiration time.Time) (auth Auth, err error)
GetAuth creates an Auth based on either passed in credentials, environment information or instance based role credentials.
func SharedAuth ¶
SharedAuth creates an Auth based on shared credentials stored in $HOME/.aws/credentials. The AWS_PROFILE environment variables is used to select the profile.
func (*Auth) Expiration ¶
type BaseResponse ¶
type BaseResponse struct {
ResponseMetadata ResponseMetadata
}
type DeadlineFunc ¶
type ErrorResponse ¶
type Region ¶
type Region struct { Name string // the canonical name of this region. EC2Endpoint string S3Endpoint string S3BucketEndpoint string // Not needed by AWS S3. Use ${bucket} for bucket name. S3LocationConstraint bool // true if this region requires a LocationConstraint declaration. S3LowercaseBucket bool // true if the region requires bucket names to be lower case. SDBEndpoint string SESEndpoint string SNSEndpoint string SQSEndpoint string IAMEndpoint string ELBEndpoint string DynamoDBEndpoint string CloudWatchServicepoint ServiceInfo AutoScalingEndpoint string RDSEndpoint ServiceInfo STSEndpoint string CloudFormationEndpoint string ECSEndpoint string DynamoDBStreamsEndpoint string }
Region defines the URLs where AWS services may be accessed.
See http://goo.gl/d8BP1 for more details.
type ResilientTransport ¶
type ResilientTransport struct { // Timeout is the maximum amount of time a dial will wait for // a connect to complete. // // The default is no timeout. // // With or without a timeout, the operating system may impose // its own earlier timeout. For instance, TCP timeouts are // often around 3 minutes. DialTimeout time.Duration // MaxTries, if non-zero, specifies the number of times we will retry on // failure. Retries are only attempted for temporary network errors or known // safe failures. MaxTries int Deadline DeadlineFunc ShouldRetry RetryableFunc Wait WaitFunc // contains filtered or unexported fields }
type ResponseMetadata ¶
type ResponseMetadata struct {
RequestId string // A unique ID for tracking the request
}
ResponseMetadata
type Route53Signer ¶
type Route53Signer struct {
// contains filtered or unexported fields
}
func NewRoute53Signer ¶
func NewRoute53Signer(auth Auth) *Route53Signer
func (*Route53Signer) Sign ¶
func (s *Route53Signer) Sign(req *http.Request)
Adds all the required headers for AWS Route53 API to the request including the authorization
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Implements a Server Query/Post API to easily query AWS services and build errors when desired
func NewService ¶
func NewService(auth Auth, service ServiceInfo) (s *Service, err error)
Create a new AWS server to handle making requests
type ServiceInfo ¶
Defines the service endpoint and correct Signer implementation to use to sign requests for this endpoint
type Signer ¶
Designates a signer interface suitable for signing AWS requests, params should be appropriately encoded for the request before signing.
A signer should be initialized with Auth and the appropriate endpoint.
type V2Signer ¶
type V2Signer struct {
// contains filtered or unexported fields
}
func NewV2Signer ¶
func NewV2Signer(auth Auth, service ServiceInfo) (*V2Signer, error)
type V4Signer ¶
type V4Signer struct {
// contains filtered or unexported fields
}
The V4Signer encapsulates all of the functionality to sign a request with the AWS Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)
Example ¶
package main import ( "fmt" "net/http" "strings" "time" "github.com/goamz/goamz/aws" . "gopkg.in/check.v1" ) var _ = Suite(&V4SignerSuite{}) type V4SignerSuite struct { auth aws.Auth region aws.Region cases []V4SignerSuiteCase } type V4SignerSuiteCase struct { label string request V4SignerSuiteCaseRequest canonicalRequest string stringToSign string signature string authorization string } type V4SignerSuiteCaseRequest struct { method string host string url string headers []string body string } func (s *V4SignerSuite) SetUpSuite(c *C) { s.auth = aws.Auth{AccessKey: "AKIDEXAMPLE", SecretKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"} s.region = aws.USEast // Test cases from the Signature Version 4 Test Suite (http://goo.gl/nguvs0) s.cases = append(s.cases, // get-header-key-duplicate V4SignerSuiteCase{ label: "get-header-key-duplicate", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "ZOO:zoobar", "zoo:foobar", "zoo:zoobar"}, }, canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:foobar,zoobar,zoobar\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n3c52f0eaae2b61329c0a332e3fa15842a37bc5812cf4d80eb64784308850e313", signature: "54afcaaf45b331f81cd2edb974f7b824ff4dd594cbbaa945ed636b48477368ed", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=54afcaaf45b331f81cd2edb974f7b824ff4dd594cbbaa945ed636b48477368ed", }, // get-header-value-order V4SignerSuiteCase{ label: "get-header-value-order", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "p:z", "p:a", "p:p", "p:a"}, }, canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\np:a,a,p,z\n\ndate;host;p\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n94c0389fefe0988cbbedc8606f0ca0b485b48da010d09fc844b45b697c8924fe", signature: "d2973954263943b11624a11d1c963ca81fb274169c7868b2858c04f083199e3d", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;p, Signature=d2973954263943b11624a11d1c963ca81fb274169c7868b2858c04f083199e3d", }, // get-header-value-trim V4SignerSuiteCase{ label: "get-header-value-trim", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "p: phfft "}, }, canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\np:phfft\n\ndate;host;p\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ndddd1902add08da1ac94782b05f9278c08dc7468db178a84f8950d93b30b1f35", signature: "debf546796015d6f6ded8626f5ce98597c33b47b9164cf6b17b4642036fcb592", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;p, Signature=debf546796015d6f6ded8626f5ce98597c33b47b9164cf6b17b4642036fcb592", }, // get-relative-relative V4SignerSuiteCase{ label: "get-relative-relative", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/foo/bar/../..", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1", signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", }, // get-relative V4SignerSuiteCase{ label: "get-relative", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/foo/..", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1", signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", }, // get-slash-dot-slash V4SignerSuiteCase{ label: "get-slash-dot-slash", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/./", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1", signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", }, // get-slash-pointless-dot V4SignerSuiteCase{ label: "get-slash-pointless-dot", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/./foo", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/foo\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n8021a97572ee460f87ca67f4e8c0db763216d84715f5424a843a5312a3321e2d", signature: "910e4d6c9abafaf87898e1eb4c929135782ea25bb0279703146455745391e63a", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=910e4d6c9abafaf87898e1eb4c929135782ea25bb0279703146455745391e63a", }, // get-slash V4SignerSuiteCase{ label: "get-slash", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "//", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1", signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", }, // get-slashes V4SignerSuiteCase{ label: "get-slashes", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "//foo//", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/foo/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n6bb4476ee8745730c9cb79f33a0c70baa6d8af29c0077fa12e4e8f1dd17e7098", signature: "b00392262853cfe3201e47ccf945601079e9b8a7f51ee4c3d9ee4f187aa9bf19", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b00392262853cfe3201e47ccf945601079e9b8a7f51ee4c3d9ee4f187aa9bf19", }, // get-space V4SignerSuiteCase{ label: "get-space", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/%20/foo", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/%20/foo\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n69c45fb9fe3fd76442b5086e50b2e9fec8298358da957b293ef26e506fdfb54b", signature: "f309cfbd10197a230c42dd17dbf5cca8a0722564cb40a872d25623cfa758e374", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=f309cfbd10197a230c42dd17dbf5cca8a0722564cb40a872d25623cfa758e374", }, // get-unreserved V4SignerSuiteCase{ label: "get-unreserved", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ndf63ee3247c0356c696a3b21f8d8490b01fa9cd5bc6550ef5ef5f4636b7b8901", signature: "830cc36d03f0f84e6ee4953fbe701c1c8b71a0372c63af9255aa364dd183281e", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=830cc36d03f0f84e6ee4953fbe701c1c8b71a0372c63af9255aa364dd183281e", }, // get-utf8 V4SignerSuiteCase{ label: "get-utf8", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/%E1%88%B4", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/%E1%88%B4\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n27ba31df5dbc6e063d8f87d62eb07143f7f271c5330a917840586ac1c85b6f6b", signature: "8d6634c189aa8c75c2e51e106b6b5121bed103fdb351f7d7d4381c738823af74", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=8d6634c189aa8c75c2e51e106b6b5121bed103fdb351f7d7d4381c738823af74", }, // get-vanilla-empty-query-key V4SignerSuiteCase{ label: "get-vanilla-empty-query-key", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/?foo=bar", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n0846c2945b0832deb7a463c66af5c4f8bd54ec28c438e67a214445b157c9ddf8", signature: "56c054473fd260c13e4e7393eb203662195f5d4a1fada5314b8b52b23f985e9f", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=56c054473fd260c13e4e7393eb203662195f5d4a1fada5314b8b52b23f985e9f", }, // get-vanilla-space-query-parameters V4SignerSuiteCase{ label: "get-vanilla-space-query-parameters", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/?foo foo=bar bar", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\nfoo%20foo=bar%20bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n6a81658ae0a0a4f73aa72ca7d3b01c9cb0c5d4099f7a5ee897f5a571bfe6f7ff", signature: "c8556bc676129d0806ea8fe6ef182dc095666f4c1582c3d9751d47e4306037c9", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=c8556bc676129d0806ea8fe6ef182dc095666f4c1582c3d9751d47e4306037c9", }, // get-vanilla-query-order-key-case V4SignerSuiteCase{ label: "get-vanilla-query-order-key-case", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/?foo=Zoo&foo=aha", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\nfoo=Zoo&foo=aha\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ne25f777ba161a0f1baf778a87faf057187cf5987f17953320e3ca399feb5f00d", signature: "be7148d34ebccdc6423b19085378aa0bee970bdc61d144bd1a8c48c33079ab09", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=be7148d34ebccdc6423b19085378aa0bee970bdc61d144bd1a8c48c33079ab09", }, // get-vanilla-query-order-key V4SignerSuiteCase{ label: "get-vanilla-query-order-key", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/?a=foo&b=foo", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\na=foo&b=foo\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n2f23d14fe13caebf6dfda346285c6d9c14f49eaca8f5ec55c627dd7404f7a727", signature: "0dc122f3b28b831ab48ba65cb47300de53fbe91b577fe113edac383730254a3b", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=0dc122f3b28b831ab48ba65cb47300de53fbe91b577fe113edac383730254a3b", }, // get-vanilla-query-order-value V4SignerSuiteCase{ label: "get-vanilla-query-order-value", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/?foo=b&foo=a", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\nfoo=a&foo=b\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n33dffc220e89131f8f6157a35c40903daa658608d9129ff9489e5cf5bbd9b11b", signature: "feb926e49e382bec75c9d7dcb2a1b6dc8aa50ca43c25d2bc51143768c0875acc", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=feb926e49e382bec75c9d7dcb2a1b6dc8aa50ca43c25d2bc51143768c0875acc", }, // get-vanilla-query-unreserved V4SignerSuiteCase{ label: "get-vanilla-query-unreserved", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/?-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\n-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nd2578f3156d4c9d180713d1ff20601d8a3eed0dd35447d24603d7d67414bd6b5", signature: "f1498ddb4d6dae767d97c466fb92f1b59a2c71ca29ac954692663f9db03426fb", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=f1498ddb4d6dae767d97c466fb92f1b59a2c71ca29ac954692663f9db03426fb", }, // get-vanilla-query V4SignerSuiteCase{ label: "get-vanilla-query", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1", signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", }, // get-vanilla-ut8-query V4SignerSuiteCase{ label: "get-vanilla-ut8-query", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/?ሴ=bar", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\n%E1%88%B4=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nde5065ff39c131e6c2e2bd19cd9345a794bf3b561eab20b8d97b2093fc2a979e", signature: "6fb359e9a05394cc7074e0feb42573a2601abc0c869a953e8c5c12e4e01f1a8c", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=6fb359e9a05394cc7074e0feb42573a2601abc0c869a953e8c5c12e4e01f1a8c", }, // get-vanilla V4SignerSuiteCase{ label: "get-vanilla", request: V4SignerSuiteCaseRequest{ method: "GET", host: "host.foo.com", url: "/", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1", signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470", }, // post-header-key-case V4SignerSuiteCase{ label: "post-header-key-case", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n05da62cee468d24ae84faff3c39f1b85540de60243c1bcaace39c0a2acc7b2c4", signature: "22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726", }, // post-header-key-sort V4SignerSuiteCase{ label: "post-header-key-sort", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "ZOO:zoobar"}, }, canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:zoobar\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n34e1bddeb99e76ee01d63b5e28656111e210529efeec6cdfd46a48e4c734545d", signature: "b7a95a52518abbca0964a999a880429ab734f35ebbf1235bd79a5de87756dc4a", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=b7a95a52518abbca0964a999a880429ab734f35ebbf1235bd79a5de87756dc4a", }, // post-header-value-case V4SignerSuiteCase{ label: "post-header-value-case", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "zoo:ZOOBAR"}, }, canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:ZOOBAR\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n3aae6d8274b8c03e2cc96fc7d6bda4b9bd7a0a184309344470b2c96953e124aa", signature: "273313af9d0c265c531e11db70bbd653f3ba074c1009239e8559d3987039cad7", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=273313af9d0c265c531e11db70bbd653f3ba074c1009239e8559d3987039cad7", }, // post-vanilla-empty-query-value V4SignerSuiteCase{ label: "post-vanilla-empty-query-value", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/?foo=bar", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "POST\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ncd4f39132d8e60bb388831d734230460872b564871c47f5de62e62d1a68dbe1e", signature: "b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92", }, // post-vanilla-query V4SignerSuiteCase{ label: "post-vanilla-query", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/?foo=bar", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "POST\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ncd4f39132d8e60bb388831d734230460872b564871c47f5de62e62d1a68dbe1e", signature: "b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92", }, // post-vanilla V4SignerSuiteCase{ label: "post-vanilla", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"}, }, canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n05da62cee468d24ae84faff3c39f1b85540de60243c1bcaace39c0a2acc7b2c4", signature: "22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726", }, // post-x-www-form-urlencoded-parameters V4SignerSuiteCase{ label: "post-x-www-form-urlencoded-parameters", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"Content-Type:application/x-www-form-urlencoded; charset=utf8", "Date:Mon, 09 Sep 2011 23:36:00 GMT"}, body: "foo=bar", }, canonicalRequest: "POST\n/\n\ncontent-type:application/x-www-form-urlencoded; charset=utf8\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ncontent-type;date;host\n3ba8907e7a252327488df390ed517c45b96dead033600219bdca7107d1d3f88a", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nc4115f9e54b5cecf192b1eaa23b8e88ed8dc5391bd4fde7b3fff3d9c9fe0af1f", signature: "b105eb10c6d318d2294de9d49dd8b031b55e3c3fe139f2e637da70511e9e7b71", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=content-type;date;host, Signature=b105eb10c6d318d2294de9d49dd8b031b55e3c3fe139f2e637da70511e9e7b71", }, // post-x-www-form-urlencoded V4SignerSuiteCase{ label: "post-x-www-form-urlencoded", request: V4SignerSuiteCaseRequest{ method: "POST", host: "host.foo.com", url: "/", headers: []string{"Content-Type:application/x-www-form-urlencoded", "Date:Mon, 09 Sep 2011 23:36:00 GMT"}, body: "foo=bar", }, canonicalRequest: "POST\n/\n\ncontent-type:application/x-www-form-urlencoded\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ncontent-type;date;host\n3ba8907e7a252327488df390ed517c45b96dead033600219bdca7107d1d3f88a", stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n4c5c6e4b52fb5fb947a8733982a8a5a61b14f04345cbfe6e739236c76dd48f74", signature: "5a15b22cf462f047318703b92e6f4f38884e4a7ab7b1d6426ca46a8bd1c26cbc", authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=content-type;date;host, Signature=5a15b22cf462f047318703b92e6f4f38884e4a7ab7b1d6426ca46a8bd1c26cbc", }, ) } func (s *V4SignerSuite) TestCases(c *C) { signer := aws.NewV4Signer(s.auth, "host", s.region) for _, testCase := range s.cases { req, err := http.NewRequest(testCase.request.method, "http://"+testCase.request.host+testCase.request.url, strings.NewReader(testCase.request.body)) c.Assert(err, IsNil, Commentf("Testcase: %s", testCase.label)) for _, v := range testCase.request.headers { h := strings.SplitN(v, ":", 2) req.Header.Add(h[0], h[1]) } req.Header.Set("host", req.Host) t := signer.RequestTime(req) canonicalRequest := signer.CanonicalRequest(req) c.Check(canonicalRequest, Equals, testCase.canonicalRequest, Commentf("Testcase: %s", testCase.label)) stringToSign := signer.StringToSign(t, canonicalRequest) c.Check(stringToSign, Equals, testCase.stringToSign, Commentf("Testcase: %s", testCase.label)) signature := signer.Signature(t, stringToSign) c.Check(signature, Equals, testCase.signature, Commentf("Testcase: %s", testCase.label)) authorization := signer.Authorization(req.Header, t, signature) c.Check(authorization, Equals, testCase.authorization, Commentf("Testcase: %s", testCase.label)) signer.Sign(req) c.Check(req.Header.Get("Authorization"), Equals, testCase.authorization, Commentf("Testcase: %s", testCase.label)) } } func main() { // Get auth from env vars auth, err := aws.EnvAuth() if err != nil { fmt.Println(err) } // Create a signer with the auth, name of the service, and aws region signer := aws.NewV4Signer(auth, "dynamodb", aws.USEast) // Create a request req, err := http.NewRequest("POST", aws.USEast.DynamoDBEndpoint, strings.NewReader("sample_request")) if err != nil { fmt.Println(err) } // Date or x-amz-date header is required to sign a request req.Header.Add("Date", time.Now().UTC().Format(http.TimeFormat)) // Sign the request signer.Sign(req) // Issue signed request http.DefaultClient.Do(req) }
Output:
func NewV4Signer ¶
Return a new instance of a V4Signer capable of signing AWS requests.
func (*V4Signer) Sign ¶
Sign a request according to the AWS Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)
The signed request will include an "x-amz-date" header with a current timestamp if a valid "x-amz-date" or "date" header was not available in the original request. In addition, AWS Signature Version 4 requires the "host" header to be a signed header, therefor the Sign method will manually set a "host" header from the request.Host.
The signed request will include a new "Authorization" header indicating that the request has been signed.
Any changes to the request after signing the request will invalidate the signature.