-
-
Notifications
You must be signed in to change notification settings - Fork 906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue #906 add support for $AWS_PROFILE #966
Conversation
Hello @fviard, |
@trane9991 Thank you for your contribution, and sorry for my slow response time. A few things I see:
It would probably be better to keep it as it was before.
at the end. Don't do this, always put an explicit error message, because otherwise some orphan errors would appear in the log and no one will understand where it came from.
I don't know a lot of history of s3cmd, but I think that if there was this line, it is probably that there is another aws config file or a previous version of its format that used such a key? This one is just a matter of taste I guess, but for the import i would have preferred something like :
And so you can use them directly in the code. I hope that you will still like to complete your PR despite this long review ^^ |
Thanks for the in-depth review, the advice is highly appreciated! Regarding the:
The idea was if person specified
I'm not sure about this one as well, but it was added a long time ago since then credentials file format was standardized and usage of the credentials in the five years old and the unsupported format should be considered as a bad practice, and not sure if it needs to be supported. |
…- better error logging- use `Config().update_option()` to set keys
S3/Config.py
Outdated
|
||
config = PyConfigParser() | ||
|
||
debug("Reading AWS credentials from", aws_credential_file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that you forgot the "%s" in the "string" template part.
S3/Config.py
Outdated
if 'AWS_PROFILE' in os.environ: | ||
profile = os.environ['AWS_PROFILE'] | ||
|
||
debug("Using AWS profile '{}'".format(profile)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the old style string template to be coherent with the rest of the code.
Ex: debug("Using %s", profile)
S3/Config.py
Outdated
cred_content = cred_file.read() | ||
aws_credential_file = os.path.expanduser('~/.aws/credentials') | ||
if 'AWS_CREDENTIAL_FILE' in os.environ and os.path.isfile(os.environ['AWS_CREDENTIAL_FILE']): | ||
aws_credential_file = os.environ['AWS_CREDENTIAL_FILE'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that it was not done before, but as an improvement, it would be great if you can ensure to pass the strings you get from os.environ to config_unicodise.
The tests to be done to check if things are good, is like to create a folder with chinese characters, and try to put some chinese chars inside the configuration file itself. Normally keys don't have special chars, but so we are sure that the code is proof to nasty issues in the future.
S3/Config.py
Outdated
|
||
profile = "default" | ||
if 'AWS_PROFILE' in os.environ: | ||
profile = os.environ['AWS_PROFILE'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 previous lines can be simplified in to:
profile = os.environ.get('AWS_PROFILE', 'default')
So with the unicode safe conversion:
profile = config_unicodise(os.environ.get('AWS_PROFILE', 'default')
S3/Config.py
Outdated
profile_secret_key = config.get(profile, 'aws_secret_access_key') | ||
debug('Setting "aws_secret_access_key" from file {} as "secret_key"'.format(aws_credential_file)) | ||
Config().update_option('secret_key', config_unicodise(profile_secret_key)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the previous code behavior, I think that you should take care that maybe only a part of access/secret/token keys could be stored in the config file.
Like only the session token, or only the access_key, ...
The rest being provided on the command line for example.
S3/Config.py
Outdated
debug("env_Config: %s->%s" % (data["key"], print_value)) | ||
error("%d accessing credentials file %s" % (e.errno, aws_credential_file)) | ||
except NoOptionError as e: | ||
error("Couldn't find required key '{}' for the AWS Profile '{}' in the credentials file '{}'".format(e.option, e.section, aws_credential_file)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, "warning" would probably be enough. For the next exception also.
if data["orig_key"] == "AWSAccessKeyId" \ | ||
or data["orig_key"] == "aws_access_key_id": | ||
data["key"] = "access_key" | ||
elif data["orig_key"]=="AWSSecretKey" \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have found a reference about that:
https://blog.csanchez.org/2011/05/
Looks like it used to be the case up to 2011 at least.
Its a little bit annoying to have to take care of that, but that would probably be better to still handle that case.
Note: a warning might still be issued.
But users could have inherited config files or found old tutorial on internet and still be using that.
It is bad to break user existing setups just for updates when it is not strictly necessary.
Hey @fviard, I pushed the fixes for all your comments, had to refactor the func to support the legacy options without much uglinesses and repetition in the code. |
Thank you for your reactivity anyway. |
@fviard sorry for bothering you, but did you have any success testing this? |
Consider adding credentials refresh. Imagine one wants to sync a very large data set and provides a profile that is valid for 60minutes. The sync will fail after 60 min and the command needs to be re run, this is very slow since it will have to re enumerate the full bucket However if for example every 35 minutes a background process update the credentials file , s3cmd when it fails for a token expires reason, it should retry loading the credentials file. |
@Frantch The ones you are talking about is the credentials provided by AWS IAM Role and read from ec2 instance metadata. This type of credentials not covered in this PR since they are already supported. |
Merged, thank you very much @trane9991 and sorry for the long delay to push it after you being very reactive. |
@Frantch As said by Trane9991, this patch is not related to the same credentials. |
@trane9991 I don't understand this:
AWS IAM Roles look like this and I don't think they are supported. Is
|
@alexanderkjeldaas The role needs to be attached to the EC2 instance, then tool, that runs on this instance my use the role (get the credentials from Instance Metadata and user them). See Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances. Technically, what you want, could be achieved by Assume Role mechanism and it is not supported AFAIK (at least not by this PR). |
Add support for reading credentials from standardized AWS credentials file [1] with multiple profiles #906
New logic works as in PR #570 but with additional changes.
Reading credentials from the AWS credentials file can be triggered by setting any of following env variables:
AWS_CREDENTIAL_FILE
AWS_PROFILE
Default value for
AWS_PROFILE
isdefault
and forAWS_CREDENTIAL_FILE
is~/.aws/credentials
.If
AWS_CREDENTIAL_FILE
set to non-existing file, it will fallback to the default value. This way you can useAWS_CREDENTIAL_FILE=true
if you want to read credentials from the default location.Also, custom logic for parsing AWS credentials file was replaced by default configparser lib, because this custom logic was written in 2013 before credentials file format was standardized in 2014.
[1] https://aws.amazon.com/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/