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