Skip to content

Commit 14a9c22

Browse files
committed
Avoid NPE when checking for CCR index privileges (#44397)
This commit avoids an NPE when checking for privileges to follow indices. The problem here is that in some cases we might not be able to read the authentication info from the thread context. In that case, a null user would be returned and we were not guarding against this.
1 parent 58c53b4 commit 14a9c22

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/CcrLicenseChecker.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
4848
import org.elasticsearch.xpack.core.security.authz.permission.ResourcePrivileges;
4949
import org.elasticsearch.xpack.core.security.support.Exceptions;
50+
import org.elasticsearch.xpack.core.security.user.User;
5051

5152
import java.util.Arrays;
5253
import java.util.Collections;
@@ -63,7 +64,7 @@
6364
/**
6465
* Encapsulates licensing checking for CCR.
6566
*/
66-
public final class CcrLicenseChecker {
67+
public class CcrLicenseChecker {
6768

6869
private final BooleanSupplier isCcrAllowed;
6970
private final BooleanSupplier isAuthAllowed;
@@ -313,9 +314,12 @@ public void hasPrivilegesToFollowIndices(final Client remoteClient, final String
313314
return;
314315
}
315316

316-
ThreadContext threadContext = remoteClient.threadPool().getThreadContext();
317-
SecurityContext securityContext = new SecurityContext(Settings.EMPTY, threadContext);
318-
String username = securityContext.getUser().principal();
317+
final User user = getUser(remoteClient);
318+
if (user == null) {
319+
handler.accept(new IllegalStateException("missing or unable to read authentication info on request"));
320+
return;
321+
}
322+
String username = user.principal();
319323

320324
RoleDescriptor.IndicesPrivileges privileges = RoleDescriptor.IndicesPrivileges.builder()
321325
.indices(indices)
@@ -350,6 +354,12 @@ public void hasPrivilegesToFollowIndices(final Client remoteClient, final String
350354
remoteClient.execute(HasPrivilegesAction.INSTANCE, request, ActionListener.wrap(responseHandler, handler));
351355
}
352356

357+
User getUser(final Client remoteClient) {
358+
final ThreadContext threadContext = remoteClient.threadPool().getThreadContext();
359+
final SecurityContext securityContext = new SecurityContext(Settings.EMPTY, threadContext);
360+
return securityContext.getUser();
361+
}
362+
353363
public static Client wrapClient(Client client, Map<String, String> headers) {
354364
if (headers.isEmpty()) {
355365
return client;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.ccr;
8+
9+
import org.elasticsearch.client.Client;
10+
import org.elasticsearch.test.ESTestCase;
11+
import org.elasticsearch.xpack.core.security.user.User;
12+
13+
import java.util.concurrent.atomic.AtomicBoolean;
14+
15+
import static org.hamcrest.Matchers.containsString;
16+
import static org.hamcrest.Matchers.hasToString;
17+
import static org.hamcrest.Matchers.instanceOf;
18+
import static org.mockito.Mockito.mock;
19+
20+
public class CcrLicenseCheckerTests extends ESTestCase {
21+
22+
public void testNoAuthenticationInfo() {
23+
final boolean isCcrAllowed = randomBoolean();
24+
final CcrLicenseChecker checker = new CcrLicenseChecker(() -> isCcrAllowed, () -> true) {
25+
26+
@Override
27+
User getUser(final Client remoteClient) {
28+
return null;
29+
}
30+
31+
};
32+
final AtomicBoolean invoked = new AtomicBoolean();
33+
checker.hasPrivilegesToFollowIndices(
34+
mock(Client.class),
35+
new String[]{randomAlphaOfLength(8)},
36+
e -> {
37+
invoked.set(true);
38+
assertThat(e, instanceOf(IllegalStateException.class));
39+
assertThat(e, hasToString(containsString("missing or unable to read authentication info on request")));
40+
});
41+
assertTrue(invoked.get());
42+
}
43+
44+
}

0 commit comments

Comments
 (0)