github.com/aavshr/aws-sdk-go@v1.41.3/aws/defaults/defaults.go (about)

     1  // Package defaults is a collection of helpers to retrieve the SDK's default
     2  // configuration and handlers.
     3  //
     4  // Generally this package shouldn't be used directly, but session.Session
     5  // instead. This package is useful when you need to reset the defaults
     6  // of a session or service client to the SDK defaults before setting
     7  // additional parameters.
     8  package defaults
     9  
    10  import (
    11  	"fmt"
    12  	"net"
    13  	"net/http"
    14  	"net/url"
    15  	"os"
    16  	"time"
    17  
    18  	"github.com/aavshr/aws-sdk-go/aws"
    19  	"github.com/aavshr/aws-sdk-go/aws/awserr"
    20  	"github.com/aavshr/aws-sdk-go/aws/corehandlers"
    21  	"github.com/aavshr/aws-sdk-go/aws/credentials"
    22  	"github.com/aavshr/aws-sdk-go/aws/credentials/ec2rolecreds"
    23  	"github.com/aavshr/aws-sdk-go/aws/credentials/endpointcreds"
    24  	"github.com/aavshr/aws-sdk-go/aws/ec2metadata"
    25  	"github.com/aavshr/aws-sdk-go/aws/endpoints"
    26  	"github.com/aavshr/aws-sdk-go/aws/request"
    27  	"github.com/aavshr/aws-sdk-go/internal/shareddefaults"
    28  )
    29  
    30  // A Defaults provides a collection of default values for SDK clients.
    31  type Defaults struct {
    32  	Config   *aws.Config
    33  	Handlers request.Handlers
    34  }
    35  
    36  // Get returns the SDK's default values with Config and handlers pre-configured.
    37  func Get() Defaults {
    38  	cfg := Config()
    39  	handlers := Handlers()
    40  	cfg.Credentials = CredChain(cfg, handlers)
    41  
    42  	return Defaults{
    43  		Config:   cfg,
    44  		Handlers: handlers,
    45  	}
    46  }
    47  
    48  // Config returns the default configuration without credentials.
    49  // To retrieve a config with credentials also included use
    50  // `defaults.Get().Config` instead.
    51  //
    52  // Generally you shouldn't need to use this method directly, but
    53  // is available if you need to reset the configuration of an
    54  // existing service client or session.
    55  func Config() *aws.Config {
    56  	return aws.NewConfig().
    57  		WithCredentials(credentials.AnonymousCredentials).
    58  		WithRegion(os.Getenv("AWS_REGION")).
    59  		WithHTTPClient(http.DefaultClient).
    60  		WithMaxRetries(aws.UseServiceDefaultRetries).
    61  		WithLogger(aws.NewDefaultLogger()).
    62  		WithLogLevel(aws.LogOff).
    63  		WithEndpointResolver(endpoints.DefaultResolver())
    64  }
    65  
    66  // Handlers returns the default request handlers.
    67  //
    68  // Generally you shouldn't need to use this method directly, but
    69  // is available if you need to reset the request handlers of an
    70  // existing service client or session.
    71  func Handlers() request.Handlers {
    72  	var handlers request.Handlers
    73  
    74  	handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
    75  	handlers.Validate.AfterEachFn = request.HandlerListStopOnError
    76  	handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
    77  	handlers.Build.PushBackNamed(corehandlers.AddHostExecEnvUserAgentHander)
    78  	handlers.Build.AfterEachFn = request.HandlerListStopOnError
    79  	handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
    80  	handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler)
    81  	handlers.Send.PushBackNamed(corehandlers.SendHandler)
    82  	handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
    83  	handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
    84  
    85  	return handlers
    86  }
    87  
    88  // CredChain returns the default credential chain.
    89  //
    90  // Generally you shouldn't need to use this method directly, but
    91  // is available if you need to reset the credentials of an
    92  // existing service client or session's Config.
    93  func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
    94  	return credentials.NewCredentials(&credentials.ChainProvider{
    95  		VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
    96  		Providers:     CredProviders(cfg, handlers),
    97  	})
    98  }
    99  
   100  // CredProviders returns the slice of providers used in
   101  // the default credential chain.
   102  //
   103  // For applications that need to use some other provider (for example use
   104  // different  environment variables for legacy reasons) but still fall back
   105  // on the default chain of providers. This allows that default chaint to be
   106  // automatically updated
   107  func CredProviders(cfg *aws.Config, handlers request.Handlers) []credentials.Provider {
   108  	return []credentials.Provider{
   109  		&credentials.EnvProvider{},
   110  		&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
   111  		RemoteCredProvider(*cfg, handlers),
   112  	}
   113  }
   114  
   115  const (
   116  	httpProviderAuthorizationEnvVar = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
   117  	httpProviderEnvVar              = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
   118  )
   119  
   120  // RemoteCredProvider returns a credentials provider for the default remote
   121  // endpoints such as EC2 or ECS Roles.
   122  func RemoteCredProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
   123  	if u := os.Getenv(httpProviderEnvVar); len(u) > 0 {
   124  		return localHTTPCredProvider(cfg, handlers, u)
   125  	}
   126  
   127  	if uri := os.Getenv(shareddefaults.ECSCredsProviderEnvVar); len(uri) > 0 {
   128  		u := fmt.Sprintf("%s%s", shareddefaults.ECSContainerCredentialsURI, uri)
   129  		return httpCredProvider(cfg, handlers, u)
   130  	}
   131  
   132  	return ec2RoleProvider(cfg, handlers)
   133  }
   134  
   135  var lookupHostFn = net.LookupHost
   136  
   137  func isLoopbackHost(host string) (bool, error) {
   138  	ip := net.ParseIP(host)
   139  	if ip != nil {
   140  		return ip.IsLoopback(), nil
   141  	}
   142  
   143  	// Host is not an ip, perform lookup
   144  	addrs, err := lookupHostFn(host)
   145  	if err != nil {
   146  		return false, err
   147  	}
   148  	for _, addr := range addrs {
   149  		if !net.ParseIP(addr).IsLoopback() {
   150  			return false, nil
   151  		}
   152  	}
   153  
   154  	return true, nil
   155  }
   156  
   157  func localHTTPCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
   158  	var errMsg string
   159  
   160  	parsed, err := url.Parse(u)
   161  	if err != nil {
   162  		errMsg = fmt.Sprintf("invalid URL, %v", err)
   163  	} else {
   164  		host := aws.URLHostname(parsed)
   165  		if len(host) == 0 {
   166  			errMsg = "unable to parse host from local HTTP cred provider URL"
   167  		} else if isLoopback, loopbackErr := isLoopbackHost(host); loopbackErr != nil {
   168  			errMsg = fmt.Sprintf("failed to resolve host %q, %v", host, loopbackErr)
   169  		} else if !isLoopback {
   170  			errMsg = fmt.Sprintf("invalid endpoint host, %q, only loopback hosts are allowed.", host)
   171  		}
   172  	}
   173  
   174  	if len(errMsg) > 0 {
   175  		if cfg.Logger != nil {
   176  			cfg.Logger.Log("Ignoring, HTTP credential provider", errMsg, err)
   177  		}
   178  		return credentials.ErrorProvider{
   179  			Err:          awserr.New("CredentialsEndpointError", errMsg, err),
   180  			ProviderName: endpointcreds.ProviderName,
   181  		}
   182  	}
   183  
   184  	return httpCredProvider(cfg, handlers, u)
   185  }
   186  
   187  func httpCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
   188  	return endpointcreds.NewProviderClient(cfg, handlers, u,
   189  		func(p *endpointcreds.Provider) {
   190  			p.ExpiryWindow = 5 * time.Minute
   191  			p.AuthorizationToken = os.Getenv(httpProviderAuthorizationEnvVar)
   192  		},
   193  	)
   194  }
   195  
   196  func ec2RoleProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
   197  	resolver := cfg.EndpointResolver
   198  	if resolver == nil {
   199  		resolver = endpoints.DefaultResolver()
   200  	}
   201  
   202  	e, _ := resolver.EndpointFor(endpoints.Ec2metadataServiceID, "")
   203  	return &ec2rolecreds.EC2RoleProvider{
   204  		Client:       ec2metadata.NewClient(cfg, handlers, e.URL, e.SigningRegion),
   205  		ExpiryWindow: 5 * time.Minute,
   206  	}
   207  }