Example #1
0
File: s3.go Project: noah10/goamz
// 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))
	}
}
Example #4
0
func (s *SQS) query(queueUrl string, params map[string]string, resp interface{}) (err error) {
	var url_ *url.URL

	if queueUrl != "" && len(queueUrl) > len(s.Region.SQSEndpoint) {
		url_, err = url.Parse(queueUrl)
	} else {
		url_, err = url.Parse(s.Region.SQSEndpoint)
	}

	if err != nil {
		return err
	}

	params["Version"] = "2012-11-05"
	hreq, err := http.NewRequest("POST", url_.String(), strings.NewReader(multimap(params).Encode()))
	if err != nil {
		return err
	}

	// respect the environmnet's proxy settings
	if prox_url, _ := http.ProxyFromEnvironment(hreq); prox_url != nil {
		hreq.URL = prox_url
	}

	hreq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))

	if s.Auth.Token() != "" {
		hreq.Header.Set("X-Amz-Security-Token", s.Auth.Token())
	}

	signer := aws.NewV4Signer(s.Auth, "sqs", s.Region)
	signer.Sign(hreq)

	r, err := http.DefaultClient.Do(hreq)

	if err != nil {
		return err
	}

	defer r.Body.Close()

	if debug {
		dump, _ := httputil.DumpResponse(r, true)
		log.Printf("DUMP:\n", string(dump))
	}

	if r.StatusCode != 200 {
		return buildError(r)
	}
	err = xml.NewDecoder(r.Body).Decode(resp)
	io.Copy(ioutil.Discard, r.Body)

	return err
}
Example #5
0
func (rds *RDS) DownloadCompleteDBLogFile(id, filename string) (io.ReadCloser, error) {
	url := fmt.Sprintf(
		"%s/v13/downloadCompleteLogFile/%s/%s",
		rds.Region.RDSEndpoint.Endpoint,
		id,
		filename,
	)
	hreq, err := http.NewRequest("GET", url, nil)
	if err != nil {
		if debug {
			log.Printf("Error http.NewRequest GET %s", url)
		}
		return nil, err
	}
	token := rds.Auth.Token()
	if token != "" {
		hreq.Header.Set("X-Amz-Security-Token", token)
	}
	hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))
	signer := aws.NewV4Signer(rds.Auth, "rds", rds.Region)
	signer.Sign(hreq)
	resp, err := http.DefaultClient.Do(hreq)
	if err != nil {
		if debug {
			log.Print("Error calling Amazon")
		}
		return nil, err
	}
	if resp.StatusCode == 200 {
		return resp.Body, nil
	} else {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			if debug {
				log.Printf("Could not read response body")
			}
			return nil, err
		}
		msg := fmt.Sprintf(
			"Responce:\n\tStatusCode: %d\n\tBody: %s\n",
			resp.StatusCode,
			string(body),
		)
		if debug {
			log.Printf(msg)
		}
		err = errors.New(msg)
		return nil, err
	}
}
Example #6
0
func (k *Kinesis) query(target string, query *Query) ([]byte, error) {
	data := strings.NewReader(query.String())
	hreq, err := http.NewRequest("POST", k.Region.KinesisEndpoint+"/", data)

	if err != nil {
		return nil, err
	}

	hreq.Header.Set("Content-Type", "application/x-amz-json-1.1")
	hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))
	hreq.Header.Set("X-Amz-Target", target)

	if k.Auth.Token() != "" {
		hreq.Header.Set("X-Amz-Security-Token", k.Auth.Token())
	}

	signer := aws.NewV4Signer(k.Auth, "kinesis", k.Region)
	signer.Sign(hreq)

	resp, err := http.DefaultClient.Do(hreq)

	if err != nil {
		log.Printf("kinesis: Error calling Amazon\n: %v", err)
		return nil, err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("kinesis: Could not read response body\n")
		return nil, err
	}

	if debug {
		log.Printf("kinesis: response:\n")
		log.Printf("kinesis: %s", string(body))
	}

	// "A response code of 200 indicates the operation was successful."
	if resp.StatusCode != 200 {
		err = buildError(resp, body)
		return nil, err
	}

	return body, nil
}
Example #7
0
func (sts *STS) query(params map[string]string, resp interface{}) error {
	params["Version"] = "2011-06-15"

	data := strings.NewReader(multimap(params).Encode())

	hreq, err := http.NewRequest("POST", sts.Region.STSEndpoint+"/", data)
	if err != nil {
		return err
	}

	hreq.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")

	token := sts.Auth.Token()
	if token != "" {
		hreq.Header.Set("X-Amz-Security-Token", token)
	}

	signer := aws.NewV4Signer(sts.Auth, "sts", sts.Region)
	signer.Sign(hreq)

	if debug {
		log.Printf("%v -> {\n", hreq)
	}
	r, err := http.DefaultClient.Do(hreq)

	if err != nil {
		log.Printf("Error calling Amazon")
		return err
	}

	defer r.Body.Close()

	if debug {
		dump, _ := httputil.DumpResponse(r, true)
		log.Printf("response:\n")
		log.Printf("%v\n}\n", string(dump))
	}
	if r.StatusCode != 200 {
		return buildError(r)
	}
	err = xml.NewDecoder(r.Body).Decode(resp)
	return err
}
Example #8
0
func (k *KMS) query(requstInfo KMSAction) ([]byte, error) {
	b, err := json.Marshal(requstInfo)
	if err != nil {
		return nil, err
	}

	hreq, err := http.NewRequest(httpMethod, k.Region.KMSEndpoint+"/", bytes.NewBuffer(b))
	if err != nil {
		return nil, err
	}

	hreq.Header.Set("Content-Type", contentType)
	hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))
	hreq.Header.Set("X-Amz-Target", targetPrefix+requstInfo.ActionName())

	if k.Auth.Token() != "" {
		hreq.Header.Set("X-Amz-Security-Token", k.Auth.Token())
	}

	//All KMS operations require Signature Version 4
	//http://docs.aws.amazon.com/kms/latest/APIReference/Welcome.html
	signer := aws.NewV4Signer(k.Auth, serverName, k.Region)
	signer.Sign(hreq)

	r, err := http.DefaultClient.Do(hreq)

	if err != nil {
		return nil, err
	}

	body, _ := ioutil.ReadAll(r.Body)

	defer r.Body.Close()

	if r.StatusCode != 200 {
		return nil, buildError(body, r.StatusCode)
	}

	return body, err
}
Example #9
0
func (ec *ElastiCache) query(query string, response interface{}) error {
	url := ec.Region.ElastiCacheEndpoint + "/?" + query

	hreq, err := http.NewRequest("POST", url, nil)
	if err != nil {
		return err
	}

	hreq.Header.Set("Content-Type", "application/x-amz-json-1.0")
	hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))

	token := ec.Auth.Token()
	if token != "" {
		hreq.Header.Set("X-Amz-Security-Token", token)
	}

	signer := aws.NewV4Signer(ec.Auth, "elasticache", ec.Region)
	signer.Sign(hreq)

	resp, err := http.DefaultClient.Do(hreq)

	if err != nil {
		return err
	}

	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return buildError(resp)
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	return xml.Unmarshal(b, &response)
}
Example #10
0
File: s3.go Project: noah10/goamz
// 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
}
Example #11
0
func (s *RetrySuite) TestRetryPolicy(c *check.C) {
	// Save off the real endpoint, and then point it at a local proxy.
	endpoint := s.table.Server.Region.DynamoDBEndpoint
	policy := s.table.Server.RetryPolicy
	defer func() {
		s.table.Server.Region.DynamoDBEndpoint = endpoint
		s.table.Server.RetryPolicy = policy
	}()
	numCalls := 0
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		numCalls++
		// Fake a failure the requested amount of times.
		if numCalls <= s.NumCallsToFail {
			b, _ := json.Marshal(map[string]interface{}{
				"__type": s.ErrorType,
				"Code":   "blah",
			})
			w.WriteHeader(s.ErrorStatusCode)
			io.WriteString(w, string(b))
			return
		}

		// Otherwise, proxy to actual DynamoDB endpoint. We reformat the request
		// with the same content.
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			c.Fatal(err)
		}
		newr, err := http.NewRequest("POST", endpoint+"/", strings.NewReader(string(body)))
		headersToKeep := map[string]bool{
			"Content-Type":         true,
			"X-Amz-Date":           true,
			"X-Amz-Target":         true,
			"X-Amz-Security-Token": true,
		}
		for h, _ := range r.Header {
			if _, ok := headersToKeep[h]; ok {
				newr.Header.Set(h, r.Header.Get(h))
			}
		}

		signer := aws.NewV4Signer(s.table.Server.Auth, "dynamodb", s.table.Server.Region)
		signer.Sign(newr)

		resp, err := http.DefaultClient.Do(newr)
		if err != nil {
			c.Fatal(err)
		}
		body, err = ioutil.ReadAll(resp.Body)
		defer resp.Body.Close()
		if err != nil {
			c.Fatal(err)
		}
		w.WriteHeader(resp.StatusCode)
		io.WriteString(w, string(body))
	}))
	defer server.Close()
	rp := &retryPolicy{}
	s.table.Server.RetryPolicy = rp
	s.table.Server.Region.DynamoDBEndpoint = server.URL

	// Now make the request.
	k := &Key{HashKey: "NewHashKeyVal"}
	in := map[string]interface{}{
		"Attr1": "Attr1Val",
		"Attr2": 12,
	}
	err := s.table.PutDocument(k, in)
	if s.ExpectError {
		if err == nil {
			c.Fatalf("Expected error")
		}
	} else {
		if err != nil {
			c.Fatal(err)
		}
	}
	if rp.numCalls != s.NumCallsToFail {
		c.Fatalf("Expected %d failed calls, saw %d", s.NumCallsToFail, rp.numCalls)
	}
}
Example #12
0
func (s *Server) queryServer(target string, query Query) ([]byte, error) {
	numRetries := 0
	for {
		qs, err := query.Marshal()
		if err != nil {
			return nil, err
		}
		data := bytes.NewReader(qs)

		hreq, err := http.NewRequest("POST", s.Region.DynamoDBEndpoint+"/", data)
		if err != nil {
			return nil, err
		}

		hreq.Header.Set("Content-Type", "application/x-amz-json-1.0")
		hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))
		hreq.Header.Set("X-Amz-Target", target)

		token := s.Auth.Token()
		if token != "" {
			hreq.Header.Set("X-Amz-Security-Token", token)
		}

		signer := aws.NewV4Signer(s.Auth, "dynamodb", s.Region)
		signer.Sign(hreq)

		resp, err := http.DefaultClient.Do(hreq)
		if err != nil {
			if s.RetryPolicy.ShouldRetry(target, resp, err, numRetries) {
				time.Sleep(s.RetryPolicy.Delay(target, resp, err, numRetries))
				numRetries++
				continue
			}
			return nil, err
		}

		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			if s.RetryPolicy.ShouldRetry(target, resp, err, numRetries) {
				time.Sleep(s.RetryPolicy.Delay(target, resp, err, numRetries))
				numRetries++
				continue
			}
			return nil, err
		}

		// http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ErrorHandling.html
		// "A response code of 200 indicates the operation was successful."
		if resp.StatusCode != 200 {
			err := buildError(resp, body)
			if s.RetryPolicy.ShouldRetry(target, resp, err, numRetries) {
				time.Sleep(s.RetryPolicy.Delay(target, resp, err, numRetries))
				numRetries++
				continue
			}
			return nil, err
		}

		return body, nil
	}
}