Skip to content
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

Allows profiles to automatically assume a role #34

Merged
merged 5 commits into from
Apr 19, 2018
Merged

Allows profiles to automatically assume a role #34

merged 5 commits into from
Apr 19, 2018

Conversation

morris25
Copy link
Contributor

@morris25 morris25 commented Mar 8, 2018

In response to #30

@samoconnor
Copy link
Contributor

Nice one!
Can you add a test? (Maybe not one that runs as part of runtests.jl but a stand-alone test with a README that describes how to create the appropriate .config files to run the test).

@@ -254,27 +254,62 @@ using IniFile
dot_aws_credentials_file() = get(ENV, "AWS_CONFIG_FILE",
joinpath(homedir(), ".aws", "credentials"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems based on the current doc that this should be changed to:

dot_aws_credentials_file() =
    get(ENV, "AWS_SHARED_CREDENTIALS_FILE",
        joinpath(homedir(), ".aws", "credentials")) 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I forgot to change that. Thanks!

function dot_aws_credentials()

@assert isfile(dot_aws_credentials_file())
@assert isfile(dot_aws_config_file())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to support systems with only one of these files. So the assert should probably be creds || conf.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up in function AWSCredentials() where dot_aws_credentials() is called we'll need to apply the same test.

ini = read(Inifile(), dot_aws_credentials_file())

config_ini = read(Inifile(), dot_aws_config_file())
creds_ini = read(Inifile(), dot_aws_credentials_file())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One or the other of these files may not exist, so read(Inifile(), ... will throw ERROR: SystemError: opening file food: No such file or directory. Probably best to have an if isfile around the block of code that uses that file.

The cli doc says that .credentials has precedence over .config for creds. So the logic should be something like:

  • if there is a .config file:
    • if there are credentials for profile in the config file load them
    • if there is a role_arn and source_profile for profile, grab the role_arnand overwrite theprofile` variable.
    • try to load credentials for profile in the config file again in case the source_profile refers to another profile in the config file.
  • if there is a .credentials file:
    • if there are credentials for profile in the .credentials file load them (overwriting whatever was loaded from the .config file.
  • create the AWSCredentials object
  • If there is a role_arn, call AssumeRole and create a new AWSCredentials object
  • return the AWSCredentials object

@samoconnor
Copy link
Contributor

Thinking a bit more about how to test this...
A test in runtests.jl could set AWS_SHARED_CREDENTIALS_FILE andAWS_CONFIG_FILE to point to temporary test files. The test could call AWSCredentials() to and inspect the resulting creds object for the expected keys based on the precedence rules for creds file vs config file. AWS_DEFAULT_PROFILE should also be set to something, and unset to ensure the correct default profile is used. In the case where STS AssumeRole is called, the test could check for the an access denied error, which would at least ensure that the AssumeRole call is reached.

@omus
Copy link
Member

omus commented Mar 13, 2018

Note that the source_profile may or may not have associated credentials.

# Has credentials
[profile root]
output = json
region = us-east-1

[profile root:dev]
source_profile = root
role_arn = arn:aws:iam::123456789000:role/Dev

[profile root:sub-dev]
source_profile = root:dev
role_arn = arn:aws:iam::123456789000:role/SubDev


profile = get(ENV, "AWS_DEFAULT_PROFILE",
get(ENV, "AWS_PROFILE", "default"))

region = get(ENV, "AWS_DEFAULT_REGION", "us-east-1")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be assuming a default region. If the profile doesn't have a region set or AWS_DEFAULT_REGION isn't set there should be an exception

Copy link
Contributor Author

@morris25 morris25 Mar 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should that also be the case in aws_config()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so. Maybe @samoconnor disagrees?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do :)
I have tried to include support for the env vars and config files that are uses by boto3 (and the AWS cli) as a convenience to end users. However, I'm not attempting to follow boto3's behaviour in every respect.

My intention is to try to make the Julia AWS interface as easy as possible for first time users. As such, I see having a default region as a feature that's good for people who don't know or care what a region is but just wan't to fetch some files from this thing called S3 where their collaborators keep their data.

Some examples:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having said that, it doesn't seem quite right to duplicate the region env lookup and default (the other place is here: https://github.com/JuliaCloud/AWSCore.jl/blob/master/src/AWSCore.jl#L109)

There is a slight problem in that struct AWSCredentials does not have a region field so the region from the .config or .credentials file can't currently be accessed by the aws_config function. I propose the following:

  • Add a default_region::String field to struct AWSCredentials.
  • Set default_region=get(ENV, "AWS_DEFAULT_REGION", "us-east-1") in the default constructor
  • In dot_aws_credentials, set default_region if specified by the config files.
  • In the aws_config function, change the region= kw parameter to region=creds.default_region.

I think this should preserve existing behaviour, keep the default in one place, and add support for reading the region from the config files.

@morris25
Copy link
Contributor Author

Nested roles should work now.

@samoconnor
Copy link
Contributor

Thanks @morris25! I won't have time to review this immediately. Easter school holidays are about to begin...

@morris25
Copy link
Contributor Author

Is this still alive?


profile = get(ENV, "AWS_DEFAULT_PROFILE",
get(ENV, "AWS_PROFILE", "default"))

region = get(ENV, "AWS_DEFAULT_REGION", "us-east-1")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having said that, it doesn't seem quite right to duplicate the region env lookup and default (the other place is here: https://github.com/JuliaCloud/AWSCore.jl/blob/master/src/AWSCore.jl#L109)

There is a slight problem in that struct AWSCredentials does not have a region field so the region from the .config or .credentials file can't currently be accessed by the aws_config function. I propose the following:

  • Add a default_region::String field to struct AWSCredentials.
  • Set default_region=get(ENV, "AWS_DEFAULT_REGION", "us-east-1") in the default constructor
  • In dot_aws_credentials, set default_region if specified by the config files.
  • In the aws_config function, change the region= kw parameter to region=creds.default_region.

I think this should preserve existing behaviour, keep the default in one place, and add support for reading the region from the config files.

@samoconnor
Copy link
Contributor

@morris25 sorry about the delay, and thanks for your efforts!

@samoconnor samoconnor merged commit 8273c07 into JuliaCloud:master Apr 19, 2018
@omus omus mentioned this pull request Jul 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants