diff options
Diffstat (limited to 'vendor/github.com/goamz/goamz/aws')
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/attempt.go | 74 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/attempt_test.go | 58 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/aws.go | 435 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/aws_test.go | 211 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/client.go | 124 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/client_test.go | 121 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/export_test.go | 29 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/regions.go | 300 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/sign.go | 357 | ||||
-rw-r--r-- | vendor/github.com/goamz/goamz/aws/sign_test.go | 540 |
10 files changed, 0 insertions, 2249 deletions
diff --git a/vendor/github.com/goamz/goamz/aws/attempt.go b/vendor/github.com/goamz/goamz/aws/attempt.go deleted file mode 100644 index c0654f5d8..000000000 --- a/vendor/github.com/goamz/goamz/aws/attempt.go +++ /dev/null @@ -1,74 +0,0 @@ -package aws - -import ( - "time" -) - -// 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. -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 -} - -type Attempt struct { - strategy AttemptStrategy - last time.Time - end time.Time - force bool - count int -} - -// Start begins a new sequence of attempts for the given strategy. -func (s AttemptStrategy) Start() *Attempt { - now := time.Now() - return &Attempt{ - strategy: s, - last: now, - end: now.Add(s.Total), - force: true, - } -} - -// Next waits until it is time to perform the next attempt or returns -// false if it is time to stop trying. -func (a *Attempt) Next() bool { - now := time.Now() - sleep := a.nextSleep(now) - if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count { - return false - } - a.force = false - if sleep > 0 && a.count > 0 { - time.Sleep(sleep) - now = time.Now() - } - a.count++ - a.last = now - return true -} - -func (a *Attempt) nextSleep(now time.Time) time.Duration { - sleep := a.strategy.Delay - now.Sub(a.last) - if sleep < 0 { - return 0 - } - return sleep -} - -// HasNext returns whether another attempt will be made if the current -// one fails. If it returns true, the following call to Next is -// guaranteed to return true. -func (a *Attempt) HasNext() bool { - if a.force || a.strategy.Min > a.count { - return true - } - now := time.Now() - if now.Add(a.nextSleep(now)).Before(a.end) { - a.force = true - return true - } - return false -} diff --git a/vendor/github.com/goamz/goamz/aws/attempt_test.go b/vendor/github.com/goamz/goamz/aws/attempt_test.go deleted file mode 100644 index 8ba497715..000000000 --- a/vendor/github.com/goamz/goamz/aws/attempt_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package aws_test - -import ( - "time" - - "github.com/goamz/goamz/aws" - . "gopkg.in/check.v1" -) - -func (S) TestAttemptTiming(c *C) { - testAttempt := aws.AttemptStrategy{ - Total: 0.25e9, - Delay: 0.1e9, - } - want := []time.Duration{0, 0.1e9, 0.2e9, 0.2e9} - got := make([]time.Duration, 0, len(want)) // avoid allocation when testing timing - t0 := time.Now() - for a := testAttempt.Start(); a.Next(); { - got = append(got, time.Now().Sub(t0)) - } - got = append(got, time.Now().Sub(t0)) - c.Assert(got, HasLen, len(want)) - const margin = 0.01e9 - for i, got := range want { - lo := want[i] - margin - hi := want[i] + margin - if got < lo || got > hi { - c.Errorf("attempt %d want %g got %g", i, want[i].Seconds(), got.Seconds()) - } - } -} - -func (S) TestAttemptNextHasNext(c *C) { - a := aws.AttemptStrategy{}.Start() - c.Assert(a.Next(), Equals, true) - c.Assert(a.Next(), Equals, false) - - a = aws.AttemptStrategy{}.Start() - c.Assert(a.Next(), Equals, true) - c.Assert(a.HasNext(), Equals, false) - c.Assert(a.Next(), Equals, false) - - a = aws.AttemptStrategy{Total: 2e8}.Start() - c.Assert(a.Next(), Equals, true) - c.Assert(a.HasNext(), Equals, true) - time.Sleep(2e8) - c.Assert(a.HasNext(), Equals, true) - c.Assert(a.Next(), Equals, true) - c.Assert(a.Next(), Equals, false) - - a = aws.AttemptStrategy{Total: 1e8, Min: 2}.Start() - time.Sleep(1e8) - c.Assert(a.Next(), Equals, true) - c.Assert(a.HasNext(), Equals, true) - c.Assert(a.Next(), Equals, true) - c.Assert(a.HasNext(), Equals, false) - c.Assert(a.Next(), Equals, false) -} diff --git a/vendor/github.com/goamz/goamz/aws/aws.go b/vendor/github.com/goamz/goamz/aws/aws.go deleted file mode 100644 index a4d359160..000000000 --- a/vendor/github.com/goamz/goamz/aws/aws.go +++ /dev/null @@ -1,435 +0,0 @@ -// -// 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> -// -package aws - -import ( - "encoding/json" - "encoding/xml" - "errors" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "os" - "time" - - "github.com/vaughan0/go-ini" -) - -// Defines the valid signers -const ( - V2Signature = iota - V4Signature = iota - Route53Signature = iota -) - -// Defines the service endpoint and correct Signer implementation to use -// to sign requests for this endpoint -type ServiceInfo struct { - Endpoint string - Signer uint -} - -// Region defines the URLs where AWS services may be accessed. -// -// See http://goo.gl/d8BP1 for more details. -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 -} - -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, -} - -// 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 Signer interface { - Sign(method, path string, params map[string]string) -} - -// 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 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 -} - -// Implements a Server Query/Post API to easily query AWS services and build -// errors when desired -type Service struct { - service ServiceInfo - signer Signer -} - -// Create a base set of params for an action -func MakeParams(action string) map[string]string { - params := make(map[string]string) - params["Action"] = action - return params -} - -// Create a new AWS server to handle making requests -func NewService(auth Auth, service ServiceInfo) (s *Service, err error) { - var signer Signer - switch service.Signer { - case V2Signature: - signer, err = NewV2Signer(auth, service) - // case V4Signature: - // signer, err = NewV4Signer(auth, service, Regions["eu-west-1"]) - default: - err = fmt.Errorf("Unsupported signer for service") - } - if err != nil { - return - } - s = &Service{service: service, signer: signer} - return -} - -func (s *Service) Query(method, path string, params map[string]string) (resp *http.Response, err error) { - params["Timestamp"] = time.Now().UTC().Format(time.RFC3339) - u, err := url.Parse(s.service.Endpoint) - if err != nil { - return nil, err - } - u.Path = path - - s.signer.Sign(method, path, params) - if method == "GET" { - u.RawQuery = multimap(params).Encode() - resp, err = http.Get(u.String()) - } else if method == "POST" { - resp, err = http.PostForm(u.String(), multimap(params)) - } - - return -} - -func (s *Service) BuildError(r *http.Response) error { - errors := ErrorResponse{} - xml.NewDecoder(r.Body).Decode(&errors) - var err Error - err = errors.Errors - err.RequestId = errors.RequestId - err.StatusCode = r.StatusCode - if err.Message == "" { - err.Message = r.Status - } - return &err -} - -type ErrorResponse struct { - Errors Error `xml:"Error"` - RequestId string // A unique ID for tracking the request -} - -type Error struct { - StatusCode int - Type string - Code string - Message string - RequestId string -} - -func (err *Error) Error() string { - return fmt.Sprintf("Type: %s, Code: %s, Message: %s", - err.Type, err.Code, err.Message, - ) -} - -type Auth struct { - AccessKey, SecretKey string - token string - expiration time.Time -} - -func (a *Auth) Token() string { - if a.token == "" { - return "" - } - if time.Since(a.expiration) >= -30*time.Second { //in an ideal world this should be zero assuming the instance is synching it's clock - *a, _ = GetAuth("", "", "", time.Time{}) - } - return a.token -} - -func (a *Auth) Expiration() time.Time { - return a.expiration -} - -// To be used with other APIs that return auth credentials such as STS -func NewAuth(accessKey, secretKey, token string, expiration time.Time) *Auth { - return &Auth{ - AccessKey: accessKey, - SecretKey: secretKey, - token: token, - expiration: expiration, - } -} - -// ResponseMetadata -type ResponseMetadata struct { - RequestId string // A unique ID for tracking the request -} - -type BaseResponse struct { - ResponseMetadata ResponseMetadata -} - -var unreserved = make([]bool, 128) -var hex = "0123456789ABCDEF" - -func init() { - // RFC3986 - u := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890-_.~" - for _, c := range u { - unreserved[c] = true - } -} - -func multimap(p map[string]string) url.Values { - q := make(url.Values, len(p)) - for k, v := range p { - q[k] = []string{v} - } - return q -} - -type credentials struct { - Code string - LastUpdated string - Type string - AccessKeyId string - SecretAccessKey string - Token string - Expiration string -} - -// 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 GetMetaData(path string) (contents []byte, err error) { - url := "http://169.254.169.254/latest/meta-data/" + path - - resp, err := RetryingClient.Get(url) - if err != nil { - return - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url) - return - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return - } - return []byte(body), err -} - -func getInstanceCredentials() (cred credentials, err error) { - credentialPath := "iam/security-credentials/" - - // Get the instance role - role, err := GetMetaData(credentialPath) - if err != nil { - return - } - - // Get the instance role credentials - credentialJSON, err := GetMetaData(credentialPath + string(role)) - if err != nil { - return - } - - err = json.Unmarshal([]byte(credentialJSON), &cred) - return -} - -// GetAuth creates an Auth based on either passed in credentials, -// environment information or instance based role credentials. -func GetAuth(accessKey string, secretKey, token string, expiration time.Time) (auth Auth, err error) { - // First try passed in credentials - if accessKey != "" && secretKey != "" { - return Auth{accessKey, secretKey, token, expiration}, nil - } - - // Next try to get auth from the shared credentials file - auth, err = SharedAuth() - if err == nil { - // Found auth, return - return - } - - // Next try to get auth from the environment - auth, err = EnvAuth() - if err == nil { - // Found auth, return - return - } - - // Next try getting auth from the instance role - cred, err := getInstanceCredentials() - if err == nil { - // Found auth, return - auth.AccessKey = cred.AccessKeyId - auth.SecretKey = cred.SecretAccessKey - auth.token = cred.Token - exptdate, err := time.Parse("2006-01-02T15:04:05Z", cred.Expiration) - if err != nil { - err = fmt.Errorf("Error Parseing expiration date: cred.Expiration :%s , error: %s \n", cred.Expiration, err) - } - auth.expiration = exptdate - return auth, err - } - err = errors.New("No valid AWS authentication found") - return auth, err -} - -// 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 EnvAuth() (auth Auth, err error) { - auth.AccessKey = os.Getenv("AWS_ACCESS_KEY_ID") - if auth.AccessKey == "" { - auth.AccessKey = os.Getenv("AWS_ACCESS_KEY") - } - - auth.SecretKey = os.Getenv("AWS_SECRET_ACCESS_KEY") - if auth.SecretKey == "" { - auth.SecretKey = os.Getenv("AWS_SECRET_KEY") - } - if auth.AccessKey == "" { - err = errors.New("AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment") - } - if auth.SecretKey == "" { - err = errors.New("AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment") - } - - auth.token = os.Getenv("AWS_SESSION_TOKEN") - return -} - -// 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 SharedAuth() (auth Auth, err error) { - var profileName = os.Getenv("AWS_PROFILE") - - if profileName == "" { - profileName = "default" - } - - var credentialsFile = os.Getenv("AWS_CREDENTIAL_FILE") - if credentialsFile == "" { - var homeDir = os.Getenv("HOME") - if homeDir == "" { - err = errors.New("Could not get HOME") - return - } - credentialsFile = homeDir + "/.aws/credentials" - } - - file, err := ini.LoadFile(credentialsFile) - if err != nil { - err = errors.New("Couldn't parse AWS credentials file") - return - } - - var profile = file[profileName] - if profile == nil { - err = errors.New("Couldn't find profile in AWS credentials file") - return - } - - auth.AccessKey = profile["aws_access_key_id"] - auth.SecretKey = profile["aws_secret_access_key"] - auth.token = profile["aws_session_token"] - - if auth.AccessKey == "" { - err = errors.New("AWS_ACCESS_KEY_ID not found in environment in credentials file") - } - if auth.SecretKey == "" { - err = errors.New("AWS_SECRET_ACCESS_KEY not found in credentials file") - } - return -} - -// Encode takes a string and URI-encodes it in a way suitable -// to be used in AWS signatures. -func Encode(s string) string { - encode := false - for i := 0; i != len(s); i++ { - c := s[i] - if c > 127 || !unreserved[c] { - encode = true - break - } - } - if !encode { - return s - } - e := make([]byte, len(s)*3) - ei := 0 - for i := 0; i != len(s); i++ { - c := s[i] - if c > 127 || !unreserved[c] { - e[ei] = '%' - e[ei+1] = hex[c>>4] - e[ei+2] = hex[c&0xF] - ei += 3 - } else { - e[ei] = c - ei += 1 - } - } - return string(e[:ei]) -} diff --git a/vendor/github.com/goamz/goamz/aws/aws_test.go b/vendor/github.com/goamz/goamz/aws/aws_test.go deleted file mode 100644 index 0c74a7905..000000000 --- a/vendor/github.com/goamz/goamz/aws/aws_test.go +++ /dev/null @@ -1,211 +0,0 @@ -package aws_test - -import ( - "io/ioutil" - "os" - "strings" - "testing" - "time" - - "github.com/goamz/goamz/aws" - . "gopkg.in/check.v1" -) - -func Test(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&S{}) - -type S struct { - environ []string -} - -func (s *S) SetUpSuite(c *C) { - s.environ = os.Environ() -} - -func (s *S) TearDownTest(c *C) { - os.Clearenv() - for _, kv := range s.environ { - l := strings.SplitN(kv, "=", 2) - os.Setenv(l[0], l[1]) - } -} - -func (s *S) TestSharedAuthNoHome(c *C) { - os.Clearenv() - os.Setenv("AWS_PROFILE", "foo") - _, err := aws.SharedAuth() - c.Assert(err, ErrorMatches, "Could not get HOME") -} - -func (s *S) TestSharedAuthNoCredentialsFile(c *C) { - os.Clearenv() - os.Setenv("AWS_PROFILE", "foo") - os.Setenv("HOME", "/tmp") - _, err := aws.SharedAuth() - c.Assert(err, ErrorMatches, "Couldn't parse AWS credentials file") -} - -func (s *S) TestSharedAuthNoProfileInFile(c *C) { - os.Clearenv() - os.Setenv("AWS_PROFILE", "foo") - - d, err := ioutil.TempDir("", "") - if err != nil { - panic(err) - } - defer os.RemoveAll(d) - - err = os.Mkdir(d+"/.aws", 0755) - if err != nil { - panic(err) - } - - ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\n"), 0644) - os.Setenv("HOME", d) - - _, err = aws.SharedAuth() - c.Assert(err, ErrorMatches, "Couldn't find profile in AWS credentials file") -} - -func (s *S) TestSharedAuthNoKeysInProfile(c *C) { - os.Clearenv() - os.Setenv("AWS_PROFILE", "bar") - - d, err := ioutil.TempDir("", "") - if err != nil { - panic(err) - } - defer os.RemoveAll(d) - - err = os.Mkdir(d+"/.aws", 0755) - if err != nil { - panic(err) - } - - ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\nawsaccesskeyid = AK.."), 0644) - os.Setenv("HOME", d) - - _, err = aws.SharedAuth() - c.Assert(err, ErrorMatches, "AWS_SECRET_ACCESS_KEY not found in credentials file") -} - -func (s *S) TestSharedAuthDefaultCredentials(c *C) { - os.Clearenv() - - d, err := ioutil.TempDir("", "") - if err != nil { - panic(err) - } - defer os.RemoveAll(d) - - err = os.Mkdir(d+"/.aws", 0755) - if err != nil { - panic(err) - } - - ioutil.WriteFile(d+"/.aws/credentials", []byte("[default]\naws_access_key_id = access\naws_secret_access_key = secret\n"), 0644) - os.Setenv("HOME", d) - - auth, err := aws.SharedAuth() - c.Assert(err, IsNil) - c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) -} - -func (s *S) TestSharedAuth(c *C) { - os.Clearenv() - os.Setenv("AWS_PROFILE", "bar") - - d, err := ioutil.TempDir("", "") - if err != nil { - panic(err) - } - defer os.RemoveAll(d) - - err = os.Mkdir(d+"/.aws", 0755) - if err != nil { - panic(err) - } - - ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\naws_access_key_id = access\naws_secret_access_key = secret\n"), 0644) - os.Setenv("HOME", d) - - auth, err := aws.SharedAuth() - c.Assert(err, IsNil) - c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) -} - -func (s *S) TestEnvAuthNoSecret(c *C) { - os.Clearenv() - _, err := aws.EnvAuth() - c.Assert(err, ErrorMatches, "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment") -} - -func (s *S) TestEnvAuthNoAccess(c *C) { - os.Clearenv() - os.Setenv("AWS_SECRET_ACCESS_KEY", "foo") - _, err := aws.EnvAuth() - c.Assert(err, ErrorMatches, "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment") -} - -func (s *S) TestEnvAuth(c *C) { - os.Clearenv() - os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") - os.Setenv("AWS_ACCESS_KEY_ID", "access") - auth, err := aws.EnvAuth() - c.Assert(err, IsNil) - c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) -} - -func (s *S) TestEnvAuthAlt(c *C) { - os.Clearenv() - os.Setenv("AWS_SECRET_KEY", "secret") - os.Setenv("AWS_ACCESS_KEY", "access") - auth, err := aws.EnvAuth() - c.Assert(err, IsNil) - c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) -} - -func (s *S) TestEnvAuthToken(c *C) { - os.Clearenv() - os.Setenv("AWS_SECRET_KEY", "secret") - os.Setenv("AWS_ACCESS_KEY", "access") - os.Setenv("AWS_SESSION_TOKEN", "token") - auth, err := aws.EnvAuth() - c.Assert(err, IsNil) - c.Assert(auth.SecretKey, Equals, "secret") - c.Assert(auth.AccessKey, Equals, "access") - c.Assert(auth.Token(), Equals, "token") -} - -func (s *S) TestGetAuthStatic(c *C) { - exptdate := time.Now().Add(time.Hour) - auth, err := aws.GetAuth("access", "secret", "token", exptdate) - c.Assert(err, IsNil) - c.Assert(auth.AccessKey, Equals, "access") - c.Assert(auth.SecretKey, Equals, "secret") - c.Assert(auth.Token(), Equals, "token") - c.Assert(auth.Expiration(), Equals, exptdate) -} - -func (s *S) TestGetAuthEnv(c *C) { - os.Clearenv() - os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") - os.Setenv("AWS_ACCESS_KEY_ID", "access") - auth, err := aws.GetAuth("", "", "", time.Time{}) - c.Assert(err, IsNil) - c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) -} - -func (s *S) TestEncode(c *C) { - c.Assert(aws.Encode("foo"), Equals, "foo") - c.Assert(aws.Encode("/"), Equals, "%2F") -} - -func (s *S) TestRegionsAreNamed(c *C) { - for n, r := range aws.Regions { - c.Assert(n, Equals, r.Name) - } -} diff --git a/vendor/github.com/goamz/goamz/aws/client.go b/vendor/github.com/goamz/goamz/aws/client.go deleted file mode 100644 index 86d2ccec8..000000000 --- a/vendor/github.com/goamz/goamz/aws/client.go +++ /dev/null @@ -1,124 +0,0 @@ -package aws - -import ( - "math" - "net" - "net/http" - "time" -) - -type RetryableFunc func(*http.Request, *http.Response, error) bool -type WaitFunc func(try int) -type DeadlineFunc func() time.Time - -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 - transport *http.Transport -} - -// Convenience method for creating an http client -func NewClient(rt *ResilientTransport) *http.Client { - rt.transport = &http.Transport{ - Dial: func(netw, addr string) (net.Conn, error) { - c, err := net.DialTimeout(netw, addr, rt.DialTimeout) - if err != nil { - return nil, err - } - c.SetDeadline(rt.Deadline()) - return c, nil - }, - Proxy: http.ProxyFromEnvironment, - } - // TODO: Would be nice is ResilientTransport allowed clients to initialize - // with http.Transport attributes. - return &http.Client{ - Transport: rt, - } -} - -var retryingTransport = &ResilientTransport{ - Deadline: func() time.Time { - return time.Now().Add(5 * time.Second) - }, - DialTimeout: 10 * time.Second, - MaxTries: 3, - ShouldRetry: awsRetry, - Wait: ExpBackoff, -} - -// Exported default client -var RetryingClient = NewClient(retryingTransport) - -func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Response, error) { - return t.tries(req) -} - -// Retry a request a maximum of t.MaxTries times. -// We'll only retry if the proper criteria are met. -// If a wait function is specified, wait that amount of time -// In between requests. -func (t *ResilientTransport) tries(req *http.Request) (res *http.Response, err error) { - for try := 0; try < t.MaxTries; try += 1 { - res, err = t.transport.RoundTrip(req) - - if !t.ShouldRetry(req, res, err) { - break - } - if res != nil { - res.Body.Close() - } - if t.Wait != nil { - t.Wait(try) - } - } - - return -} - -func ExpBackoff(try int) { - time.Sleep(100 * time.Millisecond * - time.Duration(math.Exp2(float64(try)))) -} - -func LinearBackoff(try int) { - time.Sleep(time.Duration(try*100) * time.Millisecond) -} - -// Decide if we should retry a request. -// In general, the criteria for retrying a request is described here -// http://docs.aws.amazon.com/general/latest/gr/api-retries.html -func awsRetry(req *http.Request, res *http.Response, err error) bool { - retry := false - - // Retry if there's a temporary network error. - if neterr, ok := err.(net.Error); ok { - if neterr.Temporary() { - retry = true - } - } - - // Retry if we get a 5xx series error. - if res != nil { - if res.StatusCode >= 500 && res.StatusCode < 600 { - retry = true - } - } - - return retry -} diff --git a/vendor/github.com/goamz/goamz/aws/client_test.go b/vendor/github.com/goamz/goamz/aws/client_test.go deleted file mode 100644 index c66a86333..000000000 --- a/vendor/github.com/goamz/goamz/aws/client_test.go +++ /dev/null @@ -1,121 +0,0 @@ -package aws_test - -import ( - "fmt" - "github.com/goamz/goamz/aws" - "io/ioutil" - "net/http" - "net/http/httptest" - "strings" - "testing" - "time" -) - -// Retrieve the response from handler using aws.RetryingClient -func serveAndGet(handler http.HandlerFunc) (body string, err error) { - ts := httptest.NewServer(handler) - defer ts.Close() - resp, err := aws.RetryingClient.Get(ts.URL) - if err != nil { - return - } - if resp.StatusCode != 200 { - return "", fmt.Errorf("Bad status code: %d", resp.StatusCode) - } - greeting, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - return - } - return strings.TrimSpace(string(greeting)), nil -} - -func TestClient_expected(t *testing.T) { - body := "foo bar" - - resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, body) - }) - if err != nil { - t.Fatal(err) - } - if resp != body { - t.Fatal("Body not as expected.") - } -} - -func TestClient_delay(t *testing.T) { - body := "baz" - wait := 4 - resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { - if wait < 0 { - // If we dipped to zero delay and still failed. - t.Fatal("Never succeeded.") - } - wait -= 1 - time.Sleep(time.Second * time.Duration(wait)) - fmt.Fprintln(w, body) - }) - if err != nil { - t.Fatal(err) - } - if resp != body { - t.Fatal("Body not as expected.", resp) - } -} - -func TestClient_no4xxRetry(t *testing.T) { - tries := 0 - - // Fail once before succeeding. - _, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { - tries += 1 - http.Error(w, "error", 404) - }) - - if err == nil { - t.Fatal("should have error") - } - - if tries != 1 { - t.Fatalf("should only try once: %d", tries) - } -} - -func TestClient_retries(t *testing.T) { - body := "biz" - failed := false - // Fail once before succeeding. - resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { - if !failed { - http.Error(w, "error", 500) - failed = true - } else { - fmt.Fprintln(w, body) - } - }) - if failed != true { - t.Error("We didn't retry!") - } - if err != nil { - t.Fatal(err) - } - if resp != body { - t.Fatal("Body not as expected.") - } -} - -func TestClient_fails(t *testing.T) { - tries := 0 - // Fail 3 times and return the last error. - _, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { - tries += 1 - http.Error(w, "error", 500) - }) - if err == nil { - t.Fatal(err) - } - if tries != 3 { - t.Fatal("Didn't retry enough") - } -} diff --git a/vendor/github.com/goamz/goamz/aws/export_test.go b/vendor/github.com/goamz/goamz/aws/export_test.go deleted file mode 100644 index c4aca1d72..000000000 --- a/vendor/github.com/goamz/goamz/aws/export_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package aws - -import ( - "net/http" - "time" -) - -// V4Signer: -// Exporting methods for testing - -func (s *V4Signer) RequestTime(req *http.Request) time.Time { - return s.requestTime(req) -} - -func (s *V4Signer) CanonicalRequest(req *http.Request) string { - return s.canonicalRequest(req) -} - -func (s *V4Signer) StringToSign(t time.Time, creq string) string { - return s.stringToSign(t, creq) -} - -func (s *V4Signer) Signature(t time.Time, sts string) string { - return s.signature(t, sts) -} - -func (s *V4Signer) Authorization(header http.Header, t time.Time, signature string) string { - return s.authorization(header, t, signature) -} diff --git a/vendor/github.com/goamz/goamz/aws/regions.go b/vendor/github.com/goamz/goamz/aws/regions.go deleted file mode 100644 index c75d41e11..000000000 --- a/vendor/github.com/goamz/goamz/aws/regions.go +++ /dev/null @@ -1,300 +0,0 @@ -package aws - -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 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 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", -} - -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 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 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 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 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 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", -} diff --git a/vendor/github.com/goamz/goamz/aws/sign.go b/vendor/github.com/goamz/goamz/aws/sign.go deleted file mode 100644 index 22ce0781b..000000000 --- a/vendor/github.com/goamz/goamz/aws/sign.go +++ /dev/null @@ -1,357 +0,0 @@ -package aws - -import ( - "bytes" - "crypto/hmac" - "crypto/sha256" - "encoding/base64" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "path" - "sort" - "strings" - "time" -) - -type V2Signer struct { - auth Auth - service ServiceInfo - host string -} - -var b64 = base64.StdEncoding - -func NewV2Signer(auth Auth, service ServiceInfo) (*V2Signer, error) { - u, err := url.Parse(service.Endpoint) - if err != nil { - return nil, err - } - return &V2Signer{auth: auth, service: service, host: u.Host}, nil -} - -func (s *V2Signer) Sign(method, path string, params map[string]string) { - params["AWSAccessKeyId"] = s.auth.AccessKey - params["SignatureVersion"] = "2" - params["SignatureMethod"] = "HmacSHA256" - if s.auth.Token() != "" { - params["SecurityToken"] = s.auth.Token() - } - - // AWS specifies that the parameters in a signed request must - // be provided in the natural order of the keys. This is distinct - // from the natural order of the encoded value of key=value. - // Percent and Equals affect the sorting order. - var keys, sarray []string - for k, _ := range params { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - sarray = append(sarray, Encode(k)+"="+Encode(params[k])) - } - joined := strings.Join(sarray, "&") - payload := method + "\n" + s.host + "\n" + path + "\n" + joined - hash := hmac.New(sha256.New, []byte(s.auth.SecretKey)) - hash.Write([]byte(payload)) - signature := make([]byte, b64.EncodedLen(hash.Size())) - b64.Encode(signature, hash.Sum(nil)) - - params["Signature"] = string(signature) -} - -// Common date formats for signing requests -const ( - ISO8601BasicFormat = "20060102T150405Z" - ISO8601BasicFormatShort = "20060102" -) - -type Route53Signer struct { - auth Auth -} - -func NewRoute53Signer(auth Auth) *Route53Signer { - return &Route53Signer{auth: auth} -} - -// getCurrentDate fetches the date stamp from the aws servers to -// ensure the auth headers are within 5 minutes of the server time -func (s *Route53Signer) getCurrentDate() string { - response, err := http.Get("https://route53.amazonaws.com/date") - if err != nil { - fmt.Print("Unable to get date from amazon: ", err) - return "" - } - - response.Body.Close() - return response.Header.Get("Date") -} - -// Creates the authorize signature based on the date stamp and secret key -func (s *Route53Signer) getHeaderAuthorize(message string) string { - hmacSha256 := hmac.New(sha256.New, []byte(s.auth.SecretKey)) - hmacSha256.Write([]byte(message)) - cryptedString := hmacSha256.Sum(nil) - - return base64.StdEncoding.EncodeToString(cryptedString) -} - -// Adds all the required headers for AWS Route53 API to the request -// including the authorization -func (s *Route53Signer) Sign(req *http.Request) { - date := s.getCurrentDate() - authHeader := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=%s,Signature=%s", - s.auth.AccessKey, "HmacSHA256", s.getHeaderAuthorize(date)) - - req.Header.Set("Host", req.Host) - req.Header.Set("X-Amzn-Authorization", authHeader) - req.Header.Set("X-Amz-Date", date) - req.Header.Set("Content-Type", "application/xml") -} - -/* -The V4Signer encapsulates all of the functionality to sign a request with the AWS -Signature Version 4 Signing Process. (http://goo.gl/u1OWZz) -*/ -type V4Signer struct { - auth Auth - serviceName string - region Region -} - -/* -Return a new instance of a V4Signer capable of signing AWS requests. -*/ -func NewV4Signer(auth Auth, serviceName string, region Region) *V4Signer { - return &V4Signer{auth: auth, serviceName: serviceName, region: region} -} - -/* -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. -*/ -func (s *V4Signer) Sign(req *http.Request) { - req.Header.Set("host", req.Host) // host header must be included as a signed header - t := s.requestTime(req) // Get requst time - creq := s.canonicalRequest(req) // Build canonical request - sts := s.stringToSign(t, creq) // Build string to sign - signature := s.signature(t, sts) // Calculate the AWS Signature Version 4 - auth := s.authorization(req.Header, t, signature) // Create Authorization header value - req.Header.Set("Authorization", auth) // Add Authorization header to request - return -} - -/* -requestTime method will parse the time from the request "x-amz-date" or "date" headers. -If the "x-amz-date" header is present, that will take priority over the "date" header. -If neither header is defined or we are unable to parse either header as a valid date -then we will create a new "x-amz-date" header with the current time. -*/ -func (s *V4Signer) requestTime(req *http.Request) time.Time { - - // Get "x-amz-date" header - date := req.Header.Get("x-amz-date") - - // Attempt to parse as ISO8601BasicFormat - t, err := time.Parse(ISO8601BasicFormat, date) - if err == nil { - return t - } - - // Attempt to parse as http.TimeFormat - t, err = time.Parse(http.TimeFormat, date) - if err == nil { - req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat)) - return t - } - - // Get "date" header - date = req.Header.Get("date") - - // Attempt to parse as http.TimeFormat - t, err = time.Parse(http.TimeFormat, date) - if err == nil { - return t - } - - // Create a current time header to be used - t = time.Now().UTC() - req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat)) - return t -} - -/* -canonicalRequest method creates the canonical request according to Task 1 of the AWS Signature Version 4 Signing Process. (http://goo.gl/eUUZ3S) - - CanonicalRequest = - HTTPRequestMethod + '\n' + - CanonicalURI + '\n' + - CanonicalQueryString + '\n' + - CanonicalHeaders + '\n' + - SignedHeaders + '\n' + - HexEncode(Hash(Payload)) -*/ -func (s *V4Signer) canonicalRequest(req *http.Request) string { - c := new(bytes.Buffer) - fmt.Fprintf(c, "%s\n", req.Method) - fmt.Fprintf(c, "%s\n", s.canonicalURI(req.URL)) - fmt.Fprintf(c, "%s\n", s.canonicalQueryString(req.URL)) - fmt.Fprintf(c, "%s\n\n", s.canonicalHeaders(req.Header)) - fmt.Fprintf(c, "%s\n", s.signedHeaders(req.Header)) - fmt.Fprintf(c, "%s", s.payloadHash(req)) - return c.String() -} - -func (s *V4Signer) canonicalURI(u *url.URL) string { - canonicalPath := u.RequestURI() - if u.RawQuery != "" { - canonicalPath = canonicalPath[:len(canonicalPath)-len(u.RawQuery)-1] - } - slash := strings.HasSuffix(canonicalPath, "/") - canonicalPath = path.Clean(canonicalPath) - if canonicalPath != "/" && slash { - canonicalPath += "/" - } - return canonicalPath -} - -func (s *V4Signer) canonicalQueryString(u *url.URL) string { - var a []string - for k, vs := range u.Query() { - k = Encode(k) - for _, v := range vs { - if v == "" { - a = append(a, k+"=") - } else { - v = Encode(v) - a = append(a, k+"="+v) - } - } - } - sort.Strings(a) - return strings.Join(a, "&") -} - -func (s *V4Signer) canonicalHeaders(h http.Header) string { - i, a := 0, make([]string, len(h)) - for k, v := range h { - for j, w := range v { - v[j] = strings.Trim(w, " ") - } - sort.Strings(v) - a[i] = strings.ToLower(k) + ":" + strings.Join(v, ",") - i++ - } - sort.Strings(a) - return strings.Join(a, "\n") -} - -func (s *V4Signer) signedHeaders(h http.Header) string { - i, a := 0, make([]string, len(h)) - for k, _ := range h { - a[i] = strings.ToLower(k) - i++ - } - sort.Strings(a) - return strings.Join(a, ";") -} - -func (s *V4Signer) payloadHash(req *http.Request) string { - var b []byte - if req.Body == nil { - b = []byte("") - } else { - var err error - b, err = ioutil.ReadAll(req.Body) - if err != nil { - // TODO: I REALLY DON'T LIKE THIS PANIC!!!! - panic(err) - } - } - req.Body = ioutil.NopCloser(bytes.NewBuffer(b)) - return s.hash(string(b)) -} - -/* -stringToSign method creates the string to sign accorting to Task 2 of the AWS Signature Version 4 Signing Process. (http://goo.gl/es1PAu) - - StringToSign = - Algorithm + '\n' + - RequestDate + '\n' + - CredentialScope + '\n' + - HexEncode(Hash(CanonicalRequest)) -*/ -func (s *V4Signer) stringToSign(t time.Time, creq string) string { - w := new(bytes.Buffer) - fmt.Fprint(w, "AWS4-HMAC-SHA256\n") - fmt.Fprintf(w, "%s\n", t.Format(ISO8601BasicFormat)) - fmt.Fprintf(w, "%s\n", s.credentialScope(t)) - fmt.Fprintf(w, "%s", s.hash(creq)) - return w.String() -} - -func (s *V4Signer) credentialScope(t time.Time) string { - return fmt.Sprintf("%s/%s/%s/aws4_request", t.Format(ISO8601BasicFormatShort), s.region.Name, s.serviceName) -} - -/* -signature method calculates the AWS Signature Version 4 according to Task 3 of the AWS Signature Version 4 Signing Process. (http://goo.gl/j0Yqe1) - - signature = HexEncode(HMAC(derived-signing-key, string-to-sign)) -*/ -func (s *V4Signer) signature(t time.Time, sts string) string { - h := s.hmac(s.derivedKey(t), []byte(sts)) - return fmt.Sprintf("%x", h) -} - -/* -derivedKey method derives a signing key to be used for signing a request. - - kSecret = Your AWS Secret Access Key - kDate = HMAC("AWS4" + kSecret, Date) - kRegion = HMAC(kDate, Region) - kService = HMAC(kRegion, Service) - kSigning = HMAC(kService, "aws4_request") -*/ -func (s *V4Signer) derivedKey(t time.Time) []byte { - h := s.hmac([]byte("AWS4"+s.auth.SecretKey), []byte(t.Format(ISO8601BasicFormatShort))) - h = s.hmac(h, []byte(s.region.Name)) - h = s.hmac(h, []byte(s.serviceName)) - h = s.hmac(h, []byte("aws4_request")) - return h -} - -/* -authorization method generates the authorization header value. -*/ -func (s *V4Signer) authorization(header http.Header, t time.Time, signature string) string { - w := new(bytes.Buffer) - fmt.Fprint(w, "AWS4-HMAC-SHA256 ") - fmt.Fprintf(w, "Credential=%s/%s, ", s.auth.AccessKey, s.credentialScope(t)) - fmt.Fprintf(w, "SignedHeaders=%s, ", s.signedHeaders(header)) - fmt.Fprintf(w, "Signature=%s", signature) - return w.String() -} - -// hash method calculates the sha256 hash for a given string -func (s *V4Signer) hash(in string) string { - h := sha256.New() - fmt.Fprintf(h, "%s", in) - return fmt.Sprintf("%x", h.Sum(nil)) -} - -// hmac method calculates the sha256 hmac for a given slice of bytes -func (s *V4Signer) hmac(key, data []byte) []byte { - h := hmac.New(sha256.New, key) - h.Write(data) - return h.Sum(nil) -} diff --git a/vendor/github.com/goamz/goamz/aws/sign_test.go b/vendor/github.com/goamz/goamz/aws/sign_test.go deleted file mode 100644 index 4ce2ff9a0..000000000 --- a/vendor/github.com/goamz/goamz/aws/sign_test.go +++ /dev/null @@ -1,540 +0,0 @@ -package aws_test - -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 ExampleV4Signer() { - // 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) -} |