client.go (4191B)
1 package client 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "time" 8 9 "github.com/aws/aws-sdk-go-v2/aws" 10 "github.com/aws/aws-sdk-go-v2/aws/middleware" 11 "github.com/aws/aws-sdk-go-v2/aws/retry" 12 awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http" 13 "github.com/aws/smithy-go" 14 smithymiddleware "github.com/aws/smithy-go/middleware" 15 smithyhttp "github.com/aws/smithy-go/transport/http" 16 ) 17 18 // ServiceID is the client identifer 19 const ServiceID = "endpoint-credentials" 20 21 // HTTPClient is a client for sending HTTP requests 22 type HTTPClient interface { 23 Do(*http.Request) (*http.Response, error) 24 } 25 26 // Options is the endpoint client configurable options 27 type Options struct { 28 // The endpoint to retrieve credentials from 29 Endpoint string 30 31 // The HTTP client to invoke API calls with. Defaults to client's default HTTP 32 // implementation if nil. 33 HTTPClient HTTPClient 34 35 // Retryer guides how HTTP requests should be retried in case of recoverable 36 // failures. When nil the API client will use a default retryer. 37 Retryer aws.Retryer 38 39 // Set of options to modify how the credentials operation is invoked. 40 APIOptions []func(*smithymiddleware.Stack) error 41 } 42 43 // Copy creates a copy of the API options. 44 func (o Options) Copy() Options { 45 to := o 46 to.APIOptions = make([]func(*smithymiddleware.Stack) error, len(o.APIOptions)) 47 copy(to.APIOptions, o.APIOptions) 48 return to 49 } 50 51 // Client is an client for retrieving AWS credentials from an endpoint 52 type Client struct { 53 options Options 54 } 55 56 // New constructs a new Client from the given options 57 func New(options Options, optFns ...func(*Options)) *Client { 58 options = options.Copy() 59 60 if options.HTTPClient == nil { 61 options.HTTPClient = awshttp.NewBuildableClient() 62 } 63 64 if options.Retryer == nil { 65 options.Retryer = retry.NewStandard() 66 } 67 68 for _, fn := range optFns { 69 fn(&options) 70 } 71 72 client := &Client{ 73 options: options, 74 } 75 76 return client 77 } 78 79 // GetCredentialsInput is the input to send with the endpoint service to receive credentials. 80 type GetCredentialsInput struct { 81 AuthorizationToken string 82 } 83 84 // GetCredentials retrieves credentials from credential endpoint 85 func (c *Client) GetCredentials(ctx context.Context, params *GetCredentialsInput, optFns ...func(*Options)) (*GetCredentialsOutput, error) { 86 stack := smithymiddleware.NewStack("GetCredentials", smithyhttp.NewStackRequest) 87 options := c.options.Copy() 88 for _, fn := range optFns { 89 fn(&options) 90 } 91 92 stack.Serialize.Add(&serializeOpGetCredential{}, smithymiddleware.After) 93 stack.Build.Add(&buildEndpoint{Endpoint: options.Endpoint}, smithymiddleware.After) 94 stack.Deserialize.Add(&deserializeOpGetCredential{}, smithymiddleware.After) 95 retry.AddRetryMiddlewares(stack, retry.AddRetryMiddlewaresOptions{Retryer: options.Retryer}) 96 middleware.AddSDKAgentKey(middleware.FeatureMetadata, ServiceID) 97 smithyhttp.AddErrorCloseResponseBodyMiddleware(stack) 98 smithyhttp.AddCloseResponseBodyMiddleware(stack) 99 100 for _, fn := range options.APIOptions { 101 if err := fn(stack); err != nil { 102 return nil, err 103 } 104 } 105 106 handler := smithymiddleware.DecorateHandler(smithyhttp.NewClientHandler(options.HTTPClient), stack) 107 result, _, err := handler.Handle(ctx, params) 108 if err != nil { 109 return nil, err 110 } 111 112 return result.(*GetCredentialsOutput), err 113 } 114 115 // GetCredentialsOutput is the response from the credential endpoint 116 type GetCredentialsOutput struct { 117 Expiration *time.Time 118 AccessKeyID string 119 SecretAccessKey string 120 Token string 121 } 122 123 // EndpointError is an error returned from the endpoint service 124 type EndpointError struct { 125 Code string `json:"code"` 126 Message string `json:"message"` 127 Fault smithy.ErrorFault `json:"-"` 128 } 129 130 // Error is the error mesage string 131 func (e *EndpointError) Error() string { 132 return fmt.Sprintf("%s: %s", e.Code, e.Message) 133 } 134 135 // ErrorCode is the error code returned by the endpoint 136 func (e *EndpointError) ErrorCode() string { 137 return e.Code 138 } 139 140 // ErrorMessage is the error message returned by the endpoint 141 func (e *EndpointError) ErrorMessage() string { 142 return e.Message 143 } 144 145 // ErrorFault indicates error fault classification 146 func (e *EndpointError) ErrorFault() smithy.ErrorFault { 147 return e.Fault 148 }