Skip to content

Commit 55cc115

Browse files
aajisakatasanuma
authored andcommitted
HADOOP-16527. Add a whitelist of endpoints to skip Kerberos authentication (#1336) Contributed by Akira Ajisaka.
1 parent 5d31a4e commit 55cc115

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414
package org.apache.hadoop.security.authentication.server;
1515

16+
import com.google.common.annotations.VisibleForTesting;
1617
import org.apache.hadoop.security.authentication.client.AuthenticationException;
1718
import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
1819
import org.apache.commons.codec.binary.Base64;
@@ -38,6 +39,8 @@
3839
import java.security.Principal;
3940
import java.security.PrivilegedActionException;
4041
import java.security.PrivilegedExceptionAction;
42+
import java.util.Collection;
43+
import java.util.HashSet;
4144
import java.util.Properties;
4245
import java.util.Set;
4346
import java.util.regex.Pattern;
@@ -94,10 +97,18 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
9497
*/
9598
public static final String RULE_MECHANISM = TYPE + ".name.rules.mechanism";
9699

100+
/**
101+
* Constant for the list of endpoints that skips Kerberos authentication.
102+
*/
103+
@VisibleForTesting
104+
static final String ENDPOINT_WHITELIST = TYPE + ".endpoint.whitelist";
105+
private static final Pattern ENDPOINT_PATTERN = Pattern.compile("^/[\\w]+");
106+
97107
private String type;
98108
private String keytab;
99109
private GSSManager gssManager;
100110
private Subject serverSubject = new Subject();
111+
private final Collection<String> whitelist = new HashSet<>();
101112

102113
/**
103114
* Creates a Kerberos SPNEGO authentication handler with the default
@@ -173,6 +184,22 @@ public void init(Properties config) throws ServletException {
173184
if (ruleMechanism != null) {
174185
KerberosName.setRuleMechanism(ruleMechanism);
175186
}
187+
188+
final String whitelistStr = config.getProperty(ENDPOINT_WHITELIST, null);
189+
if (whitelistStr != null) {
190+
final String[] strs = whitelistStr.trim().split("\\s*[,\n]\\s*");
191+
for (String s: strs) {
192+
if (s.isEmpty()) continue;
193+
if (ENDPOINT_PATTERN.matcher(s).matches()) {
194+
whitelist.add(s);
195+
} else {
196+
throw new ServletException(
197+
"The element of the whitelist: " + s + " must start with '/'"
198+
+ " and must not contain special characters afterwards");
199+
}
200+
}
201+
}
202+
176203
try {
177204
gssManager = Subject.doAs(serverSubject,
178205
new PrivilegedExceptionAction<GSSManager>() {
@@ -269,6 +296,16 @@ public boolean managementOperation(AuthenticationToken token,
269296
public AuthenticationToken authenticate(HttpServletRequest request,
270297
final HttpServletResponse response)
271298
throws IOException, AuthenticationException {
299+
300+
// If the request servlet path is in the whitelist,
301+
// skip Kerberos authentication and return anonymous token.
302+
final String path = request.getServletPath();
303+
for(final String endpoint: whitelist) {
304+
if (endpoint.equals(path)) {
305+
return AuthenticationToken.ANONYMOUS;
306+
}
307+
}
308+
272309
AuthenticationToken token = null;
273310
String authorization = request.getHeader(
274311
KerberosAuthenticator.AUTHORIZATION);

hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestKerberosAuthenticationHandler.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public void setup() throws Exception {
8989
// handler
9090
handler = getNewAuthenticationHandler();
9191
Properties props = getDefaultProperties();
92+
// Set whitelist for testing
93+
props.setProperty(KerberosAuthenticationHandler.ENDPOINT_WHITELIST,
94+
"/white,/white2,/white3");
9295
try {
9396
handler.init(props);
9497
} catch (Exception ex) {
@@ -371,6 +374,27 @@ public void testRequestWithInvalidKerberosAuthorization() {
371374
}
372375
}
373376

377+
@Test
378+
public void testRequestToWhitelist() throws Exception {
379+
final String token = new Base64(0).encodeToString(new byte[]{0, 1, 2});
380+
final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
381+
final HttpServletResponse response =
382+
Mockito.mock(HttpServletResponse.class);
383+
Mockito.when(request.getHeader(KerberosAuthenticator.AUTHORIZATION))
384+
.thenReturn(KerberosAuthenticator.NEGOTIATE + token);
385+
Mockito.when(request.getServletPath()).thenReturn("/white");
386+
handler.authenticate(request, response);
387+
Mockito.when(request.getServletPath()).thenReturn("/white4");
388+
try {
389+
handler.authenticate(request, response);
390+
Assert.fail();
391+
} catch (AuthenticationException ex) {
392+
// Expected
393+
} catch (Exception ex) {
394+
Assert.fail();
395+
}
396+
}
397+
374398
@After
375399
public void tearDown() throws Exception {
376400
if (handler != null) {

hadoop-common-project/hadoop-common/src/main/resources/core-default.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,6 +2495,19 @@
24952495
</description>
24962496
</property>
24972497

2498+
<property>
2499+
<name>hadoop.http.authentication.kerberos.endpoint.whitelist</name>
2500+
<value></value>
2501+
<description>
2502+
The comma-separated list of the endpoints that skips Kerberos
2503+
authentication. The endpoint must start with '/' and must not
2504+
contain special characters afterwards. This parameter is for
2505+
the monitoring tools that do not support Kerberos authentication.
2506+
Administrator must configure this parameter very carefully
2507+
because it allows unauthenticated access to the daemons.
2508+
</description>
2509+
</property>
2510+
24982511
<!-- HTTP CORS support -->
24992512
<property>
25002513
<name>hadoop.http.cross-origin.enabled</name>

0 commit comments

Comments
 (0)