1package session 2 3import ( 4 "fmt" 5 "os" 6 "strconv" 7 "strings" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/aws/credentials" 11 "github.com/aws/aws-sdk-go/aws/defaults" 12 "github.com/aws/aws-sdk-go/aws/endpoints" 13) 14 15// EnvProviderName provides a name of the provider when config is loaded from environment. 16const EnvProviderName = "EnvConfigCredentials" 17 18// envConfig is a collection of environment values the SDK will read 19// setup config from. All environment values are optional. But some values 20// such as credentials require multiple values to be complete or the values 21// will be ignored. 22type envConfig struct { 23 // Environment configuration values. If set both Access Key ID and Secret Access 24 // Key must be provided. Session Token and optionally also be provided, but is 25 // not required. 26 // 27 // # Access Key ID 28 // AWS_ACCESS_KEY_ID=AKID 29 // AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set. 30 // 31 // # Secret Access Key 32 // AWS_SECRET_ACCESS_KEY=SECRET 33 // AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set. 34 // 35 // # Session Token 36 // AWS_SESSION_TOKEN=TOKEN 37 Creds credentials.Value 38 39 // Region value will instruct the SDK where to make service API requests to. If is 40 // not provided in the environment the region must be provided before a service 41 // client request is made. 42 // 43 // AWS_REGION=us-east-1 44 // 45 // # AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set, 46 // # and AWS_REGION is not also set. 47 // AWS_DEFAULT_REGION=us-east-1 48 Region string 49 50 // Profile name the SDK should load use when loading shared configuration from the 51 // shared configuration files. If not provided "default" will be used as the 52 // profile name. 53 // 54 // AWS_PROFILE=my_profile 55 // 56 // # AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set, 57 // # and AWS_PROFILE is not also set. 58 // AWS_DEFAULT_PROFILE=my_profile 59 Profile string 60 61 // SDK load config instructs the SDK to load the shared config in addition to 62 // shared credentials. This also expands the configuration loaded from the shared 63 // credentials to have parity with the shared config file. This also enables 64 // Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE 65 // env values as well. 66 // 67 // AWS_SDK_LOAD_CONFIG=1 68 EnableSharedConfig bool 69 70 // Shared credentials file path can be set to instruct the SDK to use an alternate 71 // file for the shared credentials. If not set the file will be loaded from 72 // $HOME/.aws/credentials on Linux/Unix based systems, and 73 // %USERPROFILE%\.aws\credentials on Windows. 74 // 75 // AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials 76 SharedCredentialsFile string 77 78 // Shared config file path can be set to instruct the SDK to use an alternate 79 // file for the shared config. If not set the file will be loaded from 80 // $HOME/.aws/config on Linux/Unix based systems, and 81 // %USERPROFILE%\.aws\config on Windows. 82 // 83 // AWS_CONFIG_FILE=$HOME/my_shared_config 84 SharedConfigFile string 85 86 // Sets the path to a custom Credentials Authority (CA) Bundle PEM file 87 // that the SDK will use instead of the system's root CA bundle. 88 // Only use this if you want to configure the SDK to use a custom set 89 // of CAs. 90 // 91 // Enabling this option will attempt to merge the Transport 92 // into the SDK's HTTP client. If the client's Transport is 93 // not a http.Transport an error will be returned. If the 94 // Transport's TLS config is set this option will cause the 95 // SDK to overwrite the Transport's TLS config's RootCAs value. 96 // 97 // Setting a custom HTTPClient in the aws.Config options will override this setting. 98 // To use this option and custom HTTP client, the HTTP client needs to be provided 99 // when creating the session. Not the service client. 100 // 101 // AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle 102 CustomCABundle string 103 104 csmEnabled string 105 CSMEnabled *bool 106 CSMPort string 107 CSMHost string 108 CSMClientID string 109 110 // Enables endpoint discovery via environment variables. 111 // 112 // AWS_ENABLE_ENDPOINT_DISCOVERY=true 113 EnableEndpointDiscovery *bool 114 enableEndpointDiscovery string 115 116 // Specifies the WebIdentity token the SDK should use to assume a role 117 // with. 118 // 119 // AWS_WEB_IDENTITY_TOKEN_FILE=file_path 120 WebIdentityTokenFilePath string 121 122 // Specifies the IAM role arn to use when assuming an role. 123 // 124 // AWS_ROLE_ARN=role_arn 125 RoleARN string 126 127 // Specifies the IAM role session name to use when assuming a role. 128 // 129 // AWS_ROLE_SESSION_NAME=session_name 130 RoleSessionName string 131 132 // Specifies the STS Regional Endpoint flag for the SDK to resolve the endpoint 133 // for a service. 134 // 135 // AWS_STS_REGIONAL_ENDPOINTS=regional 136 // This can take value as `regional` or `legacy` 137 STSRegionalEndpoint endpoints.STSRegionalEndpoint 138 139 // Specifies the S3 Regional Endpoint flag for the SDK to resolve the 140 // endpoint for a service. 141 // 142 // AWS_S3_US_EAST_1_REGIONAL_ENDPOINT=regional 143 // This can take value as `regional` or `legacy` 144 S3UsEast1RegionalEndpoint endpoints.S3UsEast1RegionalEndpoint 145 146 // Specifies if the S3 service should allow ARNs to direct the region 147 // the client's requests are sent to. 148 // 149 // AWS_S3_USE_ARN_REGION=true 150 S3UseARNRegion bool 151} 152 153var ( 154 csmEnabledEnvKey = []string{ 155 "AWS_CSM_ENABLED", 156 } 157 csmHostEnvKey = []string{ 158 "AWS_CSM_HOST", 159 } 160 csmPortEnvKey = []string{ 161 "AWS_CSM_PORT", 162 } 163 csmClientIDEnvKey = []string{ 164 "AWS_CSM_CLIENT_ID", 165 } 166 credAccessEnvKey = []string{ 167 "AWS_ACCESS_KEY_ID", 168 "AWS_ACCESS_KEY", 169 } 170 credSecretEnvKey = []string{ 171 "AWS_SECRET_ACCESS_KEY", 172 "AWS_SECRET_KEY", 173 } 174 credSessionEnvKey = []string{ 175 "AWS_SESSION_TOKEN", 176 } 177 178 enableEndpointDiscoveryEnvKey = []string{ 179 "AWS_ENABLE_ENDPOINT_DISCOVERY", 180 } 181 182 regionEnvKeys = []string{ 183 "AWS_REGION", 184 "AWS_DEFAULT_REGION", // Only read if AWS_SDK_LOAD_CONFIG is also set 185 } 186 profileEnvKeys = []string{ 187 "AWS_PROFILE", 188 "AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set 189 } 190 sharedCredsFileEnvKey = []string{ 191 "AWS_SHARED_CREDENTIALS_FILE", 192 } 193 sharedConfigFileEnvKey = []string{ 194 "AWS_CONFIG_FILE", 195 } 196 webIdentityTokenFilePathEnvKey = []string{ 197 "AWS_WEB_IDENTITY_TOKEN_FILE", 198 } 199 roleARNEnvKey = []string{ 200 "AWS_ROLE_ARN", 201 } 202 roleSessionNameEnvKey = []string{ 203 "AWS_ROLE_SESSION_NAME", 204 } 205 stsRegionalEndpointKey = []string{ 206 "AWS_STS_REGIONAL_ENDPOINTS", 207 } 208 s3UsEast1RegionalEndpoint = []string{ 209 "AWS_S3_US_EAST_1_REGIONAL_ENDPOINT", 210 } 211 s3UseARNRegionEnvKey = []string{ 212 "AWS_S3_USE_ARN_REGION", 213 } 214) 215 216// loadEnvConfig retrieves the SDK's environment configuration. 217// See `envConfig` for the values that will be retrieved. 218// 219// If the environment variable `AWS_SDK_LOAD_CONFIG` is set to a truthy value 220// the shared SDK config will be loaded in addition to the SDK's specific 221// configuration values. 222func loadEnvConfig() (envConfig, error) { 223 enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG")) 224 return envConfigLoad(enableSharedConfig) 225} 226 227// loadEnvSharedConfig retrieves the SDK's environment configuration, and the 228// SDK shared config. See `envConfig` for the values that will be retrieved. 229// 230// Loads the shared configuration in addition to the SDK's specific configuration. 231// This will load the same values as `loadEnvConfig` if the `AWS_SDK_LOAD_CONFIG` 232// environment variable is set. 233func loadSharedEnvConfig() (envConfig, error) { 234 return envConfigLoad(true) 235} 236 237func envConfigLoad(enableSharedConfig bool) (envConfig, error) { 238 cfg := envConfig{} 239 240 cfg.EnableSharedConfig = enableSharedConfig 241 242 // Static environment credentials 243 var creds credentials.Value 244 setFromEnvVal(&creds.AccessKeyID, credAccessEnvKey) 245 setFromEnvVal(&creds.SecretAccessKey, credSecretEnvKey) 246 setFromEnvVal(&creds.SessionToken, credSessionEnvKey) 247 if creds.HasKeys() { 248 // Require logical grouping of credentials 249 creds.ProviderName = EnvProviderName 250 cfg.Creds = creds 251 } 252 253 // Role Metadata 254 setFromEnvVal(&cfg.RoleARN, roleARNEnvKey) 255 setFromEnvVal(&cfg.RoleSessionName, roleSessionNameEnvKey) 256 257 // Web identity environment variables 258 setFromEnvVal(&cfg.WebIdentityTokenFilePath, webIdentityTokenFilePathEnvKey) 259 260 // CSM environment variables 261 setFromEnvVal(&cfg.csmEnabled, csmEnabledEnvKey) 262 setFromEnvVal(&cfg.CSMHost, csmHostEnvKey) 263 setFromEnvVal(&cfg.CSMPort, csmPortEnvKey) 264 setFromEnvVal(&cfg.CSMClientID, csmClientIDEnvKey) 265 266 if len(cfg.csmEnabled) != 0 { 267 v, _ := strconv.ParseBool(cfg.csmEnabled) 268 cfg.CSMEnabled = &v 269 } 270 271 regionKeys := regionEnvKeys 272 profileKeys := profileEnvKeys 273 if !cfg.EnableSharedConfig { 274 regionKeys = regionKeys[:1] 275 profileKeys = profileKeys[:1] 276 } 277 278 setFromEnvVal(&cfg.Region, regionKeys) 279 setFromEnvVal(&cfg.Profile, profileKeys) 280 281 // endpoint discovery is in reference to it being enabled. 282 setFromEnvVal(&cfg.enableEndpointDiscovery, enableEndpointDiscoveryEnvKey) 283 if len(cfg.enableEndpointDiscovery) > 0 { 284 cfg.EnableEndpointDiscovery = aws.Bool(cfg.enableEndpointDiscovery != "false") 285 } 286 287 setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey) 288 setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey) 289 290 if len(cfg.SharedCredentialsFile) == 0 { 291 cfg.SharedCredentialsFile = defaults.SharedCredentialsFilename() 292 } 293 if len(cfg.SharedConfigFile) == 0 { 294 cfg.SharedConfigFile = defaults.SharedConfigFilename() 295 } 296 297 cfg.CustomCABundle = os.Getenv("AWS_CA_BUNDLE") 298 299 var err error 300 // STS Regional Endpoint variable 301 for _, k := range stsRegionalEndpointKey { 302 if v := os.Getenv(k); len(v) != 0 { 303 cfg.STSRegionalEndpoint, err = endpoints.GetSTSRegionalEndpoint(v) 304 if err != nil { 305 return cfg, fmt.Errorf("failed to load, %v from env config, %v", k, err) 306 } 307 } 308 } 309 310 // S3 Regional Endpoint variable 311 for _, k := range s3UsEast1RegionalEndpoint { 312 if v := os.Getenv(k); len(v) != 0 { 313 cfg.S3UsEast1RegionalEndpoint, err = endpoints.GetS3UsEast1RegionalEndpoint(v) 314 if err != nil { 315 return cfg, fmt.Errorf("failed to load, %v from env config, %v", k, err) 316 } 317 } 318 } 319 320 var s3UseARNRegion string 321 setFromEnvVal(&s3UseARNRegion, s3UseARNRegionEnvKey) 322 if len(s3UseARNRegion) != 0 { 323 switch { 324 case strings.EqualFold(s3UseARNRegion, "false"): 325 cfg.S3UseARNRegion = false 326 case strings.EqualFold(s3UseARNRegion, "true"): 327 cfg.S3UseARNRegion = true 328 default: 329 return envConfig{}, fmt.Errorf( 330 "invalid value for environment variable, %s=%s, need true or false", 331 s3UseARNRegionEnvKey[0], s3UseARNRegion) 332 } 333 } 334 335 return cfg, nil 336} 337 338func setFromEnvVal(dst *string, keys []string) { 339 for _, k := range keys { 340 if v := os.Getenv(k); len(v) != 0 { 341 *dst = v 342 break 343 } 344 } 345} 346