Skip to content
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

Respect runas realm for ApiKey security operations #52178

Merged
merged 12 commits into from
Feb 27, 2020

Conversation

ywangd
Copy link
Member

@ywangd ywangd commented Feb 11, 2020

When user A run as user B and perform any API key related operations,
user B's realm should always be used to associate with the API key.
Currently user A's realm is used when getting or invalidating API keys
and owner=true. The PR is to fix this bug.

resolves: #51975

@ywangd ywangd added >bug :Security/Authentication Logging in, Usernames/passwords, Realms (Native/LDAP/AD/SAML/PKI/etc) v8.0.0 v7.7.0 labels Feb 11, 2020
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-security (:Security/Authentication)

@ywangd
Copy link
Member Author

ywangd commented Feb 11, 2020

Does this change need to be documented somewhere similar to what we do for breaking changes?

@ywangd ywangd added the WIP label Feb 11, 2020
@tvernum
Copy link
Contributor

tvernum commented Feb 11, 2020

This looks good to me, but per your comment on the issue, it looks like there's additional changes needed.

Also, given we consider this a bug, I'd like a test for the actual bug. The fact that you can make the change and not need to fix any tests in the API permissions area, shows that we've got a testing gap there.

I think we want to duplicate ApiKeyIntegTests.testGetApiKeysOwnedByCurrentAuthenticatedUser and ApiKeyIntegTests.testInvalidateApiKeysOwnedByCurrentAuthenticatedUser with a run-as user. You'll need to do some refactoring on createApiKeys to support a run-as user there too, but I think it's all obvious enough.

@ywangd
Copy link
Member Author

ywangd commented Feb 12, 2020

Added tests for both get api key and invalidate api key with runas user. Thanks

@ywangd ywangd removed the WIP label Feb 12, 2020
Copy link
Contributor

@albertzaharovits albertzaharovits left a comment

Choose a reason for hiding this comment

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

The overall layout is correct, but there is a small inverted logic of authenticated - lookup that is wrong.

"es-security-runas-user", userWithManageOwnApiKeyRole));

PlainActionFuture<GetApiKeyResponse> listener = new PlainActionFuture<>();
client.execute(GetApiKeyAction.INSTANCE, GetApiKeyRequest.forOwnedApiKeys(), listener);
Copy link
Contributor

Choose a reason for hiding this comment

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

add a test when the owned flag is not set, but the username and realm are.

Copy link
Member Author

Choose a reason for hiding this comment

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

I was meant do test without the "owner" flag since the updated logic won't get executed with its presense. Somehow I ended up forgetting it. Will update. Thanks

Copy link
Member Author

Choose a reason for hiding this comment

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

Add tests for get and invalidate API key without "owner=true"

"es-security-runas-user", userWithManageOwnApiKeyRole));

PlainActionFuture<InvalidateApiKeyResponse> listener = new PlainActionFuture<>();
client.execute(InvalidateApiKeyAction.INSTANCE, InvalidateApiKeyRequest.forOwnedApiKeys(), listener);
Copy link
Contributor

Choose a reason for hiding this comment

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

same as above, we should also test without the owner flag toggled but with the concrete username and realm set.

I would also add a negative test, but this is usually better to do in unit tests, but I sometimes sneak in a negative test in integ tests as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added negative tests for calling get and invalidate API key with mismatching username and/or realm name.

ywangd and others added 3 commits February 13, 2020 21:25
…security/authz/privilege/ManageOwnApiKeyClusterPrivilegeTests.java

Co-Authored-By: Albert Zaharovits <albert.zaharovits@gmail.com>
Comment on lines +832 to +844
private void createUserWithRunAsRole() throws ExecutionException, InterruptedException {
final PutUserRequest putUserRequest = new PutUserRequest();
putUserRequest.username("user_with_run_as_role");
putUserRequest.roles("run_as_role");
putUserRequest.passwordHash(SecuritySettingsSource.TEST_PASSWORD_HASHED.toCharArray());
PlainActionFuture<PutUserResponse> listener = new PlainActionFuture<>();
final Client client = client().filterWithHeader(Map.of("Authorization",
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_SUPERUSER,
SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING)));
client.execute(PutUserAction.INSTANCE, putUserRequest, listener);
final PutUserResponse putUserResponse = listener.get();
assertTrue(putUserResponse.created());
}
Copy link
Member Author

Choose a reason for hiding this comment

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

In order to have negative tests for realm name mismatch, user_with_run_as_role needs to be created in a different realm other than file (which is handled by configureUsers()). This new helper method creates the user in the native realm.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add that explanation to the code?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added

@ywangd
Copy link
Member Author

ywangd commented Feb 13, 2020

There were some sloppiness in the last change. Thanks @albertzaharovits for catching them. It is now updated accordingly. Thanks!

Copy link
Contributor

@albertzaharovits albertzaharovits left a comment

Choose a reason for hiding this comment

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

LGTM 👍

int noOfApiKeys, TimeValue expiration, String... clusterPrivileges) {
final Map<String, String> headers = Map.of("Authorization",
UsernamePasswordToken.basicAuthHeaderValue(runAsUser, SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING),
"es-security-runas-user", user);
Copy link
Contributor

Choose a reason for hiding this comment

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

These seem backwards to me. You authenticate as runAsUser but run-as user.
I assume the parameters are just strangely named, but it probably makes sense to have authenticatingUser and owningUser or something like that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point. It does read awkward. Updated.

Comment on lines +832 to +844
private void createUserWithRunAsRole() throws ExecutionException, InterruptedException {
final PutUserRequest putUserRequest = new PutUserRequest();
putUserRequest.username("user_with_run_as_role");
putUserRequest.roles("run_as_role");
putUserRequest.passwordHash(SecuritySettingsSource.TEST_PASSWORD_HASHED.toCharArray());
PlainActionFuture<PutUserResponse> listener = new PlainActionFuture<>();
final Client client = client().filterWithHeader(Map.of("Authorization",
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_SUPERUSER,
SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING)));
client.execute(PutUserAction.INSTANCE, putUserRequest, listener);
final PutUserResponse putUserResponse = listener.get();
assertTrue(putUserResponse.created());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add that explanation to the code?

@ywangd ywangd requested a review from tvernum February 21, 2020 02:16
Copy link
Contributor

@tvernum tvernum left a comment

Choose a reason for hiding this comment

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

LGTM

@ywangd ywangd merged commit d02e1e3 into elastic:master Feb 27, 2020
ywangd added a commit to ywangd/elasticsearch that referenced this pull request Feb 27, 2020
When user A runs as user B and performs any API key related operations,
user B's realm should always be used to associate with the API key.
Currently user A's realm is used when getting or invalidating API keys
and owner=true. The PR is to fix this bug.

resolves: elastic#51975
ywangd added a commit that referenced this pull request Feb 27, 2020
When user A runs as user B and performs any API key related operations,
user B's realm should always be used to associate with the API key.
Currently user A's realm is used when getting or invalidating API keys
and owner=true. The PR is to fix this bug.

resolves: #51975
@ywangd
Copy link
Member Author

ywangd commented Feb 27, 2020

ywangd added a commit that referenced this pull request Mar 26, 2020
Avoid string comparison when we can use safter enums. 
This refactor is a follow up for #52178.

Resolves: #52511
ywangd added a commit to ywangd/elasticsearch that referenced this pull request Mar 26, 2020
Avoid string comparison when we can use safter enums.
This refactor is a follow up for elastic#52178.

Resolves: elastic#52511
ywangd added a commit that referenced this pull request Mar 26, 2020
Avoid string comparison when we can use safer enums.
This refactor is a follow up for #52178.

Resolves: #52511
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Security/Authentication Logging in, Usernames/passwords, Realms (Native/LDAP/AD/SAML/PKI/etc) v7.7.0 v8.0.0-alpha1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Respect runas auth realm for all API key security operations
5 participants