diff options
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/aws')
8 files changed, 967 insertions, 19 deletions
| diff --git a/vendor/github.com/aws/aws-sdk-go/aws/config.go b/vendor/github.com/aws/aws-sdk-go/aws/config.go index fa11f99..da72935 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/config.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/config.go @@ -139,6 +139,11 @@ type Config struct {  	//  	EC2MetadataDisableTimeoutOverride *bool +	// SleepDelay is an override for the func the SDK will call when sleeping +	// during the lifecycle of a request. Specifically this will be used for +	// request delays. This value should only be used for testing. To adjust +	// the delay of a request see the aws/client.DefaultRetryer and +	// aws/request.Retryer.  	SleepDelay func(time.Duration)  } diff --git a/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go b/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go index cff5c5c..3b73a7d 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go @@ -2,7 +2,7 @@ package aws  import "time" -// String returns a pointer to of the string value passed in. +// String returns a pointer to the string value passed in.  func String(v string) *string {  	return &v  } @@ -61,7 +61,7 @@ func StringValueMap(src map[string]*string) map[string]string {  	return dst  } -// Bool returns a pointer to of the bool value passed in. +// Bool returns a pointer to the bool value passed in.  func Bool(v bool) *bool {  	return &v  } @@ -120,7 +120,7 @@ func BoolValueMap(src map[string]*bool) map[string]bool {  	return dst  } -// Int returns a pointer to of the int value passed in. +// Int returns a pointer to the int value passed in.  func Int(v int) *int {  	return &v  } @@ -179,7 +179,7 @@ func IntValueMap(src map[string]*int) map[string]int {  	return dst  } -// Int64 returns a pointer to of the int64 value passed in. +// Int64 returns a pointer to the int64 value passed in.  func Int64(v int64) *int64 {  	return &v  } @@ -238,7 +238,7 @@ func Int64ValueMap(src map[string]*int64) map[string]int64 {  	return dst  } -// Float64 returns a pointer to of the float64 value passed in. +// Float64 returns a pointer to the float64 value passed in.  func Float64(v float64) *float64 {  	return &v  } @@ -297,7 +297,7 @@ func Float64ValueMap(src map[string]*float64) map[string]float64 {  	return dst  } -// Time returns a pointer to of the time.Time value passed in. +// Time returns a pointer to the time.Time value passed in.  func Time(v time.Time) *time.Time {  	return &v  } diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go new file mode 100644 index 0000000..a4cec5c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go @@ -0,0 +1,191 @@ +// Package endpointcreds provides support for retrieving credentials from an +// arbitrary HTTP endpoint. +// +// The credentials endpoint Provider can receive both static and refreshable +// credentials that will expire. Credentials are static when an "Expiration" +// value is not provided in the endpoint's response. +// +// Static credentials will never expire once they have been retrieved. The format +// of the static credentials response: +//    { +//        "AccessKeyId" : "MUA...", +//        "SecretAccessKey" : "/7PC5om....", +//    } +// +// Refreshable credentials will expire within the "ExpiryWindow" of the Expiration +// value in the response. The format of the refreshable credentials response: +//    { +//        "AccessKeyId" : "MUA...", +//        "SecretAccessKey" : "/7PC5om....", +//        "Token" : "AQoDY....=", +//        "Expiration" : "2016-02-25T06:03:31Z" +//    } +// +// Errors should be returned in the following format and only returned with 400 +// or 500 HTTP status codes. +//    { +//        "code": "ErrorCode", +//        "message": "Helpful error message." +//    } +package endpointcreds + +import ( +	"encoding/json" +	"time" + +	"github.com/aws/aws-sdk-go/aws" +	"github.com/aws/aws-sdk-go/aws/awserr" +	"github.com/aws/aws-sdk-go/aws/client" +	"github.com/aws/aws-sdk-go/aws/client/metadata" +	"github.com/aws/aws-sdk-go/aws/credentials" +	"github.com/aws/aws-sdk-go/aws/request" +) + +// ProviderName is the name of the credentials provider. +const ProviderName = `CredentialsEndpointProvider` + +// Provider satisfies the credentials.Provider interface, and is a client to +// retrieve credentials from an arbitrary endpoint. +type Provider struct { +	staticCreds bool +	credentials.Expiry + +	// Requires a AWS Client to make HTTP requests to the endpoint with. +	// the Endpoint the request will be made to is provided by the aws.Config's +	// Endpoint value. +	Client *client.Client + +	// ExpiryWindow will allow the credentials to trigger refreshing prior to +	// the credentials actually expiring. This is beneficial so race conditions +	// with expiring credentials do not cause request to fail unexpectedly +	// due to ExpiredTokenException exceptions. +	// +	// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true +	// 10 seconds before the credentials are actually expired. +	// +	// If ExpiryWindow is 0 or less it will be ignored. +	ExpiryWindow time.Duration +} + +// NewProviderClient returns a credentials Provider for retrieving AWS credentials +// from arbitrary endpoint. +func NewProviderClient(cfg aws.Config, handlers request.Handlers, endpoint string, options ...func(*Provider)) credentials.Provider { +	p := &Provider{ +		Client: client.New( +			cfg, +			metadata.ClientInfo{ +				ServiceName: "CredentialsEndpoint", +				Endpoint:    endpoint, +			}, +			handlers, +		), +	} + +	p.Client.Handlers.Unmarshal.PushBack(unmarshalHandler) +	p.Client.Handlers.UnmarshalError.PushBack(unmarshalError) +	p.Client.Handlers.Validate.Clear() +	p.Client.Handlers.Validate.PushBack(validateEndpointHandler) + +	for _, option := range options { +		option(p) +	} + +	return p +} + +// NewCredentialsClient returns a Credentials wrapper for retrieving credentials +// from an arbitrary endpoint concurrently. The client will request the +func NewCredentialsClient(cfg aws.Config, handlers request.Handlers, endpoint string, options ...func(*Provider)) *credentials.Credentials { +	return credentials.NewCredentials(NewProviderClient(cfg, handlers, endpoint, options...)) +} + +// IsExpired returns true if the credentials retrieved are expired, or not yet +// retrieved. +func (p *Provider) IsExpired() bool { +	if p.staticCreds { +		return false +	} +	return p.Expiry.IsExpired() +} + +// Retrieve will attempt to request the credentials from the endpoint the Provider +// was configured for. And error will be returned if the retrieval fails. +func (p *Provider) Retrieve() (credentials.Value, error) { +	resp, err := p.getCredentials() +	if err != nil { +		return credentials.Value{ProviderName: ProviderName}, +			awserr.New("CredentialsEndpointError", "failed to load credentials", err) +	} + +	if resp.Expiration != nil { +		p.SetExpiration(*resp.Expiration, p.ExpiryWindow) +	} else { +		p.staticCreds = true +	} + +	return credentials.Value{ +		AccessKeyID:     resp.AccessKeyID, +		SecretAccessKey: resp.SecretAccessKey, +		SessionToken:    resp.Token, +		ProviderName:    ProviderName, +	}, nil +} + +type getCredentialsOutput struct { +	Expiration      *time.Time +	AccessKeyID     string +	SecretAccessKey string +	Token           string +} + +type errorOutput struct { +	Code    string `json:"code"` +	Message string `json:"message"` +} + +func (p *Provider) getCredentials() (*getCredentialsOutput, error) { +	op := &request.Operation{ +		Name:       "GetCredentials", +		HTTPMethod: "GET", +	} + +	out := &getCredentialsOutput{} +	req := p.Client.NewRequest(op, nil, out) +	req.HTTPRequest.Header.Set("Accept", "application/json") + +	return out, req.Send() +} + +func validateEndpointHandler(r *request.Request) { +	if len(r.ClientInfo.Endpoint) == 0 { +		r.Error = aws.ErrMissingEndpoint +	} +} + +func unmarshalHandler(r *request.Request) { +	defer r.HTTPResponse.Body.Close() + +	out := r.Data.(*getCredentialsOutput) +	if err := json.NewDecoder(r.HTTPResponse.Body).Decode(&out); err != nil { +		r.Error = awserr.New("SerializationError", +			"failed to decode endpoint credentials", +			err, +		) +	} +} + +func unmarshalError(r *request.Request) { +	defer r.HTTPResponse.Body.Close() + +	var errOut errorOutput +	if err := json.NewDecoder(r.HTTPResponse.Body).Decode(&errOut); err != nil { +		r.Error = awserr.New("SerializationError", +			"failed to decode endpoint credentials", +			err, +		) +	} + +	// Response body format is not consistent between metadata endpoints. +	// Grab the error message as a string and include that as the source error +	r.Error = awserr.New(errOut.Code, errOut.Message, nil) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go b/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go index 12be1a5..570417f 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go @@ -8,6 +8,7 @@  package defaults  import ( +	"fmt"  	"net/http"  	"os"  	"time" @@ -16,6 +17,7 @@ import (  	"github.com/aws/aws-sdk-go/aws/corehandlers"  	"github.com/aws/aws-sdk-go/aws/credentials"  	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" +	"github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"  	"github.com/aws/aws-sdk-go/aws/ec2metadata"  	"github.com/aws/aws-sdk-go/aws/request"  	"github.com/aws/aws-sdk-go/private/endpoints" @@ -83,16 +85,43 @@ func Handlers() request.Handlers {  // is available if you need to reset the credentials of an  // existing service client or session's Config.  func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials { -	endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, *cfg.Region, true) -  	return credentials.NewCredentials(&credentials.ChainProvider{  		VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),  		Providers: []credentials.Provider{  			&credentials.EnvProvider{},  			&credentials.SharedCredentialsProvider{Filename: "", Profile: ""}, -			&ec2rolecreds.EC2RoleProvider{ -				Client:       ec2metadata.NewClient(*cfg, handlers, endpoint, signingRegion), -				ExpiryWindow: 5 * time.Minute, -			}, -		}}) +			remoteCredProvider(*cfg, handlers), +		}, +	}) +} + +func remoteCredProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider { +	ecsCredURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI") + +	if len(ecsCredURI) > 0 { +		return ecsCredProvider(cfg, handlers, ecsCredURI) +	} + +	return ec2RoleProvider(cfg, handlers) +} + +func ecsCredProvider(cfg aws.Config, handlers request.Handlers, uri string) credentials.Provider { +	const host = `169.254.170.2` + +	return endpointcreds.NewProviderClient(cfg, handlers, +		fmt.Sprintf("http://%s%s", host, uri), +		func(p *endpointcreds.Provider) { +			p.ExpiryWindow = 5 * time.Minute +		}, +	) +} + +func ec2RoleProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider { +	endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, +		aws.StringValue(cfg.Region), true) + +	return &ec2rolecreds.EC2RoleProvider{ +		Client:       ec2metadata.NewClient(cfg, handlers, endpoint, signingRegion), +		ExpiryWindow: 5 * time.Minute, +	}  } diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go index 711b90c..2832aaa 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/request/request.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go @@ -39,6 +39,7 @@ type Request struct {  	RetryDelay       time.Duration  	NotHoist         bool  	SignedHeaderVals http.Header +	LastSignedAt     time.Time  	built bool  } @@ -72,15 +73,11 @@ func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers,  	if method == "" {  		method = "POST"  	} -	p := operation.HTTPPath -	if p == "" { -		p = "/" -	}  	httpReq, _ := http.NewRequest(method, "", nil)  	var err error -	httpReq.URL, err = url.Parse(clientInfo.Endpoint + p) +	httpReq.URL, err = url.Parse(clientInfo.Endpoint + operation.HTTPPath)  	if err != nil {  		httpReq.URL = &url.URL{}  		err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err) diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go new file mode 100644 index 0000000..244c86d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go @@ -0,0 +1,82 @@ +package v4 + +import ( +	"net/http" +	"strings" +) + +// validator houses a set of rule needed for validation of a +// string value +type rules []rule + +// rule interface allows for more flexible rules and just simply +// checks whether or not a value adheres to that rule +type rule interface { +	IsValid(value string) bool +} + +// IsValid will iterate through all rules and see if any rules +// apply to the value and supports nested rules +func (r rules) IsValid(value string) bool { +	for _, rule := range r { +		if rule.IsValid(value) { +			return true +		} +	} +	return false +} + +// mapRule generic rule for maps +type mapRule map[string]struct{} + +// IsValid for the map rule satisfies whether it exists in the map +func (m mapRule) IsValid(value string) bool { +	_, ok := m[value] +	return ok +} + +// whitelist is a generic rule for whitelisting +type whitelist struct { +	rule +} + +// IsValid for whitelist checks if the value is within the whitelist +func (w whitelist) IsValid(value string) bool { +	return w.rule.IsValid(value) +} + +// blacklist is a generic rule for blacklisting +type blacklist struct { +	rule +} + +// IsValid for whitelist checks if the value is within the whitelist +func (b blacklist) IsValid(value string) bool { +	return !b.rule.IsValid(value) +} + +type patterns []string + +// IsValid for patterns checks each pattern and returns if a match has +// been found +func (p patterns) IsValid(value string) bool { +	for _, pattern := range p { +		if strings.HasPrefix(http.CanonicalHeaderKey(value), pattern) { +			return true +		} +	} +	return false +} + +// inclusiveRules rules allow for rules to depend on one another +type inclusiveRules []rule + +// IsValid will return true if all rules are true +func (r inclusiveRules) IsValid(value string) bool { +	for _, rule := range r { +		if !rule.IsValid(value) { +			return false +		} +	} +	return true +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go new file mode 100644 index 0000000..f040f9c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go @@ -0,0 +1,644 @@ +// Package v4 implements signing for AWS V4 signer +// +// Provides request signing for request that need to be signed with +// AWS V4 Signatures. +package v4 + +import ( +	"bytes" +	"crypto/hmac" +	"crypto/sha256" +	"encoding/hex" +	"fmt" +	"io" +	"net/http" +	"net/url" +	"sort" +	"strconv" +	"strings" +	"time" + +	"github.com/aws/aws-sdk-go/aws" +	"github.com/aws/aws-sdk-go/aws/credentials" +	"github.com/aws/aws-sdk-go/aws/request" +	"github.com/aws/aws-sdk-go/private/protocol/rest" +) + +const ( +	authHeaderPrefix = "AWS4-HMAC-SHA256" +	timeFormat       = "20060102T150405Z" +	shortTimeFormat  = "20060102" + +	// emptyStringSHA256 is a SHA256 of an empty string +	emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855` +) + +var ignoredHeaders = rules{ +	blacklist{ +		mapRule{ +			"Authorization": struct{}{}, +			"User-Agent":    struct{}{}, +		}, +	}, +} + +// requiredSignedHeaders is a whitelist for build canonical headers. +var requiredSignedHeaders = rules{ +	whitelist{ +		mapRule{ +			"Cache-Control":                                               struct{}{}, +			"Content-Disposition":                                         struct{}{}, +			"Content-Encoding":                                            struct{}{}, +			"Content-Language":                                            struct{}{}, +			"Content-Md5":                                                 struct{}{}, +			"Content-Type":                                                struct{}{}, +			"Expires":                                                     struct{}{}, +			"If-Match":                                                    struct{}{}, +			"If-Modified-Since":                                           struct{}{}, +			"If-None-Match":                                               struct{}{}, +			"If-Unmodified-Since":                                         struct{}{}, +			"Range":                                                       struct{}{}, +			"X-Amz-Acl":                                                   struct{}{}, +			"X-Amz-Copy-Source":                                           struct{}{}, +			"X-Amz-Copy-Source-If-Match":                                  struct{}{}, +			"X-Amz-Copy-Source-If-Modified-Since":                         struct{}{}, +			"X-Amz-Copy-Source-If-None-Match":                             struct{}{}, +			"X-Amz-Copy-Source-If-Unmodified-Since":                       struct{}{}, +			"X-Amz-Copy-Source-Range":                                     struct{}{}, +			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": struct{}{}, +			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       struct{}{}, +			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   struct{}{}, +			"X-Amz-Grant-Full-control":                                    struct{}{}, +			"X-Amz-Grant-Read":                                            struct{}{}, +			"X-Amz-Grant-Read-Acp":                                        struct{}{}, +			"X-Amz-Grant-Write":                                           struct{}{}, +			"X-Amz-Grant-Write-Acp":                                       struct{}{}, +			"X-Amz-Metadata-Directive":                                    struct{}{}, +			"X-Amz-Mfa":                                                   struct{}{}, +			"X-Amz-Request-Payer":                                         struct{}{}, +			"X-Amz-Server-Side-Encryption":                                struct{}{}, +			"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id":                 struct{}{}, +			"X-Amz-Server-Side-Encryption-Customer-Algorithm":             struct{}{}, +			"X-Amz-Server-Side-Encryption-Customer-Key":                   struct{}{}, +			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":               struct{}{}, +			"X-Amz-Storage-Class":                                         struct{}{}, +			"X-Amz-Website-Redirect-Location":                             struct{}{}, +		}, +	}, +	patterns{"X-Amz-Meta-"}, +} + +// allowedHoisting is a whitelist for build query headers. The boolean value +// represents whether or not it is a pattern. +var allowedQueryHoisting = inclusiveRules{ +	blacklist{requiredSignedHeaders}, +	patterns{"X-Amz-"}, +} + +// Signer applies AWS v4 signing to given request. Use this to sign requests +// that need to be signed with AWS V4 Signatures. +type Signer struct { +	// The authentication credentials the request will be signed against. +	// This value must be set to sign requests. +	Credentials *credentials.Credentials + +	// Sets the log level the signer should use when reporting information to +	// the logger. If the logger is nil nothing will be logged. See +	// aws.LogLevelType for more information on available logging levels +	// +	// By default nothing will be logged. +	Debug aws.LogLevelType + +	// The logger loging information will be written to. If there the logger +	// is nil, nothing will be logged. +	Logger aws.Logger + +	// Disables the Signer's moving HTTP header key/value pairs from the HTTP +	// request header to the request's query string. This is most commonly used +	// with pre-signed requests preventing headers from being added to the +	// request's query string. +	DisableHeaderHoisting bool + +	// currentTimeFn returns the time value which represents the current time. +	// This value should only be used for testing. If it is nil the default +	// time.Now will be used. +	currentTimeFn func() time.Time +} + +// NewSigner returns a Signer pointer configured with the credentials and optional +// option values provided. If not options are provided the Signer will use its +// default configuration. +func NewSigner(credentials *credentials.Credentials, options ...func(*Signer)) *Signer { +	v4 := &Signer{ +		Credentials: credentials, +	} + +	for _, option := range options { +		option(v4) +	} + +	return v4 +} + +type signingCtx struct { +	ServiceName      string +	Region           string +	Request          *http.Request +	Body             io.ReadSeeker +	Query            url.Values +	Time             time.Time +	ExpireTime       time.Duration +	SignedHeaderVals http.Header + +	credValues         credentials.Value +	isPresign          bool +	formattedTime      string +	formattedShortTime string + +	bodyDigest       string +	signedHeaders    string +	canonicalHeaders string +	canonicalString  string +	credentialString string +	stringToSign     string +	signature        string +	authorization    string +} + +// Sign signs AWS v4 requests with the provided body, service name, region the +// request is made to, and time the request is signed at. The signTime allows +// you to specify that a request is signed for the future, and cannot be +// used until then. +// +// Returns a list of HTTP headers that were included in the signature or an +// error if signing the request failed. Generally for signed requests this value +// is not needed as the full request context will be captured by the http.Request +// value. It is included for reference though. +// +// Sign differs from Presign in that it will sign the request using HTTP +// header values. This type of signing is intended for http.Request values that +// will not be shared, or are shared in a way the header values on the request +// will not be lost. +// +// The requests body is an io.ReadSeeker so the SHA256 of the body can be +// generated. To bypass the signer computing the hash you can set the +// "X-Amz-Content-Sha256" header with a precomputed value. The signer will +// only compute the hash if the request header value is empty. +func (v4 Signer) Sign(r *http.Request, body io.ReadSeeker, service, region string, signTime time.Time) (http.Header, error) { +	return v4.signWithBody(r, body, service, region, 0, signTime) +} + +// Presign signs AWS v4 requests with the provided body, service name, region +// the request is made to, and time the request is signed at. The signTime +// allows you to specify that a request is signed for the future, and cannot +// be used until then. +// +// Returns a list of HTTP headers that were included in the signature or an +// error if signing the request failed. For presigned requests these headers +// and their values must be included on the HTTP request when it is made. This +// is helpful to know what header values need to be shared with the party the +// presigned request will be distributed to. +// +// Presign differs from Sign in that it will sign the request using query string +// instead of header values. This allows you to share the Presigned Request's +// URL with third parties, or distribute it throughout your system with minimal +// dependencies. +// +// Presign also takes an exp value which is the duration the +// signed request will be valid after the signing time. This is allows you to +// set when the request will expire. +// +// The requests body is an io.ReadSeeker so the SHA256 of the body can be +// generated. To bypass the signer computing the hash you can set the +// "X-Amz-Content-Sha256" header with a precomputed value. The signer will +// only compute the hash if the request header value is empty. +// +// Presigning a S3 request will not compute the body's SHA256 hash by default. +// This is done due to the general use case for S3 presigned URLs is to share +// PUT/GET capabilities. If you would like to include the body's SHA256 in the +// presigned request's signature you can set the "X-Amz-Content-Sha256" +// HTTP header and that will be included in the request's signature. +func (v4 Signer) Presign(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) { +	return v4.signWithBody(r, body, service, region, exp, signTime) +} + +func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) { +	currentTimeFn := v4.currentTimeFn +	if currentTimeFn == nil { +		currentTimeFn = time.Now +	} + +	ctx := &signingCtx{ +		Request:     r, +		Body:        body, +		Query:       r.URL.Query(), +		Time:        signTime, +		ExpireTime:  exp, +		isPresign:   exp != 0, +		ServiceName: service, +		Region:      region, +	} + +	if ctx.isRequestSigned() { +		if !v4.Credentials.IsExpired() && currentTimeFn().Before(ctx.Time.Add(10*time.Minute)) { +			// If the request is already signed, and the credentials have not +			// expired, and the request is not too old ignore the signing request. +			return ctx.SignedHeaderVals, nil +		} +		ctx.Time = currentTimeFn() +		ctx.handlePresignRemoval() +	} + +	var err error +	ctx.credValues, err = v4.Credentials.Get() +	if err != nil { +		return http.Header{}, err +	} + +	ctx.assignAmzQueryValues() +	ctx.build(v4.DisableHeaderHoisting) + +	if v4.Debug.Matches(aws.LogDebugWithSigning) { +		v4.logSigningInfo(ctx) +	} + +	return ctx.SignedHeaderVals, nil +} + +func (ctx *signingCtx) handlePresignRemoval() { +	if !ctx.isPresign { +		return +	} + +	// The credentials have expired for this request. The current signing +	// is invalid, and needs to be request because the request will fail. +	ctx.removePresign() + +	// Update the request's query string to ensure the values stays in +	// sync in the case retrieving the new credentials fails. +	ctx.Request.URL.RawQuery = ctx.Query.Encode() +} + +func (ctx *signingCtx) assignAmzQueryValues() { +	if ctx.isPresign { +		ctx.Query.Set("X-Amz-Algorithm", authHeaderPrefix) +		if ctx.credValues.SessionToken != "" { +			ctx.Query.Set("X-Amz-Security-Token", ctx.credValues.SessionToken) +		} else { +			ctx.Query.Del("X-Amz-Security-Token") +		} + +		return +	} + +	if ctx.credValues.SessionToken != "" { +		ctx.Request.Header.Set("X-Amz-Security-Token", ctx.credValues.SessionToken) +	} +} + +// SignRequestHandler is a named request handler the SDK will use to sign +// service client request with using the V4 signature. +var SignRequestHandler = request.NamedHandler{ +	Name: "v4.SignRequestHandler", Fn: SignSDKRequest, +} + +// SignSDKRequest signs an AWS request with the V4 signature. This +// request handler is bested used only with the SDK's built in service client's +// API operation requests. +// +// This function should not be used on its on its own, but in conjunction with +// an AWS service client's API operation call. To sign a standalone request +// not created by a service client's API operation method use the "Sign" or +// "Presign" functions of the "Signer" type. +// +// If the credentials of the request's config are set to +// credentials.AnonymousCredentials the request will not be signed. +func SignSDKRequest(req *request.Request) { +	signSDKRequestWithCurrTime(req, time.Now) +} +func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time) { +	// If the request does not need to be signed ignore the signing of the +	// request if the AnonymousCredentials object is used. +	if req.Config.Credentials == credentials.AnonymousCredentials { +		return +	} + +	region := req.ClientInfo.SigningRegion +	if region == "" { +		region = aws.StringValue(req.Config.Region) +	} + +	name := req.ClientInfo.SigningName +	if name == "" { +		name = req.ClientInfo.ServiceName +	} + +	v4 := NewSigner(req.Config.Credentials, func(v4 *Signer) { +		v4.Debug = req.Config.LogLevel.Value() +		v4.Logger = req.Config.Logger +		v4.DisableHeaderHoisting = req.NotHoist +		v4.currentTimeFn = curTimeFn +	}) + +	signingTime := req.Time +	if !req.LastSignedAt.IsZero() { +		signingTime = req.LastSignedAt +	} + +	signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.Body, name, region, req.ExpireTime, signingTime) +	if err != nil { +		req.Error = err +		req.SignedHeaderVals = nil +		return +	} + +	req.SignedHeaderVals = signedHeaders +	req.LastSignedAt = curTimeFn() +} + +const logSignInfoMsg = `DEBUG: Request Signiture: +---[ CANONICAL STRING  ]----------------------------- +%s +---[ STRING TO SIGN ]-------------------------------- +%s%s +-----------------------------------------------------` +const logSignedURLMsg = ` +---[ SIGNED URL ]------------------------------------ +%s` + +func (v4 *Signer) logSigningInfo(ctx *signingCtx) { +	signedURLMsg := "" +	if ctx.isPresign { +		signedURLMsg = fmt.Sprintf(logSignedURLMsg, ctx.Request.URL.String()) +	} +	msg := fmt.Sprintf(logSignInfoMsg, ctx.canonicalString, ctx.stringToSign, signedURLMsg) +	v4.Logger.Log(msg) +} + +func (ctx *signingCtx) build(disableHeaderHoisting bool) { +	ctx.buildTime()             // no depends +	ctx.buildCredentialString() // no depends + +	unsignedHeaders := ctx.Request.Header +	if ctx.isPresign { +		if !disableHeaderHoisting { +			urlValues := url.Values{} +			urlValues, unsignedHeaders = buildQuery(allowedQueryHoisting, unsignedHeaders) // no depends +			for k := range urlValues { +				ctx.Query[k] = urlValues[k] +			} +		} +	} + +	ctx.buildBodyDigest() +	ctx.buildCanonicalHeaders(ignoredHeaders, unsignedHeaders) +	ctx.buildCanonicalString() // depends on canon headers / signed headers +	ctx.buildStringToSign()    // depends on canon string +	ctx.buildSignature()       // depends on string to sign + +	if ctx.isPresign { +		ctx.Request.URL.RawQuery += "&X-Amz-Signature=" + ctx.signature +	} else { +		parts := []string{ +			authHeaderPrefix + " Credential=" + ctx.credValues.AccessKeyID + "/" + ctx.credentialString, +			"SignedHeaders=" + ctx.signedHeaders, +			"Signature=" + ctx.signature, +		} +		ctx.Request.Header.Set("Authorization", strings.Join(parts, ", ")) +	} +} + +func (ctx *signingCtx) buildTime() { +	ctx.formattedTime = ctx.Time.UTC().Format(timeFormat) +	ctx.formattedShortTime = ctx.Time.UTC().Format(shortTimeFormat) + +	if ctx.isPresign { +		duration := int64(ctx.ExpireTime / time.Second) +		ctx.Query.Set("X-Amz-Date", ctx.formattedTime) +		ctx.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10)) +	} else { +		ctx.Request.Header.Set("X-Amz-Date", ctx.formattedTime) +	} +} + +func (ctx *signingCtx) buildCredentialString() { +	ctx.credentialString = strings.Join([]string{ +		ctx.formattedShortTime, +		ctx.Region, +		ctx.ServiceName, +		"aws4_request", +	}, "/") + +	if ctx.isPresign { +		ctx.Query.Set("X-Amz-Credential", ctx.credValues.AccessKeyID+"/"+ctx.credentialString) +	} +} + +func buildQuery(r rule, header http.Header) (url.Values, http.Header) { +	query := url.Values{} +	unsignedHeaders := http.Header{} +	for k, h := range header { +		if r.IsValid(k) { +			query[k] = h +		} else { +			unsignedHeaders[k] = h +		} +	} + +	return query, unsignedHeaders +} +func (ctx *signingCtx) buildCanonicalHeaders(r rule, header http.Header) { +	var headers []string +	headers = append(headers, "host") +	for k, v := range header { +		canonicalKey := http.CanonicalHeaderKey(k) +		if !r.IsValid(canonicalKey) { +			continue // ignored header +		} +		if ctx.SignedHeaderVals == nil { +			ctx.SignedHeaderVals = make(http.Header) +		} + +		lowerCaseKey := strings.ToLower(k) +		if _, ok := ctx.SignedHeaderVals[lowerCaseKey]; ok { +			// include additional values +			ctx.SignedHeaderVals[lowerCaseKey] = append(ctx.SignedHeaderVals[lowerCaseKey], v...) +			continue +		} + +		headers = append(headers, lowerCaseKey) +		ctx.SignedHeaderVals[lowerCaseKey] = v +	} +	sort.Strings(headers) + +	ctx.signedHeaders = strings.Join(headers, ";") + +	if ctx.isPresign { +		ctx.Query.Set("X-Amz-SignedHeaders", ctx.signedHeaders) +	} + +	headerValues := make([]string, len(headers)) +	for i, k := range headers { +		if k == "host" { +			headerValues[i] = "host:" + ctx.Request.URL.Host +		} else { +			headerValues[i] = k + ":" + +				strings.Join(ctx.SignedHeaderVals[k], ",") +		} +	} + +	ctx.canonicalHeaders = strings.Join(stripExcessSpaces(headerValues), "\n") +} + +func (ctx *signingCtx) buildCanonicalString() { +	ctx.Request.URL.RawQuery = strings.Replace(ctx.Query.Encode(), "+", "%20", -1) +	uri := ctx.Request.URL.Opaque +	if uri != "" { +		uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/") +	} else { +		uri = ctx.Request.URL.Path +	} +	if uri == "" { +		uri = "/" +	} + +	if ctx.ServiceName != "s3" { +		uri = rest.EscapePath(uri, false) +	} + +	ctx.canonicalString = strings.Join([]string{ +		ctx.Request.Method, +		uri, +		ctx.Request.URL.RawQuery, +		ctx.canonicalHeaders + "\n", +		ctx.signedHeaders, +		ctx.bodyDigest, +	}, "\n") +} + +func (ctx *signingCtx) buildStringToSign() { +	ctx.stringToSign = strings.Join([]string{ +		authHeaderPrefix, +		ctx.formattedTime, +		ctx.credentialString, +		hex.EncodeToString(makeSha256([]byte(ctx.canonicalString))), +	}, "\n") +} + +func (ctx *signingCtx) buildSignature() { +	secret := ctx.credValues.SecretAccessKey +	date := makeHmac([]byte("AWS4"+secret), []byte(ctx.formattedShortTime)) +	region := makeHmac(date, []byte(ctx.Region)) +	service := makeHmac(region, []byte(ctx.ServiceName)) +	credentials := makeHmac(service, []byte("aws4_request")) +	signature := makeHmac(credentials, []byte(ctx.stringToSign)) +	ctx.signature = hex.EncodeToString(signature) +} + +func (ctx *signingCtx) buildBodyDigest() { +	hash := ctx.Request.Header.Get("X-Amz-Content-Sha256") +	if hash == "" { +		if ctx.isPresign && ctx.ServiceName == "s3" { +			hash = "UNSIGNED-PAYLOAD" +		} else if ctx.Body == nil { +			hash = emptyStringSHA256 +		} else { +			hash = hex.EncodeToString(makeSha256Reader(ctx.Body)) +		} +		if ctx.ServiceName == "s3" { +			ctx.Request.Header.Set("X-Amz-Content-Sha256", hash) +		} +	} +	ctx.bodyDigest = hash +} + +// isRequestSigned returns if the request is currently signed or presigned +func (ctx *signingCtx) isRequestSigned() bool { +	if ctx.isPresign && ctx.Query.Get("X-Amz-Signature") != "" { +		return true +	} +	if ctx.Request.Header.Get("Authorization") != "" { +		return true +	} + +	return false +} + +// unsign removes signing flags for both signed and presigned requests. +func (ctx *signingCtx) removePresign() { +	ctx.Query.Del("X-Amz-Algorithm") +	ctx.Query.Del("X-Amz-Signature") +	ctx.Query.Del("X-Amz-Security-Token") +	ctx.Query.Del("X-Amz-Date") +	ctx.Query.Del("X-Amz-Expires") +	ctx.Query.Del("X-Amz-Credential") +	ctx.Query.Del("X-Amz-SignedHeaders") +} + +func makeHmac(key []byte, data []byte) []byte { +	hash := hmac.New(sha256.New, key) +	hash.Write(data) +	return hash.Sum(nil) +} + +func makeSha256(data []byte) []byte { +	hash := sha256.New() +	hash.Write(data) +	return hash.Sum(nil) +} + +func makeSha256Reader(reader io.ReadSeeker) []byte { +	hash := sha256.New() +	start, _ := reader.Seek(0, 1) +	defer reader.Seek(start, 0) + +	io.Copy(hash, reader) +	return hash.Sum(nil) +} + +const doubleSpaces = "  " + +var doubleSpaceBytes = []byte(doubleSpaces) + +func stripExcessSpaces(headerVals []string) []string { +	vals := make([]string, len(headerVals)) +	for i, str := range headerVals { +		// Trim leading and trailing spaces +		trimmed := strings.TrimSpace(str) + +		idx := strings.Index(trimmed, doubleSpaces) +		var buf []byte +		for idx > -1 { +			// Multiple adjacent spaces found +			if buf == nil { +				// first time create the buffer +				buf = []byte(trimmed) +			} + +			stripToIdx := -1 +			for j := idx + 1; j < len(buf); j++ { +				if buf[j] != ' ' { +					buf = append(buf[:idx+1], buf[j:]...) +					stripToIdx = j +					break +				} +			} + +			if stripToIdx >= 0 { +				idx = bytes.Index(buf[stripToIdx:], doubleSpaceBytes) +				if idx >= 0 { +					idx += stripToIdx +				} +			} else { +				idx = -1 +			} +		} + +		if buf != nil { +			vals[i] = string(buf) +		} else { +			vals[i] = trimmed +		} +	} +	return vals +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go index 79a260d..97a3f57 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/version.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go @@ -5,4 +5,4 @@ package aws  const SDKName = "aws-sdk-go"  // SDKVersion is the version of this SDK -const SDKVersion = "1.1.32" +const SDKVersion = "1.2.5" | 
