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 AvailabilityZone() string
- func Encode(s string) string
- func ExpBackoff(try int)
- func GetInstanceCredentials() (cred credentials, err error)
- func GetMetaData(path string) (contents []byte, err error)
- func InstanceId() string
- func InstanceRegion() string
- func InstanceType() string
- func LinearBackoff(try int)
- func MakeParams(action string) map[string]string
- func NewClient(rt *ResilientTransport) *http.Client
- func ServerLocalIp() string
- func ServerPublicIp() string
- type AWSService
- type Attempt
- type AttemptStrategy
- type Auth
- func CredentialFileAuth(filePath string, profile string, expiration time.Duration) (auth Auth, err error)
- func EnvAuth() (auth Auth, err error)
- func GetAuth(accessKey string, secretKey, token string, expiration time.Time) (auth Auth, err error)
- func NewAuth(accessKey, secretKey, token string, expiration time.Time) *Auth
- type BaseResponse
- type DeadlineFunc
- type DefaultRetryPolicy
- type DynamoDBRetryPolicy
- type Error
- type ErrorResponse
- type NeverRetryPolicy
- type Region
- type ResilientTransport
- type ResponseMetadata
- type RetryPolicy
- type RetryableFunc
- type Route53Signer
- type Service
- type ServiceError
- 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://kms.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://kinesis.ap-northeast-1.amazonaws.com", "https://sts.amazonaws.com", "https://cloudformation.ap-northeast-1.amazonaws.com", "https://elasticache.ap-northeast-1.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://kms.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://kinesis.ap-southeast-1.amazonaws.com", "https://sts.amazonaws.com", "https://cloudformation.ap-southeast-1.amazonaws.com", "https://elasticache.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://kms.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://kinesis.ap-southeast-2.amazonaws.com", "https://sts.amazonaws.com", "https://cloudformation.ap-southeast-2.amazonaws.com", "https://elasticache.ap-southeast-2.amazonaws.com", }
var CNNorth1 = Region{ "cn-north-1", "https://ec2.cn-north-1.amazonaws.com.cn", "https://s3.cn-north-1.amazonaws.com.cn", "", true, true, "", "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", "", "", }
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://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://kms.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://kinesis.eu-central-1.amazonaws.com", "https://sts.amazonaws.com", "https://cloudformation.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://sns.eu-west-1.amazonaws.com", "https://sqs.eu-west-1.amazonaws.com", "https://email.eu-west-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.eu-west-1.amazonaws.com", "https://kms.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://kinesis.eu-west-1.amazonaws.com", "https://sts.amazonaws.com", "https://cloudformation.eu-west-1.amazonaws.com", "https://elasticache.eu-west-1.amazonaws.com", }
var Regions = map[string]Region{ APNortheast.Name: APNortheast, APSoutheast.Name: APSoutheast, APSoutheast2.Name: APSoutheast2, EUCentral.Name: EUCentral, EUWest.Name: EUWest, USEast.Name: USEast, USWest.Name: USWest, USWest2.Name: USWest2, USGovWest.Name: USGovWest, SAEast.Name: SAEast, CNNorth1.Name: CNNorth1, }
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://kms.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://elasticache.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://sns.us-east-1.amazonaws.com", "https://sqs.us-east-1.amazonaws.com", "https://email.us-east-1.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.us-east-1.amazonaws.com", "https://kms.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://kinesis.us-east-1.amazonaws.com", "https://sts.amazonaws.com", "https://cloudformation.us-east-1.amazonaws.com", "https://elasticache.us-east-1.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", "", }
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://kms.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://kinesis.us-west-1.amazonaws.com", "https://sts.amazonaws.com", "https://cloudformation.us-west-1.amazonaws.com", "https://elasticache.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://sns.us-west-2.amazonaws.com", "https://sqs.us-west-2.amazonaws.com", "https://email.us-west-2.amazonaws.com", "https://iam.amazonaws.com", "https://elasticloadbalancing.us-west-2.amazonaws.com", "https://kms.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://kinesis.us-west-2.amazonaws.com", "https://sts.amazonaws.com", "https://cloudformation.us-west-2.amazonaws.com", "https://elasticache.us-west-2.amazonaws.com", }
Functions ¶
func AvailabilityZone ¶
func AvailabilityZone() string
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 GetInstanceCredentials ¶
func GetInstanceCredentials() (cred credentials, err error)
GetInstanceCredentials creates an Auth based on the instance's role credentials. If the running instance is not in EC2 or does not have a valid IAM role, an error will be returned. For more info about setting up IAM roles, see http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
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 InstanceId ¶
func InstanceId() string
func InstanceRegion ¶
func InstanceRegion() string
func InstanceType ¶
func InstanceType() string
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
func ServerLocalIp ¶
func ServerLocalIp() string
func ServerPublicIp ¶
func ServerPublicIp() string
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 CredentialFileAuth ¶
func CredentialFileAuth(filePath string, profile string, expiration time.Duration) (auth Auth, err error)
CredentialFileAuth creates and Auth based on a credentials file. The file contains various authentication profiles for use with AWS.
The credentials file, which is used by other AWS SDKs, is documented at http://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs
func EnvAuth ¶
EnvAuth creates an Auth based on environment information. The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables are used.
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 (*Auth) Expiration ¶
type BaseResponse ¶
type BaseResponse struct {
ResponseMetadata ResponseMetadata
}
type DeadlineFunc ¶
type DefaultRetryPolicy ¶
type DefaultRetryPolicy struct { }
DefaultRetryPolicy implements the AWS SDK default retry policy.
It will retry up to 3 times, and uses an exponential backoff with a scale factor of 300ms (300ms, 600ms, 1200ms). If the retry is because of throttling, the delay will also include some randomness.
func (DefaultRetryPolicy) Delay ¶
func (policy DefaultRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration
Delay implements the RetryPolicy Delay method.
func (DefaultRetryPolicy) ShouldRetry ¶
func (policy DefaultRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool
ShouldRetry implements the RetryPolicy ShouldRetry method.
type DynamoDBRetryPolicy ¶
type DynamoDBRetryPolicy struct { }
DynamoDBRetryPolicy implements the AWS SDK DynamoDB retry policy.
It will retry up to 10 times, and uses an exponential backoff with a scale factor of 25ms (25ms, 50ms, 100ms, ...).
func (DynamoDBRetryPolicy) Delay ¶
func (policy DynamoDBRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration
Delay implements the RetryPolicy Delay method.
func (DynamoDBRetryPolicy) ShouldRetry ¶
func (policy DynamoDBRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool
ShouldRetry implements the RetryPolicy ShouldRetry method.
type ErrorResponse ¶
type NeverRetryPolicy ¶
type NeverRetryPolicy struct { }
NeverRetryPolicy never retries requests and returns immediately on failure.
func (NeverRetryPolicy) Delay ¶
func (policy NeverRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration
Delay implements the RetryPolicy Delay method.
func (NeverRetryPolicy) ShouldRetry ¶
func (policy NeverRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool
ShouldRetry implements the RetryPolicy ShouldRetry method.
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 SNSEndpoint string SQSEndpoint string SESEndpoint string IAMEndpoint string ELBEndpoint string KMSEndpoint string DynamoDBEndpoint string CloudWatchServicepoint ServiceInfo AutoScalingEndpoint string RDSEndpoint ServiceInfo KinesisEndpoint string STSEndpoint string CloudFormationEndpoint string ElastiCacheEndpoint 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 RetryPolicy ¶
type RetryPolicy interface { // ShouldRetry returns whether a client should retry a failed request. ShouldRetry(target string, r *http.Response, err error, numRetries int) bool // Delay returns the time a client should wait before issuing a retry. Delay(target string, r *http.Response, err error, numRetries int) time.Duration }
A RetryPolicy encapsulates a strategy for implementing client retries.
Default implementations are provided which match the AWS SDKs.
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 ServiceError ¶
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 { // Add the x-amz-content-sha256 header IncludeXAmzContentSha256 bool // 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" "github.com/AdRoll/goamz/aws" "gopkg.in/check.v1" "net/http" "strings" "time" ) var _ = check.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 *check.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-empty V4SignerSuiteCase{ label: "get-relative-relative", 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-single-relative V4SignerSuiteCase{ label: "get-relative-relative", 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-multiple-relative V4SignerSuiteCase{ label: "get-relative-relative", 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-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-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 *check.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, check.IsNil, check.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, check.Equals, testCase.canonicalRequest, check.Commentf("Testcase: %s", testCase.label)) stringToSign := signer.StringToSign(t, canonicalRequest) c.Check(stringToSign, check.Equals, testCase.stringToSign, check.Commentf("Testcase: %s", testCase.label)) signature := signer.Signature(t, stringToSign) c.Check(signature, check.Equals, testCase.signature, check.Commentf("Testcase: %s", testCase.label)) authorization := signer.Authorization(req.Header, t, signature) c.Check(authorization, check.Equals, testCase.authorization, check.Commentf("Testcase: %s", testCase.label)) signer.Sign(req) c.Check(req.Header.Get("Authorization"), check.Equals, testCase.authorization, check.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.