// queryV4Signprepares and runs the req request, signed with aws v4 signatures. // If resp is not nil, the XML data contained in the response // body will be unmarshalled on it. func (s3 *S3) queryV4Sign(req *request, resp interface{}) error { if req.headers == nil { req.headers = map[string][]string{} } err := s3.setBaseURL(req) if err != nil { return err } hreq, err := s3.setupHttpRequest(req) if err != nil { return err } // req.Host must be set for V4 signature calculation hreq.Host = hreq.URL.Host signer := aws.NewV4Signer(s3.Auth, "s3", s3.Region) signer.IncludeXAmzContentSha256 = true signer.Sign(hreq) _, err = s3.doHttpRequest(hreq, resp) return err }
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) }
func (s *V4SignerSuite) TestCases(c *check.C) { signer := aws.NewV4Signer(s.auth, "host", s.region) for _, testCase := range s.cases { req, err := http.NewRequest(testCase.request.method, "http://"+testCase.request.host+testCase.request.url, strings.NewReader(testCase.request.body)) c.Assert(err, check.IsNil, check.Commentf("Testcase: %s", testCase.label)) for _, v := range testCase.request.headers { h := strings.SplitN(v, ":", 2) req.Header.Add(h[0], h[1]) } req.Header.Set("host", req.Host) t := signer.RequestTime(req) canonicalRequest := signer.CanonicalRequest(req) c.Check(canonicalRequest, check.Equals, testCase.canonicalRequest, check.Commentf("Testcase: %s", testCase.label)) stringToSign := signer.StringToSign(t, canonicalRequest) c.Check(stringToSign, check.Equals, testCase.stringToSign, check.Commentf("Testcase: %s", testCase.label)) signature := signer.Signature(t, stringToSign) c.Check(signature, check.Equals, testCase.signature, check.Commentf("Testcase: %s", testCase.label)) authorization := signer.Authorization(req.Header, t, signature) c.Check(authorization, check.Equals, testCase.authorization, check.Commentf("Testcase: %s", testCase.label)) signer.Sign(req) c.Check(req.Header.Get("Authorization"), check.Equals, testCase.authorization, check.Commentf("Testcase: %s", testCase.label)) } }
// prepare sets up req to be delivered to S3. func (s3 *S3) prepare(req *request) error { // Copy so they can be mutated without affecting on retries. params := make(url.Values) headers := make(http.Header) for k, v := range req.params { params[k] = v } for k, v := range req.headers { headers[k] = v } req.params = params req.headers = headers if !req.prepared { req.prepared = true if req.method == "" { req.method = "GET" } if !strings.HasPrefix(req.path, "/") { req.path = "/" + req.path } err := s3.setBaseURL(req) if err != nil { return err } } if s3.Signature == aws.V2Signature && s3.Auth.Token() != "" { req.headers["X-Amz-Security-Token"] = []string{s3.Auth.Token()} } else if s3.Auth.Token() != "" { req.params.Set("X-Amz-Security-Token", s3.Auth.Token()) } if s3.Signature == aws.V2Signature { // Always sign again as it's not clear how far the // server has handled a previous attempt. u, err := url.Parse(req.baseurl) if err != nil { return err } signpathPatiallyEscaped := partiallyEscapedPath(req.path) req.headers["Host"] = []string{u.Host} req.headers["Date"] = []string{time.Now().In(time.UTC).Format(time.RFC1123)} sign(s3.Auth, req.method, signpathPatiallyEscaped, req.params, req.headers) } else { hreq, err := s3.setupHttpRequest(req) if err != nil { return err } hreq.Host = hreq.URL.Host signer := aws.NewV4Signer(s3.Auth, "s3", s3.Region) signer.IncludeXAmzContentSha256 = true signer.Sign(hreq) req.payload = hreq.Body if _, ok := headers["Content-Length"]; ok { req.headers["Content-Length"] = headers["Content-Length"] } } return nil }