func (s *Session) logDeprecatedNewSessionError(msg string, err error, cfgs []*aws.Config) {
	s.Config.MergeIn(cfgs...)
	s.Config.Logger.Log("ERROR:", msg, "Error:", err)
	s.Handlers.Validate.PushBack(func(r *request.Request) {
		r.Error = err
	})
}
logDeprecatedNewSessionError function enables error handling for session
package session
import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"time"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/client"
	"github.com/aws/aws-sdk-go/aws/corehandlers"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/csm"
	"github.com/aws/aws-sdk-go/aws/defaults"
	"github.com/aws/aws-sdk-go/aws/endpoints"
	"github.com/aws/aws-sdk-go/aws/request"
)
const (
	ErrCodeSharedConfig = "SharedConfigErr"
	ErrCodeLoadCustomCABundle = "LoadCustomCABundleError"
	ErrCodeLoadClientTLSCert = "LoadClientTLSCertError"
)
var ErrSharedConfigSourceCollision = awserr.New(ErrCodeSharedConfig, "only one credential type may be specified per profile: source profile, credential source, credential process, web identity token, or sso", nil)
var ErrSharedConfigECSContainerEnvVarEmpty = awserr.New(ErrCodeSharedConfig, "EcsContainer was specified as the credential_source, but 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' was not set", nil)
var ErrSharedConfigInvalidCredSource = awserr.New(ErrCodeSharedConfig, "credential source values must be EcsContainer, Ec2InstanceMetadata, or Environment", nil)
type Session struct {
	Config   *aws.Config
	Handlers request.Handlers
	options Options
}
func New(cfgs ...*aws.Config) *Session {
	envCfg, envErr := loadEnvConfig()
	if envCfg.EnableSharedConfig {
		var cfg aws.Config
		cfg.MergeIn(cfgs...)
		s, err := NewSessionWithOptions(Options{
			Config:            cfg,
			SharedConfigState: SharedConfigEnable,
		})
		if err != nil {
			msg := "failed to create session with AWS_SDK_LOAD_CONFIG enabled. " +
				"Use session.NewSession to handle errors occurring during session creation."
			s = &Session{Config: defaults.Config()}
			s.logDeprecatedNewSessionError(msg, err, cfgs)
		}
		return s
	}
	s := deprecatedNewSession(envCfg, cfgs...)
	if envErr != nil {
		msg := "failed to load env config"
		s.logDeprecatedNewSessionError(msg, envErr, cfgs)
	}
	if csmCfg, err := loadCSMConfig(envCfg, []string{}); err != nil {
		if l := s.Config.Logger; l != nil {
			l.Log(fmt.Sprintf("ERROR: failed to load CSM configuration, %v", err))
		}
	} else if csmCfg.Enabled {
		err := enableCSM(&s.Handlers, csmCfg, s.Config.Logger)
		if err != nil {
			msg := "failed to enable CSM"
			s.logDeprecatedNewSessionError(msg, err, cfgs)
		}
	}
	return s
}
func NewSession(cfgs ...*aws.Config) (*Session, error) {
	opts := Options{}
	opts.Config.MergeIn(cfgs...)
	return NewSessionWithOptions(opts)
}
type SharedConfigState int
const (
	SharedConfigStateFromEnv SharedConfigState = iota
	SharedConfigDisable
	SharedConfigEnable
)
type Options struct {
	Config aws.Config
	Profile string
	SharedConfigState SharedConfigState
	SharedConfigFiles []string
	AssumeRoleTokenProvider func() (string, error)
	AssumeRoleDuration time.Duration
	CustomCABundle io.Reader
	ClientTLSCert io.Reader
	ClientTLSKey io.Reader
	Handlers request.Handlers
	EC2IMDSEndpoint string
}
func NewSessionWithOptions(opts Options) (*Session, error) {
	var envCfg envConfig
	var err error
	if opts.SharedConfigState == SharedConfigEnable {
		envCfg, err = loadSharedEnvConfig()
		if err != nil {
			return nil, fmt.Errorf("failed to load shared config, %v", err)
		}
	} else {
		envCfg, err = loadEnvConfig()
		if err != nil {
			return nil, fmt.Errorf("failed to load environment config, %v", err)
		}
	}
	if len(opts.Profile) != 0 {
		envCfg.Profile = opts.Profile
	}
	switch opts.SharedConfigState {
	case SharedConfigDisable:
		envCfg.EnableSharedConfig = false
	case SharedConfigEnable:
		envCfg.EnableSharedConfig = true
	}
	return newSession(opts, envCfg, &opts.Config)
}
func Must(sess *Session, err error) *Session {
	if err != nil {
		panic(err)
	}
	return sess
}
func wrapEC2IMDSEndpoint(resolver endpoints.Resolver, endpoint string) endpoints.Resolver {
	return endpoints.ResolverFunc(
		func(service, region string, opts ...func(*endpoints.Options)) (
			endpoints.ResolvedEndpoint, error,
		) {
			if service == ec2MetadataServiceID {
				return endpoints.ResolvedEndpoint{
					URL:           endpoint,
					SigningName:   ec2MetadataServiceID,
					SigningRegion: region,
				}, nil
			}
			return resolver.EndpointFor(service, region)
		})
}
func deprecatedNewSession(envCfg envConfig, cfgs ...*aws.Config) *Session {
	cfg := defaults.Config()
	handlers := defaults.Handlers()
	cfg.MergeIn(cfgs...)
	if cfg.EndpointResolver == nil {
		cfg.EndpointResolver = endpoints.DefaultResolver()
	}
	if len(envCfg.EC2IMDSEndpoint) != 0 {
		cfg.EndpointResolver = wrapEC2IMDSEndpoint(cfg.EndpointResolver, envCfg.EC2IMDSEndpoint)
	}
	cfg.Credentials = defaults.CredChain(cfg, handlers)
	cfg.MergeIn(cfgs...)
	s := &Session{
		Config:   cfg,
		Handlers: handlers,
		options: Options{
			EC2IMDSEndpoint: envCfg.EC2IMDSEndpoint,
		},
	}
	initHandlers(s)
	return s
}
func enableCSM(handlers *request.Handlers, cfg csmConfig, logger aws.Logger) error {
	if logger != nil {
		logger.Log("Enabling CSM")
	}
	r, err := csm.Start(cfg.ClientID, csm.AddressWithDefaults(cfg.Host, cfg.Port))
	if err != nil {
		return err
	}
	r.InjectHandlers(handlers)
	return nil
}
func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, error) {
	cfg := defaults.Config()
	handlers := opts.Handlers
	if handlers.IsEmpty() {
		handlers = defaults.Handlers()
	}
	userCfg := &aws.Config{}
	userCfg.MergeIn(cfgs...)
	cfg.MergeIn(userCfg)
	var cfgFiles []string
	if opts.SharedConfigFiles != nil {
		cfgFiles = opts.SharedConfigFiles
	} else {
		cfgFiles = []string{envCfg.SharedConfigFile, envCfg.SharedCredentialsFile}
		if !envCfg.EnableSharedConfig {
			cfgFiles = cfgFiles[1:]
		}
	}
	sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles, envCfg.EnableSharedConfig)
	if err != nil {
		if len(envCfg.Profile) == 0 && !envCfg.EnableSharedConfig && (envCfg.Creds.HasKeys() || userCfg.Credentials != nil) {
		} else if _, ok := err.(SharedConfigProfileNotExistsError); !ok {
			return nil, err
		}
	}
	if err := mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers, opts); err != nil {
		return nil, err
	}
	if err := setTLSOptions(&opts, cfg, envCfg, sharedCfg); err != nil {
		return nil, err
	}
	s := &Session{
		Config:   cfg,
		Handlers: handlers,
		options:  opts,
	}
	initHandlers(s)
	if csmCfg, err := loadCSMConfig(envCfg, cfgFiles); err != nil {
		if l := s.Config.Logger; l != nil {
			l.Log(fmt.Sprintf("ERROR: failed to load CSM configuration, %v", err))
		}
	} else if csmCfg.Enabled {
		err = enableCSM(&s.Handlers, csmCfg, s.Config.Logger)
		if err != nil {
			return nil, err
		}
	}
	return s, nil
}
type csmConfig struct {
	Enabled  bool
	Host     string
	Port     string
	ClientID string
}
var csmProfileName = "aws_csm"
func loadCSMConfig(envCfg envConfig, cfgFiles []string) (csmConfig, error) {
	if envCfg.CSMEnabled != nil {
		if *envCfg.CSMEnabled {
			return csmConfig{
				Enabled:  true,
				ClientID: envCfg.CSMClientID,
				Host:     envCfg.CSMHost,
				Port:     envCfg.CSMPort,
			}, nil
		}
		return csmConfig{}, nil
	}
	sharedCfg, err := loadSharedConfig(csmProfileName, cfgFiles, false)
	if err != nil {
		if _, ok := err.(SharedConfigProfileNotExistsError); !ok {
			return csmConfig{}, err
		}
	}
	if sharedCfg.CSMEnabled != nil && *sharedCfg.CSMEnabled == true {
		return csmConfig{
			Enabled:  true,
			ClientID: sharedCfg.CSMClientID,
			Host:     sharedCfg.CSMHost,
			Port:     sharedCfg.CSMPort,
		}, nil
	}
	return csmConfig{}, nil
}
func setTLSOptions(opts *Options, cfg *aws.Config, envCfg envConfig, sharedCfg sharedConfig) error {
	var caBundleFilename = envCfg.CustomCABundle
	if len(caBundleFilename) == 0 {
		caBundleFilename = sharedCfg.CustomCABundle
	}
	customTLSOptions := map[string]struct {
		filename string
		field    *io.Reader
		errCode  string
	}{
		"custom CA bundle PEM":   {filename: caBundleFilename, field: &opts.CustomCABundle, errCode: ErrCodeLoadCustomCABundle},
		"custom client TLS cert": {filename: envCfg.ClientTLSCert, field: &opts.ClientTLSCert, errCode: ErrCodeLoadClientTLSCert},
		"custom client TLS key":  {filename: envCfg.ClientTLSKey, field: &opts.ClientTLSKey, errCode: ErrCodeLoadClientTLSCert},
	}
	for name, v := range customTLSOptions {
		if len(v.filename) != 0 && *v.field == nil {
			f, err := os.Open(v.filename)
			if err != nil {
				return awserr.New(v.errCode, fmt.Sprintf("failed to open %s file", name), err)
			}
			defer f.Close()
			*v.field = f
		}
	}
	if opts.CustomCABundle != nil {
		if err := loadCustomCABundle(cfg.HTTPClient, opts.CustomCABundle); err != nil {
			return err
		}
	}
	if opts.ClientTLSCert != nil && opts.ClientTLSKey != nil {
		if err := loadClientTLSCert(cfg.HTTPClient, opts.ClientTLSCert, opts.ClientTLSKey); err != nil {
			return err
		}
	} else if opts.ClientTLSCert == nil && opts.ClientTLSKey == nil {
	} else {
		return awserr.New(ErrCodeLoadClientTLSCert,
			fmt.Sprintf("client TLS cert(%t) and key(%t) must both be provided",
				opts.ClientTLSCert != nil, opts.ClientTLSKey != nil), nil)
	}
	return nil
}
func getHTTPTransport(client *http.Client) (*http.Transport, error) {
	var t *http.Transport
	switch v := client.Transport.(type) {
	case *http.Transport:
		t = v
	default:
		if client.Transport != nil {
			return nil, fmt.Errorf("unsupported transport, %T", client.Transport)
		}
	}
	if t == nil {
		t = getCustomTransport()
	}
	return t, nil
}
func loadCustomCABundle(client *http.Client, bundle io.Reader) error {
	t, err := getHTTPTransport(client)
	if err != nil {
		return awserr.New(ErrCodeLoadCustomCABundle,
			"unable to load custom CA bundle, HTTPClient's transport unsupported type", err)
	}
	p, err := loadCertPool(bundle)
	if err != nil {
		return err
	}
	if t.TLSClientConfig == nil {
		t.TLSClientConfig = &tls.Config{}
	}
	t.TLSClientConfig.RootCAs = p
	client.Transport = t
	return nil
}
func loadCertPool(r io.Reader) (*x509.CertPool, error) {
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, awserr.New(ErrCodeLoadCustomCABundle,
			"failed to read custom CA bundle PEM file", err)
	}
	p := x509.NewCertPool()
	if !p.AppendCertsFromPEM(b) {
		return nil, awserr.New(ErrCodeLoadCustomCABundle,
			"failed to load custom CA bundle PEM file", err)
	}
	return p, nil
}
func loadClientTLSCert(client *http.Client, certFile, keyFile io.Reader) error {
	t, err := getHTTPTransport(client)
	if err != nil {
		return awserr.New(ErrCodeLoadClientTLSCert,
			"unable to get usable HTTP transport from client", err)
	}
	cert, err := ioutil.ReadAll(certFile)
	if err != nil {
		return awserr.New(ErrCodeLoadClientTLSCert,
			"unable to get read client TLS cert file", err)
	}
	key, err := ioutil.ReadAll(keyFile)
	if err != nil {
		return awserr.New(ErrCodeLoadClientTLSCert,
			"unable to get read client TLS key file", err)
	}
	clientCert, err := tls.X509KeyPair(cert, key)
	if err != nil {
		return awserr.New(ErrCodeLoadClientTLSCert,
			"unable to load x509 key pair from client cert", err)
	}
	tlsCfg := t.TLSClientConfig
	if tlsCfg == nil {
		tlsCfg = &tls.Config{}
	}
	tlsCfg.Certificates = append(tlsCfg.Certificates, clientCert)
	t.TLSClientConfig = tlsCfg
	client.Transport = t
	return nil
}
func mergeConfigSrcs(cfg, userCfg *aws.Config,
	envCfg envConfig, sharedCfg sharedConfig,
	handlers request.Handlers,
	sessOpts Options,
) error {
	if len(aws.StringValue(cfg.Region)) == 0 {
		if len(envCfg.Region) > 0 {
			cfg.WithRegion(envCfg.Region)
		} else if envCfg.EnableSharedConfig && len(sharedCfg.Region) > 0 {
			cfg.WithRegion(sharedCfg.Region)
		}
	}
	if cfg.EnableEndpointDiscovery == nil {
		if envCfg.EnableEndpointDiscovery != nil {
			cfg.WithEndpointDiscovery(*envCfg.EnableEndpointDiscovery)
		} else if envCfg.EnableSharedConfig && sharedCfg.EnableEndpointDiscovery != nil {
			cfg.WithEndpointDiscovery(*sharedCfg.EnableEndpointDiscovery)
		}
	}
	mergeSTSRegionalEndpointConfig(cfg, []endpoints.STSRegionalEndpoint{
		userCfg.STSRegionalEndpoint,
		envCfg.STSRegionalEndpoint,
		sharedCfg.STSRegionalEndpoint,
		endpoints.LegacySTSEndpoint,
	})
	mergeS3UsEast1RegionalEndpointConfig(cfg, []endpoints.S3UsEast1RegionalEndpoint{
		userCfg.S3UsEast1RegionalEndpoint,
		envCfg.S3UsEast1RegionalEndpoint,
		sharedCfg.S3UsEast1RegionalEndpoint,
		endpoints.LegacyS3UsEast1Endpoint,
	})
	ec2IMDSEndpoint := sessOpts.EC2IMDSEndpoint
	if len(ec2IMDSEndpoint) == 0 {
		ec2IMDSEndpoint = envCfg.EC2IMDSEndpoint
	}
	if len(ec2IMDSEndpoint) != 0 {
		cfg.EndpointResolver = wrapEC2IMDSEndpoint(cfg.EndpointResolver, ec2IMDSEndpoint)
	}
	if cfg.Credentials == credentials.AnonymousCredentials && userCfg.Credentials == nil {
		creds, err := resolveCredentials(cfg, envCfg, sharedCfg, handlers, sessOpts)
		if err != nil {
			return err
		}
		cfg.Credentials = creds
	}
	cfg.S3UseARNRegion = userCfg.S3UseARNRegion
	if cfg.S3UseARNRegion == nil {
		cfg.S3UseARNRegion = &envCfg.S3UseARNRegion
	}
	if cfg.S3UseARNRegion == nil {
		cfg.S3UseARNRegion = &sharedCfg.S3UseARNRegion
	}
	return nil
}
func mergeSTSRegionalEndpointConfig(cfg *aws.Config, values []endpoints.STSRegionalEndpoint) {
	for _, v := range values {
		if v != endpoints.UnsetSTSEndpoint {
			cfg.STSRegionalEndpoint = v
			break
		}
	}
}
func mergeS3UsEast1RegionalEndpointConfig(cfg *aws.Config, values []endpoints.S3UsEast1RegionalEndpoint) {
	for _, v := range values {
		if v != endpoints.UnsetS3UsEast1Endpoint {
			cfg.S3UsEast1RegionalEndpoint = v
			break
		}
	}
}
func initHandlers(s *Session) {
	s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler)
	if !aws.BoolValue(s.Config.DisableParamValidation) {
		s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler)
	}
}
func (s *Session) Copy(cfgs ...*aws.Config) *Session {
	newSession := &Session{
		Config:   s.Config.Copy(cfgs...),
		Handlers: s.Handlers.Copy(),
		options:  s.options,
	}
	initHandlers(newSession)
	return newSession
}
func (s *Session) ClientConfig(service string, cfgs ...*aws.Config) client.Config {
	s = s.Copy(cfgs...)
	region := aws.StringValue(s.Config.Region)
	resolved, err := s.resolveEndpoint(service, region, s.Config)
	if err != nil {
		s.Handlers.Validate.PushBack(func(r *request.Request) {
			if len(r.ClientInfo.Endpoint) != 0 {
				return
			}
			r.Error = err
		})
	}
	return client.Config{
		Config:             s.Config,
		Handlers:           s.Handlers,
		PartitionID:        resolved.PartitionID,
		Endpoint:           resolved.URL,
		SigningRegion:      resolved.SigningRegion,
		SigningNameDerived: resolved.SigningNameDerived,
		SigningName:        resolved.SigningName,
	}
}
const ec2MetadataServiceID = "ec2metadata"
func (s *Session) resolveEndpoint(service, region string, cfg *aws.Config) (endpoints.ResolvedEndpoint, error) {
	if ep := aws.StringValue(cfg.Endpoint); len(ep) != 0 {
		return endpoints.ResolvedEndpoint{
			URL:           endpoints.AddScheme(ep, aws.BoolValue(cfg.DisableSSL)),
			SigningRegion: region,
		}, nil
	}
	resolved, err := cfg.EndpointResolver.EndpointFor(service, region,
		func(opt *endpoints.Options) {
			opt.DisableSSL = aws.BoolValue(cfg.DisableSSL)
			opt.UseDualStack = aws.BoolValue(cfg.UseDualStack)
			opt.STSRegionalEndpoint = cfg.STSRegionalEndpoint
			opt.S3UsEast1RegionalEndpoint = cfg.S3UsEast1RegionalEndpoint
			opt.ResolveUnknownService = true
		},
	)
	if err != nil {
		return endpoints.ResolvedEndpoint{}, err
	}
	return resolved, nil
}
func (s *Session) ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) client.Config {
	s = s.Copy(cfgs...)
	var resolved endpoints.ResolvedEndpoint
	if ep := aws.StringValue(s.Config.Endpoint); len(ep) > 0 {
		resolved.URL = endpoints.AddScheme(ep, aws.BoolValue(s.Config.DisableSSL))
		resolved.SigningRegion = aws.StringValue(s.Config.Region)
	}
	return client.Config{
		Config:             s.Config,
		Handlers:           s.Handlers,
		Endpoint:           resolved.URL,
		SigningRegion:      resolved.SigningRegion,
		SigningNameDerived: resolved.SigningNameDerived,
		SigningName:        resolved.SigningName,
	}
}