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
add support for AssumeRole provider #874
Conversation
Is this too invasive a change to review/consider? I could submit a PR that just modifies |
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.
Thanks for the PR @hardbyte.
Let me drop few implementation details for your reference.
We can do this in a similar manner as the other Providers, We could create an interface compatible class to Provider
.
class Provider(object):
__metaclass__ = ABCMeta
@abstractmethod
def retrieve(self):
pass
@abstractmethod
def is_expired(self):
pass
It should honor these functions to be a valid Provider
. Check credentials.py file for these details
Please check |
Thanks for the review. It sounds like sub-classing My guess is the interface will be clunkier than my currently proposed functional one though. Thinking through a couple of made up user stories: 1 As a backend developer, I want to be able to generate temporary, restricted object store credentials to allow my front end clients to upload directly to the object store using an s3 compatible client library. In particular I want to easily serialize the new credentials. 2 As a client library developer, I want to easily be able to instantiate a minio-py client using credentials supplied to me in serialized form. 3 As someone else, at times I want to create minio clients with restricted & temporary credentials. 2 is already fully supported using the minio constructor so can be safely ignored. In 1 and 3 I think it would feel most natural for the api to be from minio import assume_role
credentials = assume_role(minio_client, policy, ...) Where the For 1 the user serializes via getting the credential's For 3 the user then creates a new minio client with the newly returned credentials: restricted_client = Minio(endpoint, credentials=credentials, ...) If instead the minio-py API is simply an from minio.credentials import AssumeRoleProvider
provider = AssumeRoleProvider(minio_client, policy, ...)
credentials = provider.retrieve() Everything else being the same from there. Still I feel this Other options I was thinking about include |
df3e023
to
fae417d
Compare
@hardbyte The benefit of using the Provider class is that we could chain the providers sequentially so that if one service is down/denies it will automatically query the next service We should follow the same across all the providers. As this is pretty much the agreed standard for all the targets. If you need to use the other way, you could use it in application side for your convenience. |
@@ -0,0 +1,55 @@ | |||
# -*- coding: utf-8 -*- |
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.
This example should be changed. It should use AssumeRoleProvider
minio/credentials/assume_role.py
Outdated
return self._expiry.is_expired() | ||
|
||
|
||
def assume_role(mc, RoleArn=None, RoleSessionName=None, Policy=None, DurationSeconds=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.
We could remove this as it is not recommended to pass clients to functions, Let us follow the Provider class everywhere
Can you fix the conflicts @hardbyte |
I'll rebase and resolve the conflicts now and adjust the example to use the I'd appreciate your thoughts about how this could be used by clients though. I realize you're thinking about it like another credentials provider for the minio client (boto does this too and I'm all for supporting this use case), however for most end users it will instead be used to get credentials to give to someone else (another service, a front end client etc). Please see my (made up) user stories earlier in the thread. Boto supports this lower level api too by exposing By the way running the unit tests on master with python3.7 has just got substantially slower for me - after pulling the time went from <1 second to 40+ seconds. I'm not sure if a recent change in master has caused this regression: |
fae417d
to
eb025c9
Compare
We should be able to expose them if they need direct access @hardbyte but it should also be a credential provider such that it can be chained together with other providers, in the current form.
Do not know, we should check all the pep8 fixes we did in master @hardbyte @balamurugana @kannappanr |
Just debugging the credential "refreshing" and I notice the existing code uses local time stamps instead of utc which seems like a bad idea. I'll push an implemention the same as the
|
Yes it should use utc() @hardbyte we shouldn't rely on anything i.e local TZ |
7c6217f
to
de56a93
Compare
Ok this has now been tested against AWS sts as well as Minio - @harshavardhana the changes required to have a valid signature are here. I think that means the signing PR is good to merge - sorry for all the rebasing and force pushing I wanted to avoid to many conflicts with the pep8 work that is landing in master. For this PR I still plan to refactor the expiry stuff to use UTC aware datetime objects. It won't be today though I'm afraid. |
FYI. I pulled the PR and ran the examples/assume_role.py on a local minio instance with a self-sign cert. Got the following error "SignatureDoesNotMatchThe request signature we calculated doesn't match the signature you provided. Check your key and signing method. " |
Thanks for trying it out @Qantas - I just tried using the self signed certificate in There is definitely an issue with the credentials expiry though - I think it will have different behavior in different time zones 🤢 |
3241d9d
to
e568226
Compare
@harshavardhana @donatello @Praveenrajmani I think this is now ready for another review. I've addressed all the issues you've pointed out earlier; tested it against both AWS and Minio; fixed the timezones used by |
Very nice @hardbyte 🍰 |
Of course please resolve the conflicts @hardbyte |
Start example of using assume role
Add copyright header to credentials/parsers.py
…oviders' expiry. Use pytz to help Python2 understand timezones.
e568226
to
f13be46
Compare
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 tested 🍰
LGTM |
I pulled the latest merged version and gave it a try. got a different error "Generating temporary credentials not allowed for this request" I am using a minio_client with a http_client to bring the cert in since it is not in your assume_role.py example code. |
You cannot generate temporary credentials for root account @Qantas |
|
This PR adds a
assume_role
api to mino-py allowing users to generate temporary credentials using theAssumeRole
STS API. It has to modify how signatures are generated to allow signing requests for other services e.g.,"sts"
.I'm assuming the functional python API should be replaced - but let me know.
Further discussion original feature request in #871.
Server side API documentation: