Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fully implement AWS4 signing support #118

Closed
wants to merge 9 commits into from
7 changes: 4 additions & 3 deletions autoscaling/autoscaling.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ func (as *AutoScaling) query(params map[string]string, resp interface{}) error {
hreq.Header.Set("X-Amz-Security-Token", token)
}

signer := aws.NewV4Signer(as.Auth, "autoscaling", as.Region)
signer.Sign(hreq)
if err = aws.SignV4(hreq, as.Auth, "autoscaling", as.Region.Name); err != nil {
return err
}

if debug {
log.Printf("%v -> {\n", hreq)
Expand All @@ -104,7 +105,7 @@ func (as *AutoScaling) query(params map[string]string, resp interface{}) error {
log.Printf("response:\n")
log.Printf("%v\n}\n", string(dump))
}
if r.StatusCode != 200 {
if r.StatusCode != http.StatusOK {
return buildError(r)
}
err = xml.NewDecoder(r.Body).Decode(resp)
Expand Down
89 changes: 35 additions & 54 deletions aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,6 @@ import (
"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.
Expand All @@ -54,13 +40,14 @@ type Region struct {
IAMEndpoint string
ELBEndpoint string
DynamoDBEndpoint string
CloudWatchServicepoint ServiceInfo
CloudWatchEndpoint string
AutoScalingEndpoint string
RDSEndpoint ServiceInfo
RDSEndpoint string
STSEndpoint string
CloudFormationEndpoint string
ECSEndpoint string
DynamoDBStreamsEndpoint string
Sign SignerFunc
}

var Regions = map[string]Region{
Expand All @@ -78,14 +65,6 @@ var Regions = map[string]Region{
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.
Expand All @@ -101,8 +80,10 @@ type AWSService interface {
// Implements a Server Query/Post API to easily query AWS services and build
// errors when desired
type Service struct {
service ServiceInfo
signer Signer
auth Auth
endpoint string
serviceName string
region Region
}

// Create a base set of params for an action
Expand All @@ -112,41 +93,29 @@ func MakeParams(action string) map[string]string {
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
// Create a new AWS service to handle making requests
func NewService(auth Auth, endpoint string, region Region, serviceName string) (*Service, error) {
return &Service{auth: auth, endpoint: endpoint, region: region, serviceName: serviceName}, nil
}

func (s *Service) Query(method, path string, params map[string]string) (resp *http.Response, err error) {
func (s *Service) Query(method, path string, params map[string]string) (*http.Response, error) {
params["Timestamp"] = time.Now().UTC().Format(time.RFC3339)
u, err := url.Parse(s.service.Endpoint)

req, err := NewRequest(method, s.endpoint, path, params)
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))
if s.region.Sign == nil {
// Default to V2 signature to maintain compatibility
err = SignV2(req, s.auth, s.serviceName)
} else {
err = s.region.Sign(req, s.auth, s.serviceName)
}
if err != nil {
return nil, err
}

return
return http.DefaultClient.Do(req)
}

func (s *Service) BuildError(r *http.Response) error {
Expand Down Expand Up @@ -261,7 +230,7 @@ func GetMetaData(path string) (contents []byte, err error) {
}
defer resp.Body.Close()

if resp.StatusCode != 200 {
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
return
}
Expand Down Expand Up @@ -432,3 +401,15 @@ func Encode(s string) string {
}
return string(e[:ei])
}

// NewRequest builds a valid request for the given endpoint, method, path and params
func NewRequest(method, endpoint, path string, params map[string]string) (*http.Request, error) {
req, err := http.NewRequest(method, endpoint+path, nil)
if err != nil {
return nil, err
}

req.URL.RawQuery = multimap(params).Encode()

return req, nil
}
2 changes: 1 addition & 1 deletion aws/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func (s *V4Signer) RequestTime(req *http.Request) time.Time {
return s.requestTime(req)
}

func (s *V4Signer) CanonicalRequest(req *http.Request) string {
func (s *V4Signer) CanonicalRequest(req *http.Request) (string, error) {
return s.canonicalRequest(req)
}

Expand Down
62 changes: 37 additions & 25 deletions aws/regions.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ var USGovWest = Region{
"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://monitoring.us-gov-west-1.amazonaws.com",
"https://autoscaling.us-gov-west-1.amazonaws.com",
ServiceInfo{"https://rds.us-gov-west-1.amazonaws.com", V2Signature},
"https://rds.us-gov-west-1.amazonaws.com",
"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",
SignV2,
}

var USEast = Region{
Expand All @@ -37,13 +38,14 @@ var USEast = Region{
"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://monitoring.us-east-1.amazonaws.com",
"https://autoscaling.us-east-1.amazonaws.com",
ServiceInfo{"https://rds.us-east-1.amazonaws.com", V2Signature},
"https://rds.us-east-1.amazonaws.com",
"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",
SignV2,
}

var USWest = Region{
Expand All @@ -60,13 +62,14 @@ var USWest = Region{
"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://monitoring.us-west-1.amazonaws.com",
"https://autoscaling.us-west-1.amazonaws.com",
ServiceInfo{"https://rds.us-west-1.amazonaws.com", V2Signature},
"https://rds.us-west-1.amazonaws.com",
"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",
SignV2,
}

var USWest2 = Region{
Expand All @@ -83,13 +86,14 @@ var USWest2 = Region{
"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://monitoring.us-west-2.amazonaws.com",
"https://autoscaling.us-west-2.amazonaws.com",
ServiceInfo{"https://rds.us-west-2.amazonaws.com", V2Signature},
"https://rds.us-west-2.amazonaws.com",
"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",
SignV2,
}

var EUWest = Region{
Expand All @@ -106,19 +110,20 @@ var EUWest = Region{
"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://monitoring.eu-west-1.amazonaws.com",
"https://autoscaling.eu-west-1.amazonaws.com",
ServiceInfo{"https://rds.eu-west-1.amazonaws.com", V2Signature},
"https://rds.eu-west-1.amazonaws.com",
"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",
SignV2,
}

var EUCentral = Region{
"eu-central-1",
"https://ec2.eu-central-1.amazonaws.com",
"https://s3-eu-central-1.amazonaws.com",
"https://s3.eu-central-1.amazonaws.com", // s3.eu.. not s3-eu.. as thats what the SSL Cert matches
"",
true,
true,
Expand All @@ -129,13 +134,14 @@ var EUCentral = Region{
"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://monitoring.eu-central-1.amazonaws.com",
"https://autoscaling.eu-central-1.amazonaws.com",
ServiceInfo{"https://rds.eu-central-1.amazonaws.com", V2Signature},
"https://rds.eu-central-1.amazonaws.com",
"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",
SignV4Region("eu-central-1"),
}

var APSoutheast = Region{
Expand All @@ -152,13 +158,14 @@ var APSoutheast = Region{
"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://monitoring.ap-southeast-1.amazonaws.com",
"https://autoscaling.ap-southeast-1.amazonaws.com",
ServiceInfo{"https://rds.ap-southeast-1.amazonaws.com", V2Signature},
"https://rds.ap-southeast-1.amazonaws.com",
"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",
SignV2,
}

var APSoutheast2 = Region{
Expand All @@ -175,13 +182,14 @@ var APSoutheast2 = Region{
"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://monitoring.ap-southeast-2.amazonaws.com",
"https://autoscaling.ap-southeast-2.amazonaws.com",
ServiceInfo{"https://rds.ap-southeast-2.amazonaws.com", V2Signature},
"https://rds.ap-southeast-2.amazonaws.com",
"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",
SignV2,
}

var APNortheast = Region{
Expand All @@ -198,13 +206,14 @@ var APNortheast = Region{
"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://monitoring.ap-northeast-1.amazonaws.com",
"https://autoscaling.ap-northeast-1.amazonaws.com",
ServiceInfo{"https://rds.ap-northeast-1.amazonaws.com", V2Signature},
"https://rds.ap-northeast-1.amazonaws.com",
"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",
SignV2,
}

var APNortheast2 = Region{
Expand All @@ -221,13 +230,14 @@ var APNortheast2 = Region{
"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://monitoring.ap-northeast-2.amazonaws.com",
"https://autoscaling.ap-northeast-2.amazonaws.com",
ServiceInfo{"https://rds.ap-northeast-2.amazonaws.com", V2Signature},
"https://rds.ap-northeast-2.amazonaws.com",
"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",
SignV4Region("eu-central-1"),
}

var SAEast = Region{
Expand All @@ -244,13 +254,14 @@ var SAEast = Region{
"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://monitoring.sa-east-1.amazonaws.com",
"https://autoscaling.sa-east-1.amazonaws.com",
ServiceInfo{"https://rds.sa-east-1.amazonaws.com", V2Signature},
"https://rds.sa-east-1.amazonaws.com",
"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",
SignV4Region("sa-east-1"),
}

var CNNorth = Region{
Expand All @@ -267,11 +278,12 @@ var CNNorth = Region{
"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://monitoring.cn-north-1.amazonaws.com.cn",
"https://autoscaling.cn-north-1.amazonaws.com.cn",
ServiceInfo{"https://rds.cn-north-1.amazonaws.com.cn", V4Signature},
"https://rds.cn-north-1.amazonaws.com.cn",
"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",
SignV4Region("cn-north-1"),
}
Loading