-
Notifications
You must be signed in to change notification settings - Fork 15
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
Implement a configurable credentials resolver chain #452
base: develop
Are you sure you want to change the base?
Implement a configurable credentials resolver chain #452
Conversation
...ages/smithy-aws-core/src/smithy_aws_core/credentials_resolvers/credentials_resolver_chain.py
Outdated
Show resolved
Hide resolved
if source[0](): | ||
self._credentials_resolver = source[1]() |
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.
What are we actually calling here 😅 A state check and then a builder for the resolver?
I think this works, I'm wondering if we want to actually make a class for the abstraction rather than composing lists of functions. This is probably minor at this point, but may be worth spending some time on ergonomics later.
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.
Yeah - your right that this is a little confusing - I was hoping the typing itself would be sufficient... but its not.
This is separating "is available" from construction for a given credential source. We first call an "is available" callable to see if we should construct credentials from a given source - think cases like SSO or assume role or process credentials, ect where we can cheaply identify when the credentials are available (by checking the presence of env/config values), but actually constructing a resolver might be more expensive.
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.
If we're concerned about perf for instantiation, you can always have a class method on the class reference. That can be used to check availability and then you have the class there to instantiate if we're ready. It's essentially the same abstraction just wrapped into a single input.
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.
The other consideration in this is that construction of a given resolver is based on the source - and its not always a 1:1 mapping and the order of precedence is important. As an example: assuming a role from a web identity. Assuming a role from a web identity token file can be specified either through the environment or through the shared config file and the order of precedence (limited just to static credentials and web identity) is:
- static credentials from ENV
- Web identity from ENV
- static credentials from profile
- web identity from profile.
In addition RE: construction, the resolver chain may need to construct certain resolvers with different options than we'd typically specify by default - an example of this is IMDS credentials. Since IMDS is the last option and is always checked, we usually use lower retries and timeouts to have it fail faster.
Edit: I do think a class/protocol interface makes a lot more sense. I'm working on an update to that, but I think the above answer still applies to why we might not just want to add an is_available method to AWS Credentials Resolvers.
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.
See commit for defining source as a class/Protocol - definitely easier to understand/use I think.
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.
LGTM!
...ages/smithy-aws-core/src/smithy_aws_core/credentials_resolvers/credentials_resolver_chain.py
Outdated
Show resolved
Hide resolved
): | ||
"""Resolves AWS Credentials from system environment variables.""" | ||
|
||
def __init__(self, *, sources: List[CredentialSource] | None = None): |
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.
Sources should be a Sequence
. But also, why isn't it just a sequence of credential resolvers that take the same identity?
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.
See the comments here for why I used a tuple of callables for checking whether a source of credentials is available and constructing it.
…vers/credentials_resolver_chain.py Co-authored-by: Nate Prewitt <[email protected]>
Description of changes:
Implements a configurable credentials resolver chain and sets it as the default identity resolver in generated Config.
The credential chain is configured by providing tuples of callables for each credential source, the first returns true if credentials are available from that source, the second is a constructor for that source.
Individual credential resolvers can be constructed from multiple sources (eg: web identity token from environment or profile) - having the sources be defined using callable's allows us to de-couple the different sources for a given credential resolver from the implementation of the resolver itself.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.