Skip to content

Conversation

@ywangd
Copy link
Member

@ywangd ywangd commented Apr 21, 2022

This PR is a follow-up of #86020 and removes all remaining usages of
Authentication constructor in test code.

Relates: #86020

This PR is a follow-up of elastic#86020 and removes all remaining usages of
Authentication constructor in test code.

Relates: elastic#86020
@ywangd ywangd added >test Issues or PRs that are addressing/adding tests :Security/Security Security issues without another label v8.3.0 labels Apr 21, 2022
@ywangd ywangd requested a review from albertzaharovits April 21, 2022 06:00
@elasticmachine elasticmachine added the Team:Security Meta label for security team label Apr 21, 2022
@elasticmachine
Copy link
Collaborator

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

final int tokenVariant = ESTestCase.randomIntBetween(0, 9);
if (tokenVariant == 0 && user == null && realmRef == null) {
// service account
prepareServiceAccountMetadata();
Copy link
Member Author

Choose a reason for hiding this comment

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

A bug fix for the test helper itself

Comment on lines +2646 to +2649
return randomValueOtherThanMany(
authc -> authc.getAuthenticationType() == AuthenticationType.INTERNAL,
() -> AuthenticationTestHelper.builder().build()
);
Copy link
Member Author

Choose a reason for hiding this comment

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

Internal users are filtered out by default for audit logging.

Comment on lines -888 to -897
final User finalUser;
final boolean isRunAs = randomBoolean();
// If testing run-as, randomize whether the service account actually has the run-as permission
// This makes a difference in the auditing logs (runAsDenied vs accessDenied)
final boolean canRunAs = isRunAs && randomBoolean();
if (isRunAs) {
finalUser = new User(new User(randomAlphaOfLengthBetween(3, 8)), serviceUser);
} else {
finalUser = serviceUser;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Service account cannot run-as. So no point to test.

Comment on lines -1636 to -1638
// Service account run as
final User authenticatedUser2 = new User("elastic/some-service");
Copy link
Member Author

Choose a reason for hiding this comment

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

Service account cannot run-as.

verify(apiKeyService).parseRoleDescriptorsBytes("key-id-3", anotherRoleBytes, RoleReference.ApiKeyRoleType.ASSIGNED);
}

private Authentication createAuthentication() {
Copy link
Member Author

Choose a reason for hiding this comment

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

This method has only 2 usages and are both replaced by inline code.

Comment on lines +345 to +346
// User associated to API key authentication has empty roles
user = stripRoles(user);
Copy link
Member Author

Choose a reason for hiding this comment

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

Another bug for the test helper

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm Okay with the strip but I would've preferred an assert for the empty role name list, wdyt?

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 chose to strip the roles for usability reasons. It is challenging to randomize authentication freely if we assert the role list must be empty and the Authentication happens to be an API key (it can either API key or a token created by an API key or run-as by an API key). Since this is after all test code, I took the easier approach to strip roles.

That said, stripping roles is in fact more akin to what happens in production code:

final User apiKeyUser = new User(principal, Strings.EMPTY_ARRAY, fullName, email, metadata, true);

which essentially also strips the roles.

TimeValue.parseTimeValue(randomTimeValue(), getClass().getSimpleName() + ".expiresIn"),
createAuthentication()
AuthenticationTestHelper.builder()
.realm()
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

assert authResult.isAuthenticated() : "API Key authn result must be successful";
final User apiKeyUser = authResult.getValue();
assert false == apiKeyUser.isRunAs();
assert apiKeyUser.roles().length == 0 : "The user associated to an API key authentication must have no role";
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like something ripe for a refactoring 😁

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed. We can iterate how newApiKeyAuthentication should work in future PRs. The roles are better stripped inside this method for a central control.

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

@ywangd
Copy link
Member Author

ywangd commented Apr 27, 2022

@elasticmachine run elasticsearch-ci/part-2

@ywangd ywangd merged commit 706a2dc into elastic:master Apr 27, 2022
ywangd added a commit to ywangd/elasticsearch that referenced this pull request Apr 27, 2022
This PR removes one constructor from Authentication and change
the visibility of the other one to private. This means Authentication
object must now be created using dedicated convenient methods, e.g.
newRealmAuthentication. This approach helps maintain the internal logic
of Authentication object more easily and correctly. It also allows
further refactoring for Authentication internals easier.

Technically, the constructor with StreamInput argument is still public.
But this one is special enough that we can leave it for now and come
back to it later if necessary.

Relates: elastic#85905
Relates: elastic#86020
Relates: elastic#86054
ywangd added a commit that referenced this pull request May 3, 2022
This PR removes one constructor from Authentication and change
the visibility of the other one to private. This means Authentication
object must now be created using dedicated convenient methods, e.g.
newRealmAuthentication. This approach helps maintain the internal logic
of Authentication object more easily and correctly. It also allows
further refactoring for Authentication internals easier.

Technically, the constructor with StreamInput argument is still public.
But this one is special enough that we can leave it for now and come
back to it later if necessary.

Relates: #85905
Relates: #86020
Relates: #86054
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Security/Security Security issues without another label Team:Security Meta label for security team >test Issues or PRs that are addressing/adding tests v8.3.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants