diff options
Diffstat (limited to 'vendor/github.com/goamz/goamz/sts/sts.go')
-rw-r--r-- | vendor/github.com/goamz/goamz/sts/sts.go | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/vendor/github.com/goamz/goamz/sts/sts.go b/vendor/github.com/goamz/goamz/sts/sts.go new file mode 100644 index 000000000..973969223 --- /dev/null +++ b/vendor/github.com/goamz/goamz/sts/sts.go @@ -0,0 +1,273 @@ +// +// sts: This package provides types and functions to interact with the AWS STS API +// +// Depends on https://github.com/goamz/goamz +// + +package sts + +import ( + "encoding/xml" + "fmt" + "log" + "net/http" + "net/http/httputil" + "net/url" + "strconv" + "strings" + "time" + + "github.com/goamz/goamz/aws" +) + +// The STS type encapsulates operations within a specific EC2 region. +type STS struct { + aws.Auth + aws.Region + private byte // Reserve the right of using private data. +} + +// New creates a new STS Client. +// We can only use us-east for region because AWS.. +func New(auth aws.Auth, region aws.Region) *STS { + // Make sure we can run the package tests + if region.Name == "" { + return &STS{auth, region, 0} + } + return &STS{auth, aws.Regions["us-east-1"], 0} +} + +const debug = false + +// ---------------------------------------------------------------------------- +// Request dispatching logic. + +// Error encapsulates an error returned by the AWS STS API. +// +// See http://goo.gl/zDZbuQ for more details. +type Error struct { + // HTTP status code (200, 403, ...) + StatusCode int + // STS error code + Code string + // The human-oriented error message + Message string + RequestId string `xml:"RequestID"` +} + +func (err *Error) Error() string { + if err.Code == "" { + return err.Message + } + + return fmt.Sprintf("%s (%s)", err.Message, err.Code) +} + +type xmlErrors struct { + RequestId string `xml:"RequestId"` + Errors []Error `xml:"Error"` +} + +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 +} + +func buildError(r *http.Response) error { + var ( + err Error + errors xmlErrors + ) + xml.NewDecoder(r.Body).Decode(&errors) + if len(errors.Errors) > 0 { + err = errors.Errors[0] + } + + err.RequestId = errors.RequestId + err.StatusCode = r.StatusCode + if err.Message == "" { + err.Message = r.Status + } + return &err +} + +func makeParams(action string) map[string]string { + params := make(map[string]string) + params["Action"] = action + return params +} + +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 +} + +// options for the AssumeRole function +// +// See http://goo.gl/Ld6Dbk for details +type AssumeRoleParams struct { + DurationSeconds int + ExternalId string + Policy string + RoleArn string + RoleSessionName string +} + +type AssumedRoleUser struct { + Arn string `xml:"Arn"` + AssumedRoleId string `xml:"AssumedRoleId"` +} + +type Credentials struct { + AccessKeyId string `xml:"AccessKeyId"` + Expiration time.Time `xml:"Expiration"` + SecretAccessKey string `xml:"SecretAccessKey"` + SessionToken string `xml:"SessionToken"` +} + +type AssumeRoleResult struct { + AssumedRoleUser AssumedRoleUser `xml:"AssumeRoleResult>AssumedRoleUser"` + Credentials Credentials `xml:"AssumeRoleResult>Credentials"` + PackedPolicySize int `xml:"AssumeRoleResult>PackedPolicySize"` + RequestId string `xml:"ResponseMetadata>RequestId"` +} + +// AssumeRole assumes the specified role +// +// See http://goo.gl/zDZbuQ for more details. +func (sts *STS) AssumeRole(options *AssumeRoleParams) (resp *AssumeRoleResult, err error) { + params := makeParams("AssumeRole") + + params["RoleArn"] = options.RoleArn + params["RoleSessionName"] = options.RoleSessionName + + if options.DurationSeconds != 0 { + params["DurationSeconds"] = strconv.Itoa(options.DurationSeconds) + } + if options.ExternalId != "" { + params["ExternalId"] = options.ExternalId + } + if options.Policy != "" { + params["Policy"] = options.Policy + } + + resp = new(AssumeRoleResult) + if err := sts.query(params, resp); err != nil { + return nil, err + } + return resp, nil +} + +// FederatedUser presents dentifiers for the federated user that is associated with the credentials. +// +// See http://goo.gl/uPtr7V for more details +type FederatedUser struct { + Arn string `xml:"Arn"` + FederatedUserId string `xml:"FederatedUserId"` +} + +// GetFederationToken wraps GetFederationToken response +// +// See http://goo.gl/Iujjeg for more details +type GetFederationTokenResult struct { + Credentials Credentials `xml:"GetFederationTokenResult>Credentials"` + FederatedUser FederatedUser `xml:"GetFederationTokenResult>FederatedUser"` + PackedPolicySize int `xml:"GetFederationTokenResult>PackedPolicySize"` + RequestId string `xml:"ResponseMetadata>RequestId"` +} + +// GetFederationToken returns a set of temporary credentials for an AWS account or IAM user +// +// See http://goo.gl/Iujjeg for more details +func (sts *STS) GetFederationToken(name, policy string, durationSeconds int) ( + resp *GetFederationTokenResult, err error) { + params := makeParams("GetFederationToken") + params["Name"] = name + + if durationSeconds != 0 { + params["DurationSeconds"] = strconv.Itoa(durationSeconds) + } + if policy != "" { + params["Policy"] = policy + } + + resp = new(GetFederationTokenResult) + if err := sts.query(params, resp); err != nil { + return nil, err + } + return resp, nil +} + +// GetSessionToken wraps GetSessionToken response +// +// See http://goo.gl/v8s5Y for more details +type GetSessionTokenResult struct { + Credentials Credentials `xml:"GetSessionTokenResult>Credentials"` + RequestId string `xml:"ResponseMetadata>RequestId"` +} + +// GetSessionToken returns a set of temporary credentials for an AWS account or IAM user +// +// See http://goo.gl/v8s5Y for more details +func (sts *STS) GetSessionToken(durationSeconds int, serialnNumber, tokenCode string) ( + resp *GetSessionTokenResult, err error) { + params := makeParams("GetSessionToken") + + if durationSeconds != 0 { + params["DurationSeconds"] = strconv.Itoa(durationSeconds) + } + if serialnNumber != "" { + params["SerialNumber"] = serialnNumber + } + if tokenCode != "" { + params["TokenCode"] = tokenCode + } + + resp = new(GetSessionTokenResult) + if err := sts.query(params, resp); err != nil { + return nil, err + } + return resp, nil +} |