-
Notifications
You must be signed in to change notification settings - Fork 46
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
Reworked API key management to use internal IDs instead of API keys #99
Conversation
This PR was tested by custom branch build on jenkins |
This PR was tested by custom branch build on jenkins |
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.
@billkalter Change looks good to me 👍 minor comments posted, otherwise it's all good.
- Verified the following:
- change to APIKey class.
- change to the AuthIdentityManager interface.
- Implementations of AuthIdentityManager. Dao impl - Identity table -> <hash_auth_id, Identity Object> & index table -> <Internal_id, hash_auth_id>
@@ -418,13 +418,13 @@ private void cacheAuthorizationInfoByInternalId(String internalId, Authorization | |||
*/ | |||
private AuthorizationInfo getUncachedAuthorizationInfoByInternalId(String internalId) { | |||
// Retrieve the roles by internal ID |
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.
minor: missed the comment update.
@@ -17,14 +17,14 @@ | |||
private final PrincipalCollection _principals; | |||
private final String _credentials; | |||
|
|||
public ApiKeyAuthenticationInfo(ApiKey apiKey, String realm) { | |||
public ApiKeyAuthenticationInfo(String authenticationId, ApiKey apiKey, String realm) { |
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.
minor: null check for authenticationId.
* | ||
* In the original design this ID was only used internally, but over time it has become an accepted public-facing | ||
* identifier for identities. This is why for historical reasons this field is called "internalId" even though | ||
* it is used as both the unique internal and external identifier for this identity. | ||
*/ | ||
private final String _internalId; | ||
|
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've seen your note about the reason for keeping the InternalID naming as is, but if it's only about changing the name at various places, I'm more biased in changing it, as it's now used as an external identifier as well. But it's your call though.
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 reason I didn't change it is because the change cascades down. Notably, to be consistent I'd have to change Subject.java and InternalAuthorizer.java, as well as any classes which use them. I agree with your statement and don't mind doing it, but it makes this PR all the larger.
* .withOwner("[email protected]") | ||
* .addRoles("role1") | ||
* .buildFrom("123"); | ||
* |
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.
minor: I think it's buildNew("123") here.
@sujithvaddi I addressed your feedback. There's two commits; the first is small and contains the smaller updates from your feedback. The second commit is much larger, but at its core it only contains the following changes:
All other changes stem from one of those changes. One thing I didn't change is that the default table for storing the ID index is still |
This PR was tested by custom branch build on jenkins |
This PR was tested by custom branch build on jenkins |
@billkalter Looks good to me. Please go ahead and merge.
|
Github Issue
50 (partial)
What Are We Doing Here?
The current API administration task uses the API key itself as input. However, API keys are supposed to be secret, and in our experience user's can't be trusted not to communicate their API key over a public channel when they need new permissions, such as by posting the key in a chat client or an email.
Additionally, as Emo moves toward distributed API key and permission management there will be a separation between individuals who grant specific roles. For example, you may go to team A to get permission to read from tables "team_a:*" while you may go to team B to get permission to read from tables "team_b:*". In both cases you may not trust giving your secret credential to anyone on either of those teams, but with the current API there is no alternative but to do so in order to for them to grant your API key a role with the new permissions.
This PR changes the API administration task to operate on the immutable internal IDs instead of the keys themselves, now generically referred to as "authentication IDs" or, for API keys in particular, "keys". So as not to break existing code or data the IDs are still referred to as
internalId
, even though it is used both internally and externally as a non-secret public identifier.This PR consists of two commits. The first is the actual work for this PR. The second is simply a rename of
RoleUpdateRequest
toRoleModification
. This was done for two reasons. The first is simply to mirror the class nameAuthIdentityModification
. The second is thatRoleUpdateRequest
was being used to both create and update roles, so it was a bit of a misnomer. The new name is more generic and less confusingly applies to both operations, though if there's a better name for it please make a comment.A few notes:
AuthIdentityManager
to work on internal IDs instead of authentication IDs. As such this PR encompasses more changes than I would have thought necessary at the outset, but ultimately I think it flows well and closes a possible vulnerability in that it no longer stores the unencrypted API key as an attribute of theApiKey
class.AuthIdentityManager
. This is actually a change for the better since it allows for an atomic migrate operation, and arguably it should have been implemented this way in the first place.DataCenterSynchronizedAuthIdentityManager
was introduced to ensure each mutative API key operation is serializable within the local data center. For now this can be managed by only running API key tasks within one data center; in the future more changes could be added to enforce this.How to Test and Verify
Risk
Risk is relatively low. The format of the data actually stored in the authentication tables
__auth:keys
and__auth:internal_ids
is unchanged, so there shouldn't be a migration issue. The biggest risk is regression, that a change in the API key manager breaks permission checks.Level
Medium
Required Testing
Regression
Code Review Checklist
Tests are included. If not, make sure you leave us a line or two for the reason.
Pulled down the PR and performed verification of at least being able to
build and run.
Well documented, including updates to any necessary markdown files. When
we inevitably come back to this code it will only take hours to figure out, not
days.
Consistent/Clear/Thoughtful? We are better with this code. We also aren't
a victim of rampaging consistency, and should be using this course of action.
We don't have coding standards out yet for this project, so please make sure to address any feedback regarding STYLE so the codebase remains consistent.
PR has a valid summary, and a good description.