-
Notifications
You must be signed in to change notification settings - Fork 108
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
Generation of API key on pbench-server #3368
Generation of API key on pbench-server #3368
Conversation
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 started to review this before reading all of the main tab, but I realize you're not rebased on top of Nikhil's merge and you've got a lot of conflicts and obsolete code that you need to clean up before this is ready for review!
This API doesn't seem very resource-centric. In particular, I expect that there will be a desire for an authorized user to be able to fetch the values of existing keys. And, there will certainly be a need to be able to revoke/remove an existing key. So, we'll want a suite of methods:
|
Yeah, all the openid-connect changes are on the main now, you should rebase this on top of the main and that should minimize the conflicting files. |
943d8c9
to
4f45ac7
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.
Great start, Siddardh, but sadly, if not unexpectedly, I have comments... 😆
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.
Great start, Siddardh, but sadly, if not unexpectedly, I have comments... 😆
Yeah, what Dave said. 😉
A few overriding themes emerge:
- I think the API "resource" name should be a noun rather than a verb.
- What do we really want in the API key token values? (They are not OIDC/Keycloak tokens, so they don't have to have the same contents, I think.)
- Do we really want them to auto-expire (I think we do not).
- Some attention needs to be paid to what we log and how (e.g., we have a special exception for dealing with internal server errors, which we should use, and we should avoid calling
abort()
in deeply-nested functions). - We need to support users having more than one key.
And, I've got a whole bunch of medium, small, and nit-level items.
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.
Okay, I glanced over the changes but there are already a lot of comments so I'll pass until you push another commit.
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.
Sorry to be posting/reviewing twice, but GitHub got confused and posted my previous review before I was ready....
It looks like you've addressed most of the items from my reviews from last week. However, you missed a couple of items: there's some odd code in test_verify_auth_api_key()
(1, 2) and test_verify_auth_api_key_invalid()
(3). And there is the stuff that I found in your updates.
Also, apparently, this PR now has a conflict in lib/pbench/server/api/__init__.py
, which you'll need to address before Mr. Jenkins will touch it.
And, I found one more thing which I request you fix, below.
Code cleanup and updg unit tests Rebasing on top of merged openid connect PR
c394c34
to
797081b
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.
The most important part is dropping the redundant audit CREATE
; see the explanation in the comment. I'm also really on the edge about requesting that you set the completion audit attributes
to record the key just in case we need to find it... but it's a value that's awkward to display.
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 is starting to look great! I think you've resolved all of my actual objections (although, I second Dave's, but I'll let him be the one to block the merge, now 😀), but I did find some more things which you should consider addressing.
It seems that Siddardh acknowledged and even "liked" several comments, but didn't make changes. We need to remove the duplicate and broken audit record. I'd really really like to see the audit log verified in the unit tests, plus adding (and verifying) the audit And Webb's right that, if this handling is turning a duplicate key into an internal server error, that's likely to become unpleasant ... |
I've updated the changes related to
Yeah, this is not the right way to handle this scenario. Adding some changes to handle the SQL Related errors for a debugging |
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.
Most of these changes are good; however, your attempt to refactor the SQL error decoding was not successful. I think we need to try a somewhat different approach. (I would be happy to discuss this with you, if you like.)
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 would be happy to discuss this with you, if you like.
I went ahead and captured my thoughts.
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're getting really close here!
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.
Yes, I'm with Dave: we're getting really close. But, there are a few items (although small, at this point) which need touching up.
In particular, the call to decode_integrity_error()
needs a little more work, and I recommend being a little more rigorous and concrete with its interface.
response = jsonify({"api_key": new_key}) | ||
response.status_code = HTTPStatus.OK | ||
return response |
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 seems a little "heavy" (or not DRY enough). I think it would be better to use a local variable to capture the response status, which you would set to OK
here and to CREATED
either inside the try
block after line 67 or in an else
clause on the try
block, and then have a common exit path where you create the response
, set the status_code
, and return
.
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 is also skipping the audit attributes
setting ...
Although ... this makes me realize that there isn't really a clear way to record the "duplicate, alternate success" status, and I'm not sure what to do about that. Probably nothing, in the context of this PR. 😦
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 is also skipping the audit attributes setting ...
Another excellent reason for a common return point!
I'm not sure what to do about that. Probably nothing, in the context of this PR. 😦
Yes, not in this PR.... 😏
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.
Just some commentary on recent changes and conversations, but I'm happy enough at this point to just get it in.
response = jsonify({"api_key": new_key}) | ||
response.status_code = HTTPStatus.OK | ||
return response |
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 is also skipping the audit attributes
setting ...
Although ... this makes me realize that there isn't really a clear way to record the "duplicate, alternate success" status, and I'm not sure what to do about that. Probably nothing, in the context of this PR. 😦
e, on_duplicate=DuplicateApiKey, on_null=NullKey | ||
) | ||
if decode_exc == e: |
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 should probably be if decode_exc is e
... that is, it's not just Object.__eq__(e)
(whatever logic the superclass __eq__
chooses, which might not be much) but the exact same exception instance. Although in the context of this logic I'm not sure it makes a functional difference since the other paths aren't likely to return an equal or identical instance. 😆
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.
Dave is, of course, correct -- we should be using is
, not ==
, to compare the two objects. (I had that in an earlier version of my suggestion, but I slipped up in my latest.)
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.
And this then prompts another tweak (which I'm not recommending for this PR, but...): since we're expecting decode_integrity_error()
to construct exception objects for us in two out of the three cases, we might as well pass in the c'tor for the third case as well, and then the code here can go back to just raise
'ing whatever it returns. 🙂
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 is good enough, now. 😀
It would be better with the is
/==
thing and the decode_integrity_error()
signature fixed, and it would be nicer if decode_integrity_error()
took an additional argument to construct the no-match return value, but I think we can merge this as it is, now (we can add the third factory to decode_integrity_error()
when we convert the other three DB classes to use it).
@@ -54,7 +55,7 @@ def process_result_value(self, value, dialect): | |||
|
|||
|
|||
def decode_integrity_error( | |||
exception: IntegrityError, on_null: type, on_duplicate: type | |||
exception: IntegrityError, on_null: Callable, on_duplicate: Callable |
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 is good, but I was hoping for something even more specific. 😏
exception: IntegrityError, on_null: Callable[[str], Exception], on_duplicate: Callable[[str], Exception]
e, on_duplicate=DuplicateApiKey, on_null=NullKey | ||
) | ||
if decode_exc == e: |
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.
Dave is, of course, correct -- we should be using is
, not ==
, to compare the two objects. (I had that in an earlier version of my suggestion, but I slipped up in my latest.)
e, on_duplicate=DuplicateApiKey, on_null=NullKey | ||
) | ||
if decode_exc == e: |
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.
And this then prompts another tweak (which I'm not recommending for this PR, but...): since we're expecting decode_integrity_error()
to construct exception objects for us in two out of the three cases, we might as well pass in the c'tor for the third case as well, and then the code here can go back to just raise
'ing whatever it returns. 🙂
response = jsonify({"api_key": new_key}) | ||
response.status_code = HTTPStatus.OK | ||
return response |
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 is also skipping the audit attributes setting ...
Another excellent reason for a common return point!
I'm not sure what to do about that. Probably nothing, in the context of this PR. 😦
Yes, not in this PR.... 😏
Let's get this in, but a suggestion for a small task for @siddardh-ra ... we should add a functional test case that uses your I hate the way our functional test system is getting forced into a single file in order to get test dependency ordering (because the |
Generate a unique API key internally when the user presents a Keycloak access_token and encode the user identity in the API key.
Reworked
active_token
table.This API Key will be also be validated under
verify_auth
module .POST
/api/v1/generate_key
call generates api_key and will be updated in the reworkedapi_key
(active_token
)