env_config.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. package config
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "io"
  7. "os"
  8. "strconv"
  9. "strings"
  10. "github.com/aws/aws-sdk-go-v2/aws"
  11. "github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
  12. smithyrequestcompression "github.com/aws/smithy-go/private/requestcompression"
  13. )
  14. // CredentialsSourceName provides a name of the provider when config is
  15. // loaded from environment.
  16. const CredentialsSourceName = "EnvConfigCredentials"
  17. // Environment variables that will be read for configuration values.
  18. const (
  19. awsAccessKeyIDEnv = "AWS_ACCESS_KEY_ID"
  20. awsAccessKeyEnv = "AWS_ACCESS_KEY"
  21. awsSecretAccessKeyEnv = "AWS_SECRET_ACCESS_KEY"
  22. awsSecretKeyEnv = "AWS_SECRET_KEY"
  23. awsSessionTokenEnv = "AWS_SESSION_TOKEN"
  24. awsContainerCredentialsFullURIEnv = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
  25. awsContainerCredentialsRelativeURIEnv = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
  26. awsContainerAuthorizationTokenEnv = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
  27. awsRegionEnv = "AWS_REGION"
  28. awsDefaultRegionEnv = "AWS_DEFAULT_REGION"
  29. awsProfileEnv = "AWS_PROFILE"
  30. awsDefaultProfileEnv = "AWS_DEFAULT_PROFILE"
  31. awsSharedCredentialsFileEnv = "AWS_SHARED_CREDENTIALS_FILE"
  32. awsConfigFileEnv = "AWS_CONFIG_FILE"
  33. awsCABundleEnv = "AWS_CA_BUNDLE"
  34. awsWebIdentityTokenFileEnv = "AWS_WEB_IDENTITY_TOKEN_FILE"
  35. awsRoleARNEnv = "AWS_ROLE_ARN"
  36. awsRoleSessionNameEnv = "AWS_ROLE_SESSION_NAME"
  37. awsEnableEndpointDiscoveryEnv = "AWS_ENABLE_ENDPOINT_DISCOVERY"
  38. awsS3UseARNRegionEnv = "AWS_S3_USE_ARN_REGION"
  39. awsEc2MetadataServiceEndpointModeEnv = "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE"
  40. awsEc2MetadataServiceEndpointEnv = "AWS_EC2_METADATA_SERVICE_ENDPOINT"
  41. awsEc2MetadataDisabledEnv = "AWS_EC2_METADATA_DISABLED"
  42. awsEc2MetadataV1DisabledEnv = "AWS_EC2_METADATA_V1_DISABLED"
  43. awsS3DisableMultiRegionAccessPointsEnv = "AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS"
  44. awsUseDualStackEndpointEnv = "AWS_USE_DUALSTACK_ENDPOINT"
  45. awsUseFIPSEndpointEnv = "AWS_USE_FIPS_ENDPOINT"
  46. awsDefaultsModeEnv = "AWS_DEFAULTS_MODE"
  47. awsMaxAttemptsEnv = "AWS_MAX_ATTEMPTS"
  48. awsRetryModeEnv = "AWS_RETRY_MODE"
  49. awsSdkUaAppIDEnv = "AWS_SDK_UA_APP_ID"
  50. awsIgnoreConfiguredEndpointURLEnv = "AWS_IGNORE_CONFIGURED_ENDPOINT_URLS"
  51. awsEndpointURLEnv = "AWS_ENDPOINT_URL"
  52. awsDisableRequestCompressionEnv = "AWS_DISABLE_REQUEST_COMPRESSION"
  53. awsRequestMinCompressionSizeBytesEnv = "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES"
  54. awsS3DisableExpressSessionAuthEnv = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH"
  55. awsAccountIDEnv = "AWS_ACCOUNT_ID"
  56. awsAccountIDEndpointModeEnv = "AWS_ACCOUNT_ID_ENDPOINT_MODE"
  57. awsRequestChecksumCalculation = "AWS_REQUEST_CHECKSUM_CALCULATION"
  58. awsResponseChecksumValidation = "AWS_RESPONSE_CHECKSUM_VALIDATION"
  59. awsAuthSchemePreferenceEnv = "AWS_AUTH_SCHEME_PREFERENCE"
  60. )
  61. var (
  62. credAccessEnvKeys = []string{
  63. awsAccessKeyIDEnv,
  64. awsAccessKeyEnv,
  65. }
  66. credSecretEnvKeys = []string{
  67. awsSecretAccessKeyEnv,
  68. awsSecretKeyEnv,
  69. }
  70. regionEnvKeys = []string{
  71. awsRegionEnv,
  72. awsDefaultRegionEnv,
  73. }
  74. profileEnvKeys = []string{
  75. awsProfileEnv,
  76. awsDefaultProfileEnv,
  77. }
  78. )
  79. // EnvConfig is a collection of environment values the SDK will read
  80. // setup config from. All environment values are optional. But some values
  81. // such as credentials require multiple values to be complete or the values
  82. // will be ignored.
  83. type EnvConfig struct {
  84. // Environment configuration values. If set both Access Key ID and Secret Access
  85. // Key must be provided. Session Token and optionally also be provided, but is
  86. // not required.
  87. //
  88. // # Access Key ID
  89. // AWS_ACCESS_KEY_ID=AKID
  90. // AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
  91. //
  92. // # Secret Access Key
  93. // AWS_SECRET_ACCESS_KEY=SECRET
  94. // AWS_SECRET_KEY=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
  95. //
  96. // # Session Token
  97. // AWS_SESSION_TOKEN=TOKEN
  98. Credentials aws.Credentials
  99. // ContainerCredentialsEndpoint value is the HTTP enabled endpoint to retrieve credentials
  100. // using the endpointcreds.Provider
  101. ContainerCredentialsEndpoint string
  102. // ContainerCredentialsRelativePath is the relative URI path that will be used when attempting to retrieve
  103. // credentials from the container endpoint.
  104. ContainerCredentialsRelativePath string
  105. // ContainerAuthorizationToken is the authorization token that will be included in the HTTP Authorization
  106. // header when attempting to retrieve credentials from the container credentials endpoint.
  107. ContainerAuthorizationToken string
  108. // Region value will instruct the SDK where to make service API requests to. If is
  109. // not provided in the environment the region must be provided before a service
  110. // client request is made.
  111. //
  112. // AWS_REGION=us-west-2
  113. // AWS_DEFAULT_REGION=us-west-2
  114. Region string
  115. // Profile name the SDK should load use when loading shared configuration from the
  116. // shared configuration files. If not provided "default" will be used as the
  117. // profile name.
  118. //
  119. // AWS_PROFILE=my_profile
  120. // AWS_DEFAULT_PROFILE=my_profile
  121. SharedConfigProfile string
  122. // Shared credentials file path can be set to instruct the SDK to use an alternate
  123. // file for the shared credentials. If not set the file will be loaded from
  124. // $HOME/.aws/credentials on Linux/Unix based systems, and
  125. // %USERPROFILE%\.aws\credentials on Windows.
  126. //
  127. // AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
  128. SharedCredentialsFile string
  129. // Shared config file path can be set to instruct the SDK to use an alternate
  130. // file for the shared config. If not set the file will be loaded from
  131. // $HOME/.aws/config on Linux/Unix based systems, and
  132. // %USERPROFILE%\.aws\config on Windows.
  133. //
  134. // AWS_CONFIG_FILE=$HOME/my_shared_config
  135. SharedConfigFile string
  136. // Sets the path to a custom Credentials Authority (CA) Bundle PEM file
  137. // that the SDK will use instead of the system's root CA bundle.
  138. // Only use this if you want to configure the SDK to use a custom set
  139. // of CAs.
  140. //
  141. // Enabling this option will attempt to merge the Transport
  142. // into the SDK's HTTP client. If the client's Transport is
  143. // not a http.Transport an error will be returned. If the
  144. // Transport's TLS config is set this option will cause the
  145. // SDK to overwrite the Transport's TLS config's RootCAs value.
  146. //
  147. // Setting a custom HTTPClient in the aws.Config options will override this setting.
  148. // To use this option and custom HTTP client, the HTTP client needs to be provided
  149. // when creating the config. Not the service client.
  150. //
  151. // AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle
  152. CustomCABundle string
  153. // Enables endpoint discovery via environment variables.
  154. //
  155. // AWS_ENABLE_ENDPOINT_DISCOVERY=true
  156. EnableEndpointDiscovery aws.EndpointDiscoveryEnableState
  157. // Specifies the WebIdentity token the SDK should use to assume a role
  158. // with.
  159. //
  160. // AWS_WEB_IDENTITY_TOKEN_FILE=file_path
  161. WebIdentityTokenFilePath string
  162. // Specifies the IAM role arn to use when assuming an role.
  163. //
  164. // AWS_ROLE_ARN=role_arn
  165. RoleARN string
  166. // Specifies the IAM role session name to use when assuming a role.
  167. //
  168. // AWS_ROLE_SESSION_NAME=session_name
  169. RoleSessionName string
  170. // Specifies if the S3 service should allow ARNs to direct the region
  171. // the client's requests are sent to.
  172. //
  173. // AWS_S3_USE_ARN_REGION=true
  174. S3UseARNRegion *bool
  175. // Specifies if the EC2 IMDS service client is enabled.
  176. //
  177. // AWS_EC2_METADATA_DISABLED=true
  178. EC2IMDSClientEnableState imds.ClientEnableState
  179. // Specifies if EC2 IMDSv1 fallback is disabled.
  180. //
  181. // AWS_EC2_METADATA_V1_DISABLED=true
  182. EC2IMDSv1Disabled *bool
  183. // Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
  184. //
  185. // AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv6
  186. EC2IMDSEndpointMode imds.EndpointModeState
  187. // Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
  188. //
  189. // AWS_EC2_METADATA_SERVICE_ENDPOINT=http://fd00:ec2::254
  190. EC2IMDSEndpoint string
  191. // Specifies if the S3 service should disable multi-region access points
  192. // support.
  193. //
  194. // AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS=true
  195. S3DisableMultiRegionAccessPoints *bool
  196. // Specifies that SDK clients must resolve a dual-stack endpoint for
  197. // services.
  198. //
  199. // AWS_USE_DUALSTACK_ENDPOINT=true
  200. UseDualStackEndpoint aws.DualStackEndpointState
  201. // Specifies that SDK clients must resolve a FIPS endpoint for
  202. // services.
  203. //
  204. // AWS_USE_FIPS_ENDPOINT=true
  205. UseFIPSEndpoint aws.FIPSEndpointState
  206. // Specifies the SDK Defaults Mode used by services.
  207. //
  208. // AWS_DEFAULTS_MODE=standard
  209. DefaultsMode aws.DefaultsMode
  210. // Specifies the maximum number attempts an API client will call an
  211. // operation that fails with a retryable error.
  212. //
  213. // AWS_MAX_ATTEMPTS=3
  214. RetryMaxAttempts int
  215. // Specifies the retry model the API client will be created with.
  216. //
  217. // aws_retry_mode=standard
  218. RetryMode aws.RetryMode
  219. // aws sdk app ID that can be added to user agent header string
  220. AppID string
  221. // Flag used to disable configured endpoints.
  222. IgnoreConfiguredEndpoints *bool
  223. // Value to contain configured endpoints to be propagated to
  224. // corresponding endpoint resolution field.
  225. BaseEndpoint string
  226. // determine if request compression is allowed, default to false
  227. // retrieved from env var AWS_DISABLE_REQUEST_COMPRESSION
  228. DisableRequestCompression *bool
  229. // inclusive threshold request body size to trigger compression,
  230. // default to 10240 and must be within 0 and 10485760 bytes inclusive
  231. // retrieved from env var AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES
  232. RequestMinCompressSizeBytes *int64
  233. // Whether S3Express auth is disabled.
  234. //
  235. // This will NOT prevent requests from being made to S3Express buckets, it
  236. // will only bypass the modified endpoint routing and signing behaviors
  237. // associated with the feature.
  238. S3DisableExpressAuth *bool
  239. // Indicates whether account ID will be required/ignored in endpoint2.0 routing
  240. AccountIDEndpointMode aws.AccountIDEndpointMode
  241. // Indicates whether request checksum should be calculated
  242. RequestChecksumCalculation aws.RequestChecksumCalculation
  243. // Indicates whether response checksum should be validated
  244. ResponseChecksumValidation aws.ResponseChecksumValidation
  245. // Priority list of preferred auth scheme names (e.g. sigv4a).
  246. AuthSchemePreference []string
  247. }
  248. // loadEnvConfig reads configuration values from the OS's environment variables.
  249. // Returning the a Config typed EnvConfig to satisfy the ConfigLoader func type.
  250. func loadEnvConfig(ctx context.Context, cfgs configs) (Config, error) {
  251. return NewEnvConfig()
  252. }
  253. // NewEnvConfig retrieves the SDK's environment configuration.
  254. // See `EnvConfig` for the values that will be retrieved.
  255. func NewEnvConfig() (EnvConfig, error) {
  256. var cfg EnvConfig
  257. creds := aws.Credentials{
  258. Source: CredentialsSourceName,
  259. }
  260. setStringFromEnvVal(&creds.AccessKeyID, credAccessEnvKeys)
  261. setStringFromEnvVal(&creds.SecretAccessKey, credSecretEnvKeys)
  262. if creds.HasKeys() {
  263. creds.AccountID = os.Getenv(awsAccountIDEnv)
  264. creds.SessionToken = os.Getenv(awsSessionTokenEnv)
  265. cfg.Credentials = creds
  266. }
  267. cfg.ContainerCredentialsEndpoint = os.Getenv(awsContainerCredentialsFullURIEnv)
  268. cfg.ContainerCredentialsRelativePath = os.Getenv(awsContainerCredentialsRelativeURIEnv)
  269. cfg.ContainerAuthorizationToken = os.Getenv(awsContainerAuthorizationTokenEnv)
  270. setStringFromEnvVal(&cfg.Region, regionEnvKeys)
  271. setStringFromEnvVal(&cfg.SharedConfigProfile, profileEnvKeys)
  272. cfg.SharedCredentialsFile = os.Getenv(awsSharedCredentialsFileEnv)
  273. cfg.SharedConfigFile = os.Getenv(awsConfigFileEnv)
  274. cfg.CustomCABundle = os.Getenv(awsCABundleEnv)
  275. cfg.WebIdentityTokenFilePath = os.Getenv(awsWebIdentityTokenFileEnv)
  276. cfg.RoleARN = os.Getenv(awsRoleARNEnv)
  277. cfg.RoleSessionName = os.Getenv(awsRoleSessionNameEnv)
  278. cfg.AppID = os.Getenv(awsSdkUaAppIDEnv)
  279. if err := setBoolPtrFromEnvVal(&cfg.DisableRequestCompression, []string{awsDisableRequestCompressionEnv}); err != nil {
  280. return cfg, err
  281. }
  282. if err := setInt64PtrFromEnvVal(&cfg.RequestMinCompressSizeBytes, []string{awsRequestMinCompressionSizeBytesEnv}, smithyrequestcompression.MaxRequestMinCompressSizeBytes); err != nil {
  283. return cfg, err
  284. }
  285. if err := setEndpointDiscoveryTypeFromEnvVal(&cfg.EnableEndpointDiscovery, []string{awsEnableEndpointDiscoveryEnv}); err != nil {
  286. return cfg, err
  287. }
  288. if err := setBoolPtrFromEnvVal(&cfg.S3UseARNRegion, []string{awsS3UseARNRegionEnv}); err != nil {
  289. return cfg, err
  290. }
  291. setEC2IMDSClientEnableState(&cfg.EC2IMDSClientEnableState, []string{awsEc2MetadataDisabledEnv})
  292. if err := setEC2IMDSEndpointMode(&cfg.EC2IMDSEndpointMode, []string{awsEc2MetadataServiceEndpointModeEnv}); err != nil {
  293. return cfg, err
  294. }
  295. cfg.EC2IMDSEndpoint = os.Getenv(awsEc2MetadataServiceEndpointEnv)
  296. if err := setBoolPtrFromEnvVal(&cfg.EC2IMDSv1Disabled, []string{awsEc2MetadataV1DisabledEnv}); err != nil {
  297. return cfg, err
  298. }
  299. if err := setBoolPtrFromEnvVal(&cfg.S3DisableMultiRegionAccessPoints, []string{awsS3DisableMultiRegionAccessPointsEnv}); err != nil {
  300. return cfg, err
  301. }
  302. if err := setUseDualStackEndpointFromEnvVal(&cfg.UseDualStackEndpoint, []string{awsUseDualStackEndpointEnv}); err != nil {
  303. return cfg, err
  304. }
  305. if err := setUseFIPSEndpointFromEnvVal(&cfg.UseFIPSEndpoint, []string{awsUseFIPSEndpointEnv}); err != nil {
  306. return cfg, err
  307. }
  308. if err := setDefaultsModeFromEnvVal(&cfg.DefaultsMode, []string{awsDefaultsModeEnv}); err != nil {
  309. return cfg, err
  310. }
  311. if err := setIntFromEnvVal(&cfg.RetryMaxAttempts, []string{awsMaxAttemptsEnv}); err != nil {
  312. return cfg, err
  313. }
  314. if err := setRetryModeFromEnvVal(&cfg.RetryMode, []string{awsRetryModeEnv}); err != nil {
  315. return cfg, err
  316. }
  317. setStringFromEnvVal(&cfg.BaseEndpoint, []string{awsEndpointURLEnv})
  318. if err := setBoolPtrFromEnvVal(&cfg.IgnoreConfiguredEndpoints, []string{awsIgnoreConfiguredEndpointURLEnv}); err != nil {
  319. return cfg, err
  320. }
  321. if err := setBoolPtrFromEnvVal(&cfg.S3DisableExpressAuth, []string{awsS3DisableExpressSessionAuthEnv}); err != nil {
  322. return cfg, err
  323. }
  324. if err := setAIDEndPointModeFromEnvVal(&cfg.AccountIDEndpointMode, []string{awsAccountIDEndpointModeEnv}); err != nil {
  325. return cfg, err
  326. }
  327. if err := setRequestChecksumCalculationFromEnvVal(&cfg.RequestChecksumCalculation, []string{awsRequestChecksumCalculation}); err != nil {
  328. return cfg, err
  329. }
  330. if err := setResponseChecksumValidationFromEnvVal(&cfg.ResponseChecksumValidation, []string{awsResponseChecksumValidation}); err != nil {
  331. return cfg, err
  332. }
  333. cfg.AuthSchemePreference = toAuthSchemePreferenceList(os.Getenv(awsAuthSchemePreferenceEnv))
  334. return cfg, nil
  335. }
  336. func (c EnvConfig) getDefaultsMode(ctx context.Context) (aws.DefaultsMode, bool, error) {
  337. if len(c.DefaultsMode) == 0 {
  338. return "", false, nil
  339. }
  340. return c.DefaultsMode, true, nil
  341. }
  342. func (c EnvConfig) getAppID(context.Context) (string, bool, error) {
  343. return c.AppID, len(c.AppID) > 0, nil
  344. }
  345. func (c EnvConfig) getDisableRequestCompression(context.Context) (bool, bool, error) {
  346. if c.DisableRequestCompression == nil {
  347. return false, false, nil
  348. }
  349. return *c.DisableRequestCompression, true, nil
  350. }
  351. func (c EnvConfig) getRequestMinCompressSizeBytes(context.Context) (int64, bool, error) {
  352. if c.RequestMinCompressSizeBytes == nil {
  353. return 0, false, nil
  354. }
  355. return *c.RequestMinCompressSizeBytes, true, nil
  356. }
  357. func (c EnvConfig) getAccountIDEndpointMode(context.Context) (aws.AccountIDEndpointMode, bool, error) {
  358. return c.AccountIDEndpointMode, len(c.AccountIDEndpointMode) > 0, nil
  359. }
  360. func (c EnvConfig) getRequestChecksumCalculation(context.Context) (aws.RequestChecksumCalculation, bool, error) {
  361. return c.RequestChecksumCalculation, c.RequestChecksumCalculation > 0, nil
  362. }
  363. func (c EnvConfig) getResponseChecksumValidation(context.Context) (aws.ResponseChecksumValidation, bool, error) {
  364. return c.ResponseChecksumValidation, c.ResponseChecksumValidation > 0, nil
  365. }
  366. // GetRetryMaxAttempts returns the value of AWS_MAX_ATTEMPTS if was specified,
  367. // and not 0.
  368. func (c EnvConfig) GetRetryMaxAttempts(ctx context.Context) (int, bool, error) {
  369. if c.RetryMaxAttempts == 0 {
  370. return 0, false, nil
  371. }
  372. return c.RetryMaxAttempts, true, nil
  373. }
  374. // GetRetryMode returns the RetryMode of AWS_RETRY_MODE if was specified, and a
  375. // valid value.
  376. func (c EnvConfig) GetRetryMode(ctx context.Context) (aws.RetryMode, bool, error) {
  377. if len(c.RetryMode) == 0 {
  378. return "", false, nil
  379. }
  380. return c.RetryMode, true, nil
  381. }
  382. func setEC2IMDSClientEnableState(state *imds.ClientEnableState, keys []string) {
  383. for _, k := range keys {
  384. value := os.Getenv(k)
  385. if len(value) == 0 {
  386. continue
  387. }
  388. switch {
  389. case strings.EqualFold(value, "true"):
  390. *state = imds.ClientDisabled
  391. case strings.EqualFold(value, "false"):
  392. *state = imds.ClientEnabled
  393. default:
  394. continue
  395. }
  396. break
  397. }
  398. }
  399. func setDefaultsModeFromEnvVal(mode *aws.DefaultsMode, keys []string) error {
  400. for _, k := range keys {
  401. if value := os.Getenv(k); len(value) > 0 {
  402. if ok := mode.SetFromString(value); !ok {
  403. return fmt.Errorf("invalid %s value: %s", k, value)
  404. }
  405. break
  406. }
  407. }
  408. return nil
  409. }
  410. func setRetryModeFromEnvVal(mode *aws.RetryMode, keys []string) (err error) {
  411. for _, k := range keys {
  412. if value := os.Getenv(k); len(value) > 0 {
  413. *mode, err = aws.ParseRetryMode(value)
  414. if err != nil {
  415. return fmt.Errorf("invalid %s value, %w", k, err)
  416. }
  417. break
  418. }
  419. }
  420. return nil
  421. }
  422. func setEC2IMDSEndpointMode(mode *imds.EndpointModeState, keys []string) error {
  423. for _, k := range keys {
  424. value := os.Getenv(k)
  425. if len(value) == 0 {
  426. continue
  427. }
  428. if err := mode.SetFromString(value); err != nil {
  429. return fmt.Errorf("invalid value for environment variable, %s=%s, %v", k, value, err)
  430. }
  431. }
  432. return nil
  433. }
  434. func setAIDEndPointModeFromEnvVal(m *aws.AccountIDEndpointMode, keys []string) error {
  435. for _, k := range keys {
  436. value := os.Getenv(k)
  437. if len(value) == 0 {
  438. continue
  439. }
  440. switch value {
  441. case "preferred":
  442. *m = aws.AccountIDEndpointModePreferred
  443. case "required":
  444. *m = aws.AccountIDEndpointModeRequired
  445. case "disabled":
  446. *m = aws.AccountIDEndpointModeDisabled
  447. default:
  448. return fmt.Errorf("invalid value for environment variable, %s=%s, must be preferred/required/disabled", k, value)
  449. }
  450. break
  451. }
  452. return nil
  453. }
  454. func setRequestChecksumCalculationFromEnvVal(m *aws.RequestChecksumCalculation, keys []string) error {
  455. for _, k := range keys {
  456. value := os.Getenv(k)
  457. if len(value) == 0 {
  458. continue
  459. }
  460. switch strings.ToLower(value) {
  461. case checksumWhenSupported:
  462. *m = aws.RequestChecksumCalculationWhenSupported
  463. case checksumWhenRequired:
  464. *m = aws.RequestChecksumCalculationWhenRequired
  465. default:
  466. return fmt.Errorf("invalid value for environment variable, %s=%s, must be when_supported/when_required", k, value)
  467. }
  468. }
  469. return nil
  470. }
  471. func setResponseChecksumValidationFromEnvVal(m *aws.ResponseChecksumValidation, keys []string) error {
  472. for _, k := range keys {
  473. value := os.Getenv(k)
  474. if len(value) == 0 {
  475. continue
  476. }
  477. switch strings.ToLower(value) {
  478. case checksumWhenSupported:
  479. *m = aws.ResponseChecksumValidationWhenSupported
  480. case checksumWhenRequired:
  481. *m = aws.ResponseChecksumValidationWhenRequired
  482. default:
  483. return fmt.Errorf("invalid value for environment variable, %s=%s, must be when_supported/when_required", k, value)
  484. }
  485. }
  486. return nil
  487. }
  488. // GetRegion returns the AWS Region if set in the environment. Returns an empty
  489. // string if not set.
  490. func (c EnvConfig) getRegion(ctx context.Context) (string, bool, error) {
  491. if len(c.Region) == 0 {
  492. return "", false, nil
  493. }
  494. return c.Region, true, nil
  495. }
  496. // GetSharedConfigProfile returns the shared config profile if set in the
  497. // environment. Returns an empty string if not set.
  498. func (c EnvConfig) getSharedConfigProfile(ctx context.Context) (string, bool, error) {
  499. if len(c.SharedConfigProfile) == 0 {
  500. return "", false, nil
  501. }
  502. return c.SharedConfigProfile, true, nil
  503. }
  504. // getSharedConfigFiles returns a slice of filenames set in the environment.
  505. //
  506. // Will return the filenames in the order of:
  507. // * Shared Config
  508. func (c EnvConfig) getSharedConfigFiles(context.Context) ([]string, bool, error) {
  509. var files []string
  510. if v := c.SharedConfigFile; len(v) > 0 {
  511. files = append(files, v)
  512. }
  513. if len(files) == 0 {
  514. return nil, false, nil
  515. }
  516. return files, true, nil
  517. }
  518. // getSharedCredentialsFiles returns a slice of filenames set in the environment.
  519. //
  520. // Will return the filenames in the order of:
  521. // * Shared Credentials
  522. func (c EnvConfig) getSharedCredentialsFiles(context.Context) ([]string, bool, error) {
  523. var files []string
  524. if v := c.SharedCredentialsFile; len(v) > 0 {
  525. files = append(files, v)
  526. }
  527. if len(files) == 0 {
  528. return nil, false, nil
  529. }
  530. return files, true, nil
  531. }
  532. // GetCustomCABundle returns the custom CA bundle's PEM bytes if the file was
  533. func (c EnvConfig) getCustomCABundle(context.Context) (io.Reader, bool, error) {
  534. if len(c.CustomCABundle) == 0 {
  535. return nil, false, nil
  536. }
  537. b, err := os.ReadFile(c.CustomCABundle)
  538. if err != nil {
  539. return nil, false, err
  540. }
  541. return bytes.NewReader(b), true, nil
  542. }
  543. // GetIgnoreConfiguredEndpoints is used in knowing when to disable configured
  544. // endpoints feature.
  545. func (c EnvConfig) GetIgnoreConfiguredEndpoints(context.Context) (bool, bool, error) {
  546. if c.IgnoreConfiguredEndpoints == nil {
  547. return false, false, nil
  548. }
  549. return *c.IgnoreConfiguredEndpoints, true, nil
  550. }
  551. func (c EnvConfig) getBaseEndpoint(context.Context) (string, bool, error) {
  552. return c.BaseEndpoint, len(c.BaseEndpoint) > 0, nil
  553. }
  554. // GetServiceBaseEndpoint is used to retrieve a normalized SDK ID for use
  555. // with configured endpoints.
  556. func (c EnvConfig) GetServiceBaseEndpoint(ctx context.Context, sdkID string) (string, bool, error) {
  557. if endpt := os.Getenv(fmt.Sprintf("%s_%s", awsEndpointURLEnv, normalizeEnv(sdkID))); endpt != "" {
  558. return endpt, true, nil
  559. }
  560. return "", false, nil
  561. }
  562. func normalizeEnv(sdkID string) string {
  563. upper := strings.ToUpper(sdkID)
  564. return strings.ReplaceAll(upper, " ", "_")
  565. }
  566. // GetS3UseARNRegion returns whether to allow ARNs to direct the region
  567. // the S3 client's requests are sent to.
  568. func (c EnvConfig) GetS3UseARNRegion(ctx context.Context) (value, ok bool, err error) {
  569. if c.S3UseARNRegion == nil {
  570. return false, false, nil
  571. }
  572. return *c.S3UseARNRegion, true, nil
  573. }
  574. // GetS3DisableMultiRegionAccessPoints returns whether to disable multi-region access point
  575. // support for the S3 client.
  576. func (c EnvConfig) GetS3DisableMultiRegionAccessPoints(ctx context.Context) (value, ok bool, err error) {
  577. if c.S3DisableMultiRegionAccessPoints == nil {
  578. return false, false, nil
  579. }
  580. return *c.S3DisableMultiRegionAccessPoints, true, nil
  581. }
  582. // GetUseDualStackEndpoint returns whether the service's dual-stack endpoint should be
  583. // used for requests.
  584. func (c EnvConfig) GetUseDualStackEndpoint(ctx context.Context) (value aws.DualStackEndpointState, found bool, err error) {
  585. if c.UseDualStackEndpoint == aws.DualStackEndpointStateUnset {
  586. return aws.DualStackEndpointStateUnset, false, nil
  587. }
  588. return c.UseDualStackEndpoint, true, nil
  589. }
  590. // GetUseFIPSEndpoint returns whether the service's FIPS endpoint should be
  591. // used for requests.
  592. func (c EnvConfig) GetUseFIPSEndpoint(ctx context.Context) (value aws.FIPSEndpointState, found bool, err error) {
  593. if c.UseFIPSEndpoint == aws.FIPSEndpointStateUnset {
  594. return aws.FIPSEndpointStateUnset, false, nil
  595. }
  596. return c.UseFIPSEndpoint, true, nil
  597. }
  598. func setStringFromEnvVal(dst *string, keys []string) {
  599. for _, k := range keys {
  600. if v := os.Getenv(k); len(v) > 0 {
  601. *dst = v
  602. break
  603. }
  604. }
  605. }
  606. func setIntFromEnvVal(dst *int, keys []string) error {
  607. for _, k := range keys {
  608. if v := os.Getenv(k); len(v) > 0 {
  609. i, err := strconv.ParseInt(v, 10, 64)
  610. if err != nil {
  611. return fmt.Errorf("invalid value %s=%s, %w", k, v, err)
  612. }
  613. *dst = int(i)
  614. break
  615. }
  616. }
  617. return nil
  618. }
  619. func setBoolPtrFromEnvVal(dst **bool, keys []string) error {
  620. for _, k := range keys {
  621. value := os.Getenv(k)
  622. if len(value) == 0 {
  623. continue
  624. }
  625. if *dst == nil {
  626. *dst = new(bool)
  627. }
  628. switch {
  629. case strings.EqualFold(value, "false"):
  630. **dst = false
  631. case strings.EqualFold(value, "true"):
  632. **dst = true
  633. default:
  634. return fmt.Errorf(
  635. "invalid value for environment variable, %s=%s, need true or false",
  636. k, value)
  637. }
  638. break
  639. }
  640. return nil
  641. }
  642. func setInt64PtrFromEnvVal(dst **int64, keys []string, max int64) error {
  643. for _, k := range keys {
  644. value := os.Getenv(k)
  645. if len(value) == 0 {
  646. continue
  647. }
  648. v, err := strconv.ParseInt(value, 10, 64)
  649. if err != nil {
  650. return fmt.Errorf("invalid value for env var, %s=%s, need int64", k, value)
  651. } else if v < 0 || v > max {
  652. return fmt.Errorf("invalid range for env var min request compression size bytes %q, must be within 0 and 10485760 inclusively", v)
  653. }
  654. if *dst == nil {
  655. *dst = new(int64)
  656. }
  657. **dst = v
  658. break
  659. }
  660. return nil
  661. }
  662. func setEndpointDiscoveryTypeFromEnvVal(dst *aws.EndpointDiscoveryEnableState, keys []string) error {
  663. for _, k := range keys {
  664. value := os.Getenv(k)
  665. if len(value) == 0 {
  666. continue // skip if empty
  667. }
  668. switch {
  669. case strings.EqualFold(value, endpointDiscoveryDisabled):
  670. *dst = aws.EndpointDiscoveryDisabled
  671. case strings.EqualFold(value, endpointDiscoveryEnabled):
  672. *dst = aws.EndpointDiscoveryEnabled
  673. case strings.EqualFold(value, endpointDiscoveryAuto):
  674. *dst = aws.EndpointDiscoveryAuto
  675. default:
  676. return fmt.Errorf(
  677. "invalid value for environment variable, %s=%s, need true, false or auto",
  678. k, value)
  679. }
  680. }
  681. return nil
  682. }
  683. func setUseDualStackEndpointFromEnvVal(dst *aws.DualStackEndpointState, keys []string) error {
  684. for _, k := range keys {
  685. value := os.Getenv(k)
  686. if len(value) == 0 {
  687. continue // skip if empty
  688. }
  689. switch {
  690. case strings.EqualFold(value, "true"):
  691. *dst = aws.DualStackEndpointStateEnabled
  692. case strings.EqualFold(value, "false"):
  693. *dst = aws.DualStackEndpointStateDisabled
  694. default:
  695. return fmt.Errorf(
  696. "invalid value for environment variable, %s=%s, need true, false",
  697. k, value)
  698. }
  699. }
  700. return nil
  701. }
  702. func setUseFIPSEndpointFromEnvVal(dst *aws.FIPSEndpointState, keys []string) error {
  703. for _, k := range keys {
  704. value := os.Getenv(k)
  705. if len(value) == 0 {
  706. continue // skip if empty
  707. }
  708. switch {
  709. case strings.EqualFold(value, "true"):
  710. *dst = aws.FIPSEndpointStateEnabled
  711. case strings.EqualFold(value, "false"):
  712. *dst = aws.FIPSEndpointStateDisabled
  713. default:
  714. return fmt.Errorf(
  715. "invalid value for environment variable, %s=%s, need true, false",
  716. k, value)
  717. }
  718. }
  719. return nil
  720. }
  721. // GetEnableEndpointDiscovery returns resolved value for EnableEndpointDiscovery env variable setting.
  722. func (c EnvConfig) GetEnableEndpointDiscovery(ctx context.Context) (value aws.EndpointDiscoveryEnableState, found bool, err error) {
  723. if c.EnableEndpointDiscovery == aws.EndpointDiscoveryUnset {
  724. return aws.EndpointDiscoveryUnset, false, nil
  725. }
  726. return c.EnableEndpointDiscovery, true, nil
  727. }
  728. // GetEC2IMDSClientEnableState implements a EC2IMDSClientEnableState options resolver interface.
  729. func (c EnvConfig) GetEC2IMDSClientEnableState() (imds.ClientEnableState, bool, error) {
  730. if c.EC2IMDSClientEnableState == imds.ClientDefaultEnableState {
  731. return imds.ClientDefaultEnableState, false, nil
  732. }
  733. return c.EC2IMDSClientEnableState, true, nil
  734. }
  735. // GetEC2IMDSEndpointMode implements a EC2IMDSEndpointMode option resolver interface.
  736. func (c EnvConfig) GetEC2IMDSEndpointMode() (imds.EndpointModeState, bool, error) {
  737. if c.EC2IMDSEndpointMode == imds.EndpointModeStateUnset {
  738. return imds.EndpointModeStateUnset, false, nil
  739. }
  740. return c.EC2IMDSEndpointMode, true, nil
  741. }
  742. // GetEC2IMDSEndpoint implements a EC2IMDSEndpoint option resolver interface.
  743. func (c EnvConfig) GetEC2IMDSEndpoint() (string, bool, error) {
  744. if len(c.EC2IMDSEndpoint) == 0 {
  745. return "", false, nil
  746. }
  747. return c.EC2IMDSEndpoint, true, nil
  748. }
  749. // GetEC2IMDSV1FallbackDisabled implements an EC2IMDSV1FallbackDisabled option
  750. // resolver interface.
  751. func (c EnvConfig) GetEC2IMDSV1FallbackDisabled() (bool, bool) {
  752. if c.EC2IMDSv1Disabled == nil {
  753. return false, false
  754. }
  755. return *c.EC2IMDSv1Disabled, true
  756. }
  757. // GetS3DisableExpressAuth returns the configured value for
  758. // [EnvConfig.S3DisableExpressAuth].
  759. func (c EnvConfig) GetS3DisableExpressAuth() (value, ok bool) {
  760. if c.S3DisableExpressAuth == nil {
  761. return false, false
  762. }
  763. return *c.S3DisableExpressAuth, true
  764. }
  765. func (c EnvConfig) getAuthSchemePreference() ([]string, bool) {
  766. if len(c.AuthSchemePreference) > 0 {
  767. return c.AuthSchemePreference, true
  768. }
  769. return nil, false
  770. }