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 Regional Endpoint flag for the sdk to resolve the endpoint for a service 132 // 133 // AWS_STS_REGIONAL_ENDPOINTS =sts_regional_endpoint 134 // This can take value as `regional` or `legacy` 135 STSRegionalEndpoint endpoints.STSRegionalEndpoint 136} 137 138var ( 139 csmEnabledEnvKey = []string{ 140 "AWS_CSM_ENABLED", 141 } 142 csmHostEnvKey = []string{ 143 "AWS_CSM_HOST", 144 } 145 csmPortEnvKey = []string{ 146 "AWS_CSM_PORT", 147 } 148 csmClientIDEnvKey = []string{ 149 "AWS_CSM_CLIENT_ID", 150 } 151 credAccessEnvKey = []string{ 152 "AWS_ACCESS_KEY_ID", 153 "AWS_ACCESS_KEY", 154 } 155 credSecretEnvKey = []string{ 156 "AWS_SECRET_ACCESS_KEY", 157 "AWS_SECRET_KEY", 158 } 159 credSessionEnvKey = []string{ 160 "AWS_SESSION_TOKEN", 161 } 162 163 enableEndpointDiscoveryEnvKey = []string{ 164 "AWS_ENABLE_ENDPOINT_DISCOVERY", 165 } 166 167 regionEnvKeys = []string{ 168 "AWS_REGION", 169 "AWS_DEFAULT_REGION", // Only read if AWS_SDK_LOAD_CONFIG is also set 170 } 171 profileEnvKeys = []string{ 172 "AWS_PROFILE", 173 "AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set 174 } 175 sharedCredsFileEnvKey = []string{ 176 "AWS_SHARED_CREDENTIALS_FILE", 177 } 178 sharedConfigFileEnvKey = []string{ 179 "AWS_CONFIG_FILE", 180 } 181 webIdentityTokenFilePathEnvKey = []string{ 182 "AWS_WEB_IDENTITY_TOKEN_FILE", 183 } 184 roleARNEnvKey = []string{ 185 "AWS_ROLE_ARN", 186 } 187 roleSessionNameEnvKey = []string{ 188 "AWS_ROLE_SESSION_NAME", 189 } 190 stsRegionalEndpointKey = []string{ 191 "AWS_STS_REGIONAL_ENDPOINTS", 192 } 193) 194 195// loadEnvConfig retrieves the SDK's environment configuration. 196// See `envConfig` for the values that will be retrieved. 197// 198// If the environment variable `AWS_SDK_LOAD_CONFIG` is set to a truthy value 199// the shared SDK config will be loaded in addition to the SDK's specific 200// configuration values. 201func loadEnvConfig() (envConfig, error) { 202 enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG")) 203 return envConfigLoad(enableSharedConfig) 204} 205 206// loadEnvSharedConfig retrieves the SDK's environment configuration, and the 207// SDK shared config. See `envConfig` for the values that will be retrieved. 208// 209// Loads the shared configuration in addition to the SDK's specific configuration. 210// This will load the same values as `loadEnvConfig` if the `AWS_SDK_LOAD_CONFIG` 211// environment variable is set. 212func loadSharedEnvConfig() (envConfig, error) { 213 return envConfigLoad(true) 214} 215 216func envConfigLoad(enableSharedConfig bool) (envConfig, error) { 217 cfg := envConfig{} 218 219 cfg.EnableSharedConfig = enableSharedConfig 220 221 // Static environment credentials 222 var creds credentials.Value 223 setFromEnvVal(&creds.AccessKeyID, credAccessEnvKey) 224 setFromEnvVal(&creds.SecretAccessKey, credSecretEnvKey) 225 setFromEnvVal(&creds.SessionToken, credSessionEnvKey) 226 if creds.HasKeys() { 227 // Require logical grouping of credentials 228 creds.ProviderName = EnvProviderName 229 cfg.Creds = creds 230 } 231 232 // Role Metadata 233 setFromEnvVal(&cfg.RoleARN, roleARNEnvKey) 234 setFromEnvVal(&cfg.RoleSessionName, roleSessionNameEnvKey) 235 236 // Web identity environment variables 237 setFromEnvVal(&cfg.WebIdentityTokenFilePath, webIdentityTokenFilePathEnvKey) 238 239 // CSM environment variables 240 setFromEnvVal(&cfg.csmEnabled, csmEnabledEnvKey) 241 setFromEnvVal(&cfg.CSMHost, csmHostEnvKey) 242 setFromEnvVal(&cfg.CSMPort, csmPortEnvKey) 243 setFromEnvVal(&cfg.CSMClientID, csmClientIDEnvKey) 244 245 if len(cfg.csmEnabled) != 0 { 246 v, _ := strconv.ParseBool(cfg.csmEnabled) 247 cfg.CSMEnabled = &v 248 } 249 250 regionKeys := regionEnvKeys 251 profileKeys := profileEnvKeys 252 if !cfg.EnableSharedConfig { 253 regionKeys = regionKeys[:1] 254 profileKeys = profileKeys[:1] 255 } 256 257 setFromEnvVal(&cfg.Region, regionKeys) 258 setFromEnvVal(&cfg.Profile, profileKeys) 259 260 // endpoint discovery is in reference to it being enabled. 261 setFromEnvVal(&cfg.enableEndpointDiscovery, enableEndpointDiscoveryEnvKey) 262 if len(cfg.enableEndpointDiscovery) > 0 { 263 cfg.EnableEndpointDiscovery = aws.Bool(cfg.enableEndpointDiscovery != "false") 264 } 265 266 setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey) 267 setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey) 268 269 if len(cfg.SharedCredentialsFile) == 0 { 270 cfg.SharedCredentialsFile = defaults.SharedCredentialsFilename() 271 } 272 if len(cfg.SharedConfigFile) == 0 { 273 cfg.SharedConfigFile = defaults.SharedConfigFilename() 274 } 275 276 cfg.CustomCABundle = os.Getenv("AWS_CA_BUNDLE") 277 278 // STS Regional Endpoint variable 279 for _, k := range stsRegionalEndpointKey { 280 if v := os.Getenv(k); len(v) != 0 { 281 STSRegionalEndpoint, err := endpoints.GetSTSRegionalEndpoint(v) 282 if err != nil { 283 return cfg, fmt.Errorf("failed to load, %v from env config, %v", k, err) 284 } 285 cfg.STSRegionalEndpoint = STSRegionalEndpoint 286 } 287 } 288 289 return cfg, nil 290} 291 292func setFromEnvVal(dst *string, keys []string) { 293 for _, k := range keys { 294 if v := os.Getenv(k); len(v) != 0 { 295 *dst = v 296 break 297 } 298 } 299} 300