session.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. package session
  2. import (
  3. "crypto/tls"
  4. "crypto/x509"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "net/http"
  9. "os"
  10. "github.com/aws/aws-sdk-go/aws"
  11. "github.com/aws/aws-sdk-go/aws/awserr"
  12. "github.com/aws/aws-sdk-go/aws/client"
  13. "github.com/aws/aws-sdk-go/aws/corehandlers"
  14. "github.com/aws/aws-sdk-go/aws/credentials"
  15. "github.com/aws/aws-sdk-go/aws/credentials/stscreds"
  16. "github.com/aws/aws-sdk-go/aws/defaults"
  17. "github.com/aws/aws-sdk-go/aws/endpoints"
  18. "github.com/aws/aws-sdk-go/aws/request"
  19. )
  20. // A Session provides a central location to create service clients from and
  21. // store configurations and request handlers for those services.
  22. //
  23. // Sessions are safe to create service clients concurrently, but it is not safe
  24. // to mutate the Session concurrently.
  25. //
  26. // The Session satisfies the service client's client.ClientConfigProvider.
  27. type Session struct {
  28. Config *aws.Config
  29. Handlers request.Handlers
  30. }
  31. // New creates a new instance of the handlers merging in the provided configs
  32. // on top of the SDK's default configurations. Once the Session is created it
  33. // can be mutated to modify the Config or Handlers. The Session is safe to be
  34. // read concurrently, but it should not be written to concurrently.
  35. //
  36. // If the AWS_SDK_LOAD_CONFIG environment is set to a truthy value, the New
  37. // method could now encounter an error when loading the configuration. When
  38. // The environment variable is set, and an error occurs, New will return a
  39. // session that will fail all requests reporting the error that occurred while
  40. // loading the session. Use NewSession to get the error when creating the
  41. // session.
  42. //
  43. // If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
  44. // the shared config file (~/.aws/config) will also be loaded, in addition to
  45. // the shared credentials file (~/.aws/credentials). Values set in both the
  46. // shared config, and shared credentials will be taken from the shared
  47. // credentials file.
  48. //
  49. // Deprecated: Use NewSession functions to create sessions instead. NewSession
  50. // has the same functionality as New except an error can be returned when the
  51. // func is called instead of waiting to receive an error until a request is made.
  52. func New(cfgs ...*aws.Config) *Session {
  53. // load initial config from environment
  54. envCfg := loadEnvConfig()
  55. if envCfg.EnableSharedConfig {
  56. s, err := newSession(Options{}, envCfg, cfgs...)
  57. if err != nil {
  58. // Old session.New expected all errors to be discovered when
  59. // a request is made, and would report the errors then. This
  60. // needs to be replicated if an error occurs while creating
  61. // the session.
  62. msg := "failed to create session with AWS_SDK_LOAD_CONFIG enabled. " +
  63. "Use session.NewSession to handle errors occurring during session creation."
  64. // Session creation failed, need to report the error and prevent
  65. // any requests from succeeding.
  66. s = &Session{Config: defaults.Config()}
  67. s.Config.MergeIn(cfgs...)
  68. s.Config.Logger.Log("ERROR:", msg, "Error:", err)
  69. s.Handlers.Validate.PushBack(func(r *request.Request) {
  70. r.Error = err
  71. })
  72. }
  73. return s
  74. }
  75. return deprecatedNewSession(cfgs...)
  76. }
  77. // NewSession returns a new Session created from SDK defaults, config files,
  78. // environment, and user provided config files. Once the Session is created
  79. // it can be mutated to modify the Config or Handlers. The Session is safe to
  80. // be read concurrently, but it should not be written to concurrently.
  81. //
  82. // If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
  83. // the shared config file (~/.aws/config) will also be loaded in addition to
  84. // the shared credentials file (~/.aws/credentials). Values set in both the
  85. // shared config, and shared credentials will be taken from the shared
  86. // credentials file. Enabling the Shared Config will also allow the Session
  87. // to be built with retrieving credentials with AssumeRole set in the config.
  88. //
  89. // See the NewSessionWithOptions func for information on how to override or
  90. // control through code how the Session will be created. Such as specifying the
  91. // config profile, and controlling if shared config is enabled or not.
  92. func NewSession(cfgs ...*aws.Config) (*Session, error) {
  93. opts := Options{}
  94. opts.Config.MergeIn(cfgs...)
  95. return NewSessionWithOptions(opts)
  96. }
  97. // SharedConfigState provides the ability to optionally override the state
  98. // of the session's creation based on the shared config being enabled or
  99. // disabled.
  100. type SharedConfigState int
  101. const (
  102. // SharedConfigStateFromEnv does not override any state of the
  103. // AWS_SDK_LOAD_CONFIG env var. It is the default value of the
  104. // SharedConfigState type.
  105. SharedConfigStateFromEnv SharedConfigState = iota
  106. // SharedConfigDisable overrides the AWS_SDK_LOAD_CONFIG env var value
  107. // and disables the shared config functionality.
  108. SharedConfigDisable
  109. // SharedConfigEnable overrides the AWS_SDK_LOAD_CONFIG env var value
  110. // and enables the shared config functionality.
  111. SharedConfigEnable
  112. )
  113. // Options provides the means to control how a Session is created and what
  114. // configuration values will be loaded.
  115. //
  116. type Options struct {
  117. // Provides config values for the SDK to use when creating service clients
  118. // and making API requests to services. Any value set in with this field
  119. // will override the associated value provided by the SDK defaults,
  120. // environment or config files where relevant.
  121. //
  122. // If not set, configuration values from from SDK defaults, environment,
  123. // config will be used.
  124. Config aws.Config
  125. // Overrides the config profile the Session should be created from. If not
  126. // set the value of the environment variable will be loaded (AWS_PROFILE,
  127. // or AWS_DEFAULT_PROFILE if the Shared Config is enabled).
  128. //
  129. // If not set and environment variables are not set the "default"
  130. // (DefaultSharedConfigProfile) will be used as the profile to load the
  131. // session config from.
  132. Profile string
  133. // Instructs how the Session will be created based on the AWS_SDK_LOAD_CONFIG
  134. // environment variable. By default a Session will be created using the
  135. // value provided by the AWS_SDK_LOAD_CONFIG environment variable.
  136. //
  137. // Setting this value to SharedConfigEnable or SharedConfigDisable
  138. // will allow you to override the AWS_SDK_LOAD_CONFIG environment variable
  139. // and enable or disable the shared config functionality.
  140. SharedConfigState SharedConfigState
  141. // Ordered list of files the session will load configuration from.
  142. // It will override environment variable AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE.
  143. SharedConfigFiles []string
  144. // When the SDK's shared config is configured to assume a role with MFA
  145. // this option is required in order to provide the mechanism that will
  146. // retrieve the MFA token. There is no default value for this field. If
  147. // it is not set an error will be returned when creating the session.
  148. //
  149. // This token provider will be called when ever the assumed role's
  150. // credentials need to be refreshed. Within the context of service clients
  151. // all sharing the same session the SDK will ensure calls to the token
  152. // provider are atomic. When sharing a token provider across multiple
  153. // sessions additional synchronization logic is needed to ensure the
  154. // token providers do not introduce race conditions. It is recommend to
  155. // share the session where possible.
  156. //
  157. // stscreds.StdinTokenProvider is a basic implementation that will prompt
  158. // from stdin for the MFA token code.
  159. //
  160. // This field is only used if the shared configuration is enabled, and
  161. // the config enables assume role wit MFA via the mfa_serial field.
  162. AssumeRoleTokenProvider func() (string, error)
  163. // Reader for a custom Credentials Authority (CA) bundle in PEM format that
  164. // the SDK will use instead of the default system's root CA bundle. Use this
  165. // only if you want to replace the CA bundle the SDK uses for TLS requests.
  166. //
  167. // Enabling this option will attempt to merge the Transport into the SDK's HTTP
  168. // client. If the client's Transport is not a http.Transport an error will be
  169. // returned. If the Transport's TLS config is set this option will cause the SDK
  170. // to overwrite the Transport's TLS config's RootCAs value. If the CA
  171. // bundle reader contains multiple certificates all of them will be loaded.
  172. //
  173. // The Session option CustomCABundle is also available when creating sessions
  174. // to also enable this feature. CustomCABundle session option field has priority
  175. // over the AWS_CA_BUNDLE environment variable, and will be used if both are set.
  176. CustomCABundle io.Reader
  177. }
  178. // NewSessionWithOptions returns a new Session created from SDK defaults, config files,
  179. // environment, and user provided config files. This func uses the Options
  180. // values to configure how the Session is created.
  181. //
  182. // If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
  183. // the shared config file (~/.aws/config) will also be loaded in addition to
  184. // the shared credentials file (~/.aws/credentials). Values set in both the
  185. // shared config, and shared credentials will be taken from the shared
  186. // credentials file. Enabling the Shared Config will also allow the Session
  187. // to be built with retrieving credentials with AssumeRole set in the config.
  188. //
  189. // // Equivalent to session.New
  190. // sess := session.Must(session.NewSessionWithOptions(session.Options{}))
  191. //
  192. // // Specify profile to load for the session's config
  193. // sess := session.Must(session.NewSessionWithOptions(session.Options{
  194. // Profile: "profile_name",
  195. // }))
  196. //
  197. // // Specify profile for config and region for requests
  198. // sess := session.Must(session.NewSessionWithOptions(session.Options{
  199. // Config: aws.Config{Region: aws.String("us-east-1")},
  200. // Profile: "profile_name",
  201. // }))
  202. //
  203. // // Force enable Shared Config support
  204. // sess := session.Must(session.NewSessionWithOptions(session.Options{
  205. // SharedConfigState: session.SharedConfigEnable,
  206. // }))
  207. func NewSessionWithOptions(opts Options) (*Session, error) {
  208. var envCfg envConfig
  209. if opts.SharedConfigState == SharedConfigEnable {
  210. envCfg = loadSharedEnvConfig()
  211. } else {
  212. envCfg = loadEnvConfig()
  213. }
  214. if len(opts.Profile) > 0 {
  215. envCfg.Profile = opts.Profile
  216. }
  217. switch opts.SharedConfigState {
  218. case SharedConfigDisable:
  219. envCfg.EnableSharedConfig = false
  220. case SharedConfigEnable:
  221. envCfg.EnableSharedConfig = true
  222. }
  223. if len(envCfg.SharedCredentialsFile) == 0 {
  224. envCfg.SharedCredentialsFile = defaults.SharedCredentialsFilename()
  225. }
  226. if len(envCfg.SharedConfigFile) == 0 {
  227. envCfg.SharedConfigFile = defaults.SharedConfigFilename()
  228. }
  229. // Only use AWS_CA_BUNDLE if session option is not provided.
  230. if len(envCfg.CustomCABundle) != 0 && opts.CustomCABundle == nil {
  231. f, err := os.Open(envCfg.CustomCABundle)
  232. if err != nil {
  233. return nil, awserr.New("LoadCustomCABundleError",
  234. "failed to open custom CA bundle PEM file", err)
  235. }
  236. defer f.Close()
  237. opts.CustomCABundle = f
  238. }
  239. return newSession(opts, envCfg, &opts.Config)
  240. }
  241. // Must is a helper function to ensure the Session is valid and there was no
  242. // error when calling a NewSession function.
  243. //
  244. // This helper is intended to be used in variable initialization to load the
  245. // Session and configuration at startup. Such as:
  246. //
  247. // var sess = session.Must(session.NewSession())
  248. func Must(sess *Session, err error) *Session {
  249. if err != nil {
  250. panic(err)
  251. }
  252. return sess
  253. }
  254. func deprecatedNewSession(cfgs ...*aws.Config) *Session {
  255. cfg := defaults.Config()
  256. handlers := defaults.Handlers()
  257. // Apply the passed in configs so the configuration can be applied to the
  258. // default credential chain
  259. cfg.MergeIn(cfgs...)
  260. if cfg.EndpointResolver == nil {
  261. // An endpoint resolver is required for a session to be able to provide
  262. // endpoints for service client configurations.
  263. cfg.EndpointResolver = endpoints.DefaultResolver()
  264. }
  265. cfg.Credentials = defaults.CredChain(cfg, handlers)
  266. // Reapply any passed in configs to override credentials if set
  267. cfg.MergeIn(cfgs...)
  268. s := &Session{
  269. Config: cfg,
  270. Handlers: handlers,
  271. }
  272. initHandlers(s)
  273. return s
  274. }
  275. func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, error) {
  276. cfg := defaults.Config()
  277. handlers := defaults.Handlers()
  278. // Get a merged version of the user provided config to determine if
  279. // credentials were.
  280. userCfg := &aws.Config{}
  281. userCfg.MergeIn(cfgs...)
  282. // Ordered config files will be loaded in with later files overwriting
  283. // previous config file values.
  284. var cfgFiles []string
  285. if opts.SharedConfigFiles != nil {
  286. cfgFiles = opts.SharedConfigFiles
  287. } else {
  288. cfgFiles = []string{envCfg.SharedConfigFile, envCfg.SharedCredentialsFile}
  289. if !envCfg.EnableSharedConfig {
  290. // The shared config file (~/.aws/config) is only loaded if instructed
  291. // to load via the envConfig.EnableSharedConfig (AWS_SDK_LOAD_CONFIG).
  292. cfgFiles = cfgFiles[1:]
  293. }
  294. }
  295. // Load additional config from file(s)
  296. sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles)
  297. if err != nil {
  298. return nil, err
  299. }
  300. if err := mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers, opts); err != nil {
  301. return nil, err
  302. }
  303. s := &Session{
  304. Config: cfg,
  305. Handlers: handlers,
  306. }
  307. initHandlers(s)
  308. // Setup HTTP client with custom cert bundle if enabled
  309. if opts.CustomCABundle != nil {
  310. if err := loadCustomCABundle(s, opts.CustomCABundle); err != nil {
  311. return nil, err
  312. }
  313. }
  314. return s, nil
  315. }
  316. func loadCustomCABundle(s *Session, bundle io.Reader) error {
  317. var t *http.Transport
  318. switch v := s.Config.HTTPClient.Transport.(type) {
  319. case *http.Transport:
  320. t = v
  321. default:
  322. if s.Config.HTTPClient.Transport != nil {
  323. return awserr.New("LoadCustomCABundleError",
  324. "unable to load custom CA bundle, HTTPClient's transport unsupported type", nil)
  325. }
  326. }
  327. if t == nil {
  328. t = &http.Transport{}
  329. }
  330. p, err := loadCertPool(bundle)
  331. if err != nil {
  332. return err
  333. }
  334. if t.TLSClientConfig == nil {
  335. t.TLSClientConfig = &tls.Config{}
  336. }
  337. t.TLSClientConfig.RootCAs = p
  338. s.Config.HTTPClient.Transport = t
  339. return nil
  340. }
  341. func loadCertPool(r io.Reader) (*x509.CertPool, error) {
  342. b, err := ioutil.ReadAll(r)
  343. if err != nil {
  344. return nil, awserr.New("LoadCustomCABundleError",
  345. "failed to read custom CA bundle PEM file", err)
  346. }
  347. p := x509.NewCertPool()
  348. if !p.AppendCertsFromPEM(b) {
  349. return nil, awserr.New("LoadCustomCABundleError",
  350. "failed to load custom CA bundle PEM file", err)
  351. }
  352. return p, nil
  353. }
  354. func mergeConfigSrcs(cfg, userCfg *aws.Config, envCfg envConfig, sharedCfg sharedConfig, handlers request.Handlers, sessOpts Options) error {
  355. // Merge in user provided configuration
  356. cfg.MergeIn(userCfg)
  357. // Region if not already set by user
  358. if len(aws.StringValue(cfg.Region)) == 0 {
  359. if len(envCfg.Region) > 0 {
  360. cfg.WithRegion(envCfg.Region)
  361. } else if envCfg.EnableSharedConfig && len(sharedCfg.Region) > 0 {
  362. cfg.WithRegion(sharedCfg.Region)
  363. }
  364. }
  365. // Configure credentials if not already set
  366. if cfg.Credentials == credentials.AnonymousCredentials && userCfg.Credentials == nil {
  367. if len(envCfg.Creds.AccessKeyID) > 0 {
  368. cfg.Credentials = credentials.NewStaticCredentialsFromCreds(
  369. envCfg.Creds,
  370. )
  371. } else if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.RoleARN) > 0 && sharedCfg.AssumeRoleSource != nil {
  372. cfgCp := *cfg
  373. cfgCp.Credentials = credentials.NewStaticCredentialsFromCreds(
  374. sharedCfg.AssumeRoleSource.Creds,
  375. )
  376. if len(sharedCfg.AssumeRole.MFASerial) > 0 && sessOpts.AssumeRoleTokenProvider == nil {
  377. // AssumeRole Token provider is required if doing Assume Role
  378. // with MFA.
  379. return AssumeRoleTokenProviderNotSetError{}
  380. }
  381. cfg.Credentials = stscreds.NewCredentials(
  382. &Session{
  383. Config: &cfgCp,
  384. Handlers: handlers.Copy(),
  385. },
  386. sharedCfg.AssumeRole.RoleARN,
  387. func(opt *stscreds.AssumeRoleProvider) {
  388. opt.RoleSessionName = sharedCfg.AssumeRole.RoleSessionName
  389. // Assume role with external ID
  390. if len(sharedCfg.AssumeRole.ExternalID) > 0 {
  391. opt.ExternalID = aws.String(sharedCfg.AssumeRole.ExternalID)
  392. }
  393. // Assume role with MFA
  394. if len(sharedCfg.AssumeRole.MFASerial) > 0 {
  395. opt.SerialNumber = aws.String(sharedCfg.AssumeRole.MFASerial)
  396. opt.TokenProvider = sessOpts.AssumeRoleTokenProvider
  397. }
  398. },
  399. )
  400. } else if len(sharedCfg.Creds.AccessKeyID) > 0 {
  401. cfg.Credentials = credentials.NewStaticCredentialsFromCreds(
  402. sharedCfg.Creds,
  403. )
  404. } else {
  405. // Fallback to default credentials provider, include mock errors
  406. // for the credential chain so user can identify why credentials
  407. // failed to be retrieved.
  408. cfg.Credentials = credentials.NewCredentials(&credentials.ChainProvider{
  409. VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
  410. Providers: []credentials.Provider{
  411. &credProviderError{Err: awserr.New("EnvAccessKeyNotFound", "failed to find credentials in the environment.", nil)},
  412. &credProviderError{Err: awserr.New("SharedCredsLoad", fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil)},
  413. defaults.RemoteCredProvider(*cfg, handlers),
  414. },
  415. })
  416. }
  417. }
  418. return nil
  419. }
  420. // AssumeRoleTokenProviderNotSetError is an error returned when creating a session when the
  421. // MFAToken option is not set when shared config is configured load assume a
  422. // role with an MFA token.
  423. type AssumeRoleTokenProviderNotSetError struct{}
  424. // Code is the short id of the error.
  425. func (e AssumeRoleTokenProviderNotSetError) Code() string {
  426. return "AssumeRoleTokenProviderNotSetError"
  427. }
  428. // Message is the description of the error
  429. func (e AssumeRoleTokenProviderNotSetError) Message() string {
  430. return fmt.Sprintf("assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.")
  431. }
  432. // OrigErr is the underlying error that caused the failure.
  433. func (e AssumeRoleTokenProviderNotSetError) OrigErr() error {
  434. return nil
  435. }
  436. // Error satisfies the error interface.
  437. func (e AssumeRoleTokenProviderNotSetError) Error() string {
  438. return awserr.SprintError(e.Code(), e.Message(), "", nil)
  439. }
  440. type credProviderError struct {
  441. Err error
  442. }
  443. var emptyCreds = credentials.Value{}
  444. func (c credProviderError) Retrieve() (credentials.Value, error) {
  445. return credentials.Value{}, c.Err
  446. }
  447. func (c credProviderError) IsExpired() bool {
  448. return true
  449. }
  450. func initHandlers(s *Session) {
  451. // Add the Validate parameter handler if it is not disabled.
  452. s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler)
  453. if !aws.BoolValue(s.Config.DisableParamValidation) {
  454. s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler)
  455. }
  456. }
  457. // Copy creates and returns a copy of the current Session, coping the config
  458. // and handlers. If any additional configs are provided they will be merged
  459. // on top of the Session's copied config.
  460. //
  461. // // Create a copy of the current Session, configured for the us-west-2 region.
  462. // sess.Copy(&aws.Config{Region: aws.String("us-west-2")})
  463. func (s *Session) Copy(cfgs ...*aws.Config) *Session {
  464. newSession := &Session{
  465. Config: s.Config.Copy(cfgs...),
  466. Handlers: s.Handlers.Copy(),
  467. }
  468. initHandlers(newSession)
  469. return newSession
  470. }
  471. // ClientConfig satisfies the client.ConfigProvider interface and is used to
  472. // configure the service client instances. Passing the Session to the service
  473. // client's constructor (New) will use this method to configure the client.
  474. func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config {
  475. // Backwards compatibility, the error will be eaten if user calls ClientConfig
  476. // directly. All SDK services will use ClientconfigWithError.
  477. cfg, _ := s.clientConfigWithErr(serviceName, cfgs...)
  478. return cfg
  479. }
  480. func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) (client.Config, error) {
  481. s = s.Copy(cfgs...)
  482. var resolved endpoints.ResolvedEndpoint
  483. var err error
  484. region := aws.StringValue(s.Config.Region)
  485. if endpoint := aws.StringValue(s.Config.Endpoint); len(endpoint) != 0 {
  486. resolved.URL = endpoints.AddScheme(endpoint, aws.BoolValue(s.Config.DisableSSL))
  487. resolved.SigningRegion = region
  488. } else {
  489. resolved, err = s.Config.EndpointResolver.EndpointFor(
  490. serviceName, region,
  491. func(opt *endpoints.Options) {
  492. opt.DisableSSL = aws.BoolValue(s.Config.DisableSSL)
  493. opt.UseDualStack = aws.BoolValue(s.Config.UseDualStack)
  494. // Support the condition where the service is modeled but its
  495. // endpoint metadata is not available.
  496. opt.ResolveUnknownService = true
  497. },
  498. )
  499. }
  500. return client.Config{
  501. Config: s.Config,
  502. Handlers: s.Handlers,
  503. Endpoint: resolved.URL,
  504. SigningRegion: resolved.SigningRegion,
  505. SigningName: resolved.SigningName,
  506. }, err
  507. }
  508. // ClientConfigNoResolveEndpoint is the same as ClientConfig with the exception
  509. // that the EndpointResolver will not be used to resolve the endpoint. The only
  510. // endpoint set must come from the aws.Config.Endpoint field.
  511. func (s *Session) ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) client.Config {
  512. s = s.Copy(cfgs...)
  513. var resolved endpoints.ResolvedEndpoint
  514. region := aws.StringValue(s.Config.Region)
  515. if ep := aws.StringValue(s.Config.Endpoint); len(ep) > 0 {
  516. resolved.URL = endpoints.AddScheme(ep, aws.BoolValue(s.Config.DisableSSL))
  517. resolved.SigningRegion = region
  518. }
  519. return client.Config{
  520. Config: s.Config,
  521. Handlers: s.Handlers,
  522. Endpoint: resolved.URL,
  523. SigningRegion: resolved.SigningRegion,
  524. SigningName: resolved.SigningName,
  525. }
  526. }