Skip to content

Conversation

@elventear
Copy link

When fetching credentials after obtaining the boto3 session, we check if the configuration has an optional assume_role field, which indicates that role needs to be assumed to obtain the credentials.

If found, the role is assumed and used to obtain the credentails. If not the original boto3 session is used to obtain the credentials.

When fetching credentials after obtaining the boto3 session, we check if
the configuration has an optional `assume_role` field, which indicates
that role needs to be assumed to obtain the credentials.

If found, the role is assumed and used to obtain the credentails. If not
the original boto3 session is used to obtain the credentials.
@jmkeyes
Copy link
Owner

jmkeyes commented Apr 17, 2025

Thanks for making this contribution! I agree that having the option to assume a role would be a good addition to the accepted configuration keys: using temporary credentials is a much better option than static access/secret keys.

Copy link
Owner

@jmkeyes jmkeyes left a comment

Choose a reason for hiding this comment

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

/lgtm

The whitespace changes in the diff of the test code made things a bit harder to read, but I can run black later if needed.

@jmkeyes
Copy link
Owner

jmkeyes commented Apr 17, 2025

Not strictly relevant to the PR, but the AWS SDK can also assume a role if configured to do so.

While it is nice to explicitly configure it ourselves here, it begs the question of how much responsibility this library should take in replicating that logic.

This also ties into #8: where do we draw the line between the behaviour of this library (via configuration) and the implicit behaviour of the boto3 library and the AWS SDK?

* Run black.
* Make role assumption logic more explicit.
* Make role session name optional.
@elventear
Copy link
Author

elventear commented Apr 17, 2025

Not strictly relevant to the PR, but the AWS SDK can also assume a role if configured to do so.

While it is nice to explicitly configure it ourselves here, it begs the question of how much responsibility this library should take in replicating that logic.

This also ties into #8: where do we draw the line between the behaviour of this library (via configuration) and the implicit behaviour of the boto3 library and the AWS SDK?

We have a considerable number of profiles and AWS child accounts that require cross-account authentication. Tightly coupling IAM configuration between identity roles and resource access can become difficult (one reason being IAM policy size limits) and keeping our identity roles loosely coupled from some resource access roles makes maintenance easier.

We could have additional configuration settings for the AWS SDK to assume the roles, but all the combinations we have would create an explosion of configuration entries. Being able to have loose coupling between the identity roles we use and resource roles in the configuration for this library makes management of all these things much simpler for our users.

@elventear elventear requested a review from jmkeyes April 17, 2025 22:03
@jmkeyes
Copy link
Owner

jmkeyes commented Apr 17, 2025

Not strictly relevant to the PR, but the AWS SDK can also assume a role if configured to do so.

While it is nice to explicitly configure it ourselves here, it begs the question of how much responsibility this library should take in replicating that logic.

This also ties into #8: where do we draw the line between the behaviour of this library (via configuration) and the implicit behaviour of the boto3 library and the AWS SDK?

We have a considerable number of profiles and AWS child accounts that require cross-account authentication. Tightly coupling IAM configuration between identity roles and resource access can become difficult (one reason being IAM policy size limits) and keeping our identity roles loosely coupled from some resource access roles makes maintenance easier.

We could have additional configuration settings for the AWS SDK to assume the roles, but all the combinations we have would create an explosion of configuration entries. Being able to have loose coupling between the identity roles we use and resource roles in the configuration for this library makes management of all these things much simpler for our users.

I agree.

The first use case for this keyring backend had very little need for configuration at all.

While it is convenient to define access/secret keys in the keyringrc.cfg for a trivial use case doing so is still a bad practice: this library isn't responsible for managing the credentials to access AWS but it should use the existing ones.

For version 3.x of this backend, I'm tempted to drop support for specifying access/secret keys in configuration and explicitly require users to migrate them to ~/.aws/credentials.

This would substantially limit the configuration options that this library needs to be aware of.

@elventear
Copy link
Author

@jmkeyes does this look good to merge?

assumed_role = session.client("sts").assume_role(
RoleArn=config["assume_role"],
RoleSessionName=config.get(
"assume_role_session_name", "KeyRingsCodeArtifact"
Copy link
Author

Choose a reason for hiding this comment

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

So the AWS SDK will not pick a RoleSessionName for you; you can see the docs that they say they are required. So I have include an explicit default as a fallback instead.

Copy link
Owner

@jmkeyes jmkeyes May 21, 2025

Choose a reason for hiding this comment

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

As mentioned in a comment, I'd like this fallback to be a dynamic value usable for auditing in CloudTrail, but that's not required for this PR.

@jmkeyes
Copy link
Owner

jmkeyes commented May 21, 2025

@jmkeyes does this look good to merge?

Almost! Here are some thoughts:

  1. I'd like to rename the assume_role configuration option to assume_role_arn to be explicit about the content of the string.
  2. I've finally had some time to rework the unit tests to use botocore.stub.Stubber to stub out the AWS interactions so I can avoid the drawbacks of monkey-patching boto3 internals. As of 537fe6f, CodeArtifactBackend has a session keyword argument that defaults to boto3.session.Session() if not provided. There's a StubbingSession in the tests directory that allows for injecting expected responses from AWS API calls.
  3. Finally -- while not required in this PR -- since the role session name is mandatory for the AssumeRole call, I'd prefer to make the default something usable for auditing in CloudTrail rather than a just fixed string. I want to include information about the identity of the user invoking AssumeRole at minimum. (I can add this in a followup commit.)

Let me know what you think!

aws_access_key_id=config.get("aws_access_key_id"),
aws_secret_access_key=config.get("aws_secret_access_key"),
)
session = self.get_boto_session(region=region, config=config)
Copy link
Owner

Choose a reason for hiding this comment

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

As part of 537fe6f, I've created a _get_codeartifact_client instance method that returns an initialized CodeArtifact service client with specific options.

assumed_role = session.client("sts").assume_role(
RoleArn=config["assume_role"],
RoleSessionName=config.get(
"assume_role_session_name", "KeyRingsCodeArtifact"
Copy link
Owner

@jmkeyes jmkeyes May 21, 2025

Choose a reason for hiding this comment

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

As mentioned in a comment, I'd like this fallback to be a dynamic value usable for auditing in CloudTrail, but that's not required for this PR.

@@ -1,2 +1,3 @@
pytest >= 6
pytest-cov
pytest-mock
Copy link
Owner

Choose a reason for hiding this comment

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

This shouldn't be necessary with the recent unit test modifications.

Copy link
Owner

Choose a reason for hiding this comment

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

The recent changes to the unit tests in 537fe6f may help clean up these tests.

- `token_duration`: Validity period (in seconds) for retieved authorization tokens.
- `aws_access_key_id`: Use a specific AWS access key to authenticate with AWS.
- `aws_secret_access_key`: Use a specific AWS secret access key to authenticate with AWS.
- `assume_role`: Role ARN to assume with the current profile name to get the CodeArtifact credentials.
Copy link
Owner

@jmkeyes jmkeyes May 21, 2025

Choose a reason for hiding this comment

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

I'd like to rename this to assume_role_arn to be more explicit about the content it contains.

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.

2 participants