Browse code

Fixes #989 - in aws_credential_file, fixes read_string only available with py3 + refactor for possible unicode issues

Florent Viard authored on 2020/03/29 09:41:21
Showing 1 changed files
... ...
@@ -24,11 +24,15 @@ except ImportError:
24 24
     import http.client as httplib
25 25
 import locale
26 26
 
27
-try: 
28
- from configparser import NoOptionError, NoSectionError, MissingSectionHeaderError, ConfigParser as PyConfigParser
27
+try:
28
+ from configparser import (NoOptionError, NoSectionError,
29
+                           MissingSectionHeaderError, ParsingError,
30
+                           ConfigParser as PyConfigParser)
29 31
 except ImportError:
30 32
   # Python2 fallback code
31
-  from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError, ConfigParser as PyConfigParser
33
+  from ConfigParser import (NoOptionError, NoSectionError,
34
+                            MissingSectionHeaderError, ParsingError,
35
+                            ConfigParser as PyConfigParser)
32 36
 
33 37
 try:
34 38
     unicode
... ...
@@ -286,31 +290,44 @@ class Config(object):
286 286
 
287 287
     def aws_credential_file(self):
288 288
         try:
289
-            aws_credential_file = os.path.expanduser('~/.aws/credentials') 
290
-            if 'AWS_CREDENTIAL_FILE' in os.environ and os.path.isfile(os.environ['AWS_CREDENTIAL_FILE']):
291
-                aws_credential_file = config_unicodise(os.environ['AWS_CREDENTIAL_FILE'])
289
+            aws_credential_file = os.path.expanduser('~/.aws/credentials')
290
+            credential_file_from_env = os.environ.get('AWS_CREDENTIAL_FILE')
291
+            if credential_file_from_env and \
292
+               os.path.isfile(credential_file_from_env):
293
+                aws_credential_file = config_unicodise(credential_file_from_env)
294
+            elif not os.path.isfile(aws_credential_file):
295
+                return
296
+
297
+            warning("Errno %d accessing credentials file %s" % (e.errno, aws_credential_file))
292 298
 
293 299
             config = PyConfigParser()
294 300
 
295 301
             debug("Reading AWS credentials from %s" % (aws_credential_file))
302
+            with io.open(aws_credential_file, "r",
303
+                         encoding=getattr(self, 'encoding', 'UTF-8')) as fp:
304
+                config_string = fp.read()
296 305
             try:
297
-                config.read(aws_credential_file)
298
-            except MissingSectionHeaderError:
299
-                # if header is missing, this could be deprecated credentials file format
300
-                # as described here: https://blog.csanchez.org/2011/05/
301
-                # then do the hacky-hack and add default header
302
-                # to be able to read the file with PyConfigParser() 
303
-                config_string = None
304
-                with open(aws_credential_file, 'r') as f:
305
-                    config_string = '[default]\n' + f.read()
306
-                config.read_string(config_string.decode('utf-8'))
307
-
306
+                try:
307
+                    # readfp is replaced by read_file in python3,
308
+                    # but so far readfp it is still available.
309
+                    config.readfp(io.StringIO(config_string))
310
+                except MissingSectionHeaderError:
311
+                    # if header is missing, this could be deprecated credentials file format
312
+                    # as described here: https://blog.csanchez.org/2011/05/
313
+                    # then do the hacky-hack and add default header
314
+                    # to be able to read the file with PyConfigParser()
315
+                    config_string = u'[default]\n' + config_string
316
+                    config.readfp(io.StringIO(config_string))
317
+            except ParsingError as exc:
318
+                raise ValueError(
319
+                    "Error reading aws_credential_file "
320
+                    "(%s): %s" % (aws_credential_file, str(exc)))
308 321
 
309 322
             profile = config_unicodise(os.environ.get('AWS_PROFILE', "default"))
310 323
             debug("Using AWS profile '%s'" % (profile))
311 324
 
312 325
             # get_key - helper function to read the aws profile credentials
313
-            # including the legacy ones as described here: https://blog.csanchez.org/2011/05/ 
326
+            # including the legacy ones as described here: https://blog.csanchez.org/2011/05/
314 327
             def get_key(profile, key, legacy_key, print_warning=True):
315 328
                 result = None
316 329
 
... ...
@@ -325,7 +342,7 @@ class Config(object):
325 325
                             profile = "default"
326 326
                             result = config.get(profile, key)
327 327
                             warning(
328
-                                    "Legacy configuratin key '%s' used, " % (key) + 
328
+                                    "Legacy configuratin key '%s' used, " % (key) +
329 329
                                     "please use the standardized config format as described here: " +
330 330
                                     "https://aws.amazon.com/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/"
331 331
                                      )
... ...
@@ -333,23 +350,23 @@ class Config(object):
333 333
                             pass
334 334
 
335 335
                 if result:
336
-                    debug("Found the configuration option '%s' for the AWS Profile '%s' in the credentials file %s" % (key, profile, aws_credential_file)) 
336
+                    debug("Found the configuration option '%s' for the AWS Profile '%s' in the credentials file %s" % (key, profile, aws_credential_file))
337 337
                 return result
338 338
 
339
-            profile_access_key = get_key(profile, "aws_access_key_id", "AWSAccessKeyId") 
339
+            profile_access_key = get_key(profile, "aws_access_key_id", "AWSAccessKeyId")
340 340
             if profile_access_key:
341 341
                 Config().update_option('access_key', config_unicodise(profile_access_key))
342 342
 
343
-            profile_secret_key = get_key(profile, "aws_secret_access_key", "AWSSecretKey") 
343
+            profile_secret_key = get_key(profile, "aws_secret_access_key", "AWSSecretKey")
344 344
             if profile_secret_key:
345 345
                 Config().update_option('secret_key', config_unicodise(profile_secret_key))
346 346
 
347
-            profile_access_token = get_key(profile, "aws_session_token", None, False) 
347
+            profile_access_token = get_key(profile, "aws_session_token", None, False)
348 348
             if profile_access_token:
349 349
                 Config().update_option('access_token', config_unicodise(profile_access_token))
350 350
 
351 351
         except IOError as e:
352
-            warning("%d accessing credentials file %s" % (e.errno, aws_credential_file))
352
+            warning("Errno %d accessing credentials file %s" % (e.errno, aws_credential_file))
353 353
         except NoSectionError as e:
354 354
             warning("Couldn't find AWS Profile '%s' in the credentials file '%s'" % (profile, aws_credential_file))
355 355