Skip to content

Commit 55451a8

Browse files
committed
Add test and validation of error response
1 parent 98cf628 commit 55451a8

File tree

2 files changed

+59
-16
lines changed

2 files changed

+59
-16
lines changed

hbase-http/src/main/java/org/apache/hadoop/hbase/http/log/LogLevel.java

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
import java.io.IOException;
2323
import java.io.InputStreamReader;
2424
import java.io.PrintWriter;
25+
import java.net.HttpURLConnection;
2526
import java.net.URL;
26-
import java.net.URLConnection;
2727
import java.nio.charset.StandardCharsets;
2828
import java.util.Objects;
2929
import java.util.regex.Pattern;
@@ -41,6 +41,7 @@
4141
import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
4242
import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
4343
import org.apache.hadoop.security.ssl.SSLFactory;
44+
import org.apache.hadoop.util.HttpExceptionUtils;
4445
import org.apache.hadoop.util.ServletUtil;
4546
import org.apache.hadoop.util.Tool;
4647
import org.apache.yetus.audience.InterfaceAudience;
@@ -59,6 +60,8 @@ public final class LogLevel {
5960
public static final String PROTOCOL_HTTP = "http";
6061
public static final String PROTOCOL_HTTPS = "https";
6162

63+
public static final String READONLY_LOGGERS_CONF_KEY = "hbase.ui.logLevels.readonly.loggers";
64+
6265
/**
6366
* A command line implementation
6467
*/
@@ -247,11 +250,11 @@ private void doSetLevel() throws Exception {
247250
* @return a connected connection
248251
* @throws Exception if it can not establish a connection.
249252
*/
250-
private URLConnection connect(URL url) throws Exception {
253+
private HttpURLConnection connect(URL url) throws Exception {
251254
AuthenticatedURL.Token token = new AuthenticatedURL.Token();
252255
AuthenticatedURL aUrl;
253256
SSLFactory clientSslFactory;
254-
URLConnection connection;
257+
HttpURLConnection connection;
255258
// If https is chosen, configures SSL client.
256259
if (PROTOCOL_HTTPS.equals(url.getProtocol())) {
257260
clientSslFactory = new SSLFactory(SSLFactory.Mode.CLIENT, this.getConf());
@@ -280,7 +283,9 @@ private void process(String urlString) throws Exception {
280283
URL url = new URL(urlString);
281284
System.out.println("Connecting to " + url);
282285

283-
URLConnection connection = connect(url);
286+
HttpURLConnection connection = connect(url);
287+
288+
HttpExceptionUtils.validateResponse(connection, 200);
284289

285290
// read from the servlet
286291

@@ -317,8 +322,10 @@ public void doGet(HttpServletRequest request, HttpServletResponse response)
317322
Configuration conf = (Configuration) getServletContext().getAttribute(
318323
HttpServer.CONF_CONTEXT_ATTRIBUTE);
319324
if (conf.getBoolean("hbase.master.ui.readonly", false)) {
320-
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Modification of HBase via"
321-
+ " the UI is disallowed in configuration.");
325+
sendError(
326+
response,
327+
HttpServletResponse.SC_FORBIDDEN,
328+
"Modification of HBase via the UI is disallowed in configuration.");
322329
return;
323330
}
324331
response.setContentType("text/html");
@@ -336,7 +343,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response)
336343
String logName = ServletUtil.getParameter(request, "log");
337344
String level = ServletUtil.getParameter(request, "level");
338345

339-
String[] readOnlyLogLevels = conf.getStrings("hbase.ui.logLevels.readonly.loggers");
346+
String[] readOnlyLogLevels = conf.getStrings(READONLY_LOGGERS_CONF_KEY);
340347

341348
if (logName != null) {
342349
out.println("<p>Results:</p>");
@@ -348,8 +355,10 @@ public void doGet(HttpServletRequest request, HttpServletResponse response)
348355
+ "Log Class: <b>" + log.getClass().getName() +"</b><br />");
349356
if (level != null) {
350357
if (!isLogLevelChangeAllowed(logName, readOnlyLogLevels)) {
351-
response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED,
352-
"Modification of logger " + logName + " not allowed.");
358+
sendError(
359+
response,
360+
HttpServletResponse.SC_PRECONDITION_FAILED,
361+
"Modification of logger " + logName + " is disallowed in configuration.");
353362
return;
354363
}
355364

@@ -373,13 +382,19 @@ private boolean isLogLevelChangeAllowed(String logger, String[] readOnlyLogLevel
373382
return true;
374383
}
375384
for (String readOnlyLogLevel : readOnlyLogLevels) {
376-
if (readOnlyLogLevel.startsWith(logger)) {
385+
if (logger.startsWith(readOnlyLogLevel)) {
377386
return false;
378387
}
379388
}
380389
return true;
381390
}
382391

392+
private void sendError(HttpServletResponse response, int code, String message)
393+
throws IOException {
394+
response.setStatus(code, message);
395+
response.sendError(code, message);
396+
}
397+
383398
static final String FORMS = "<div class='container-fluid content'>\n"
384399
+ "<div class='row inner_header'>\n" + "<div class='page-header'>\n"
385400
+ "<h1>Get/Set Log Level</h1>\n" + "</div>\n" + "</div>\n" + "Actions:" + "<p>"

hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
import static org.junit.Assert.fail;
2525

2626
import java.io.File;
27+
import java.io.IOException;
2728
import java.net.BindException;
2829
import java.net.SocketException;
2930
import java.net.URI;
3031
import java.security.PrivilegedExceptionAction;
3132
import java.util.Properties;
3233
import javax.net.ssl.SSLException;
34+
import javax.servlet.http.HttpServletResponse;
3335
import org.apache.commons.io.FileUtils;
3436
import org.apache.hadoop.HadoopIllegalArgumentException;
3537
import org.apache.hadoop.conf.Configuration;
@@ -73,6 +75,8 @@ public class TestLogLevel {
7375
private static Configuration clientConf;
7476
private static Configuration sslConf;
7577
private static final String logName = TestLogLevel.class.getName();
78+
private static final String protectedPrefix = "protected";
79+
private static final String protectedLogName = protectedPrefix + "." + logName;
7680
private static final org.apache.logging.log4j.Logger log =
7781
org.apache.logging.log4j.LogManager.getLogger(logName);
7882
private final static String PRINCIPAL = "loglevel.principal";
@@ -89,6 +93,7 @@ public class TestLogLevel {
8993
@BeforeClass
9094
public static void setUp() throws Exception {
9195
serverConf = new Configuration();
96+
serverConf.setStrings(LogLevel.READONLY_LOGGERS_CONF_KEY, protectedPrefix);
9297
HTU = new HBaseCommonTestingUtil(serverConf);
9398

9499
File keystoreDir = new File(HTU.getDataTestDir("keystore").toString());
@@ -259,9 +264,17 @@ private HttpServer createServer(String protocol, boolean isSpnego) throws Except
259264
private void testDynamicLogLevel(final String bindProtocol, final String connectProtocol,
260265
final boolean isSpnego) throws Exception {
261266
testDynamicLogLevel(bindProtocol, connectProtocol, isSpnego,
267+
logName,
262268
org.apache.logging.log4j.Level.DEBUG.toString());
263269
}
264270

271+
private void testDynamicLogLevel(final String bindProtocol, final String connectProtocol,
272+
final boolean isSpnego, final String newLevel) throws Exception {
273+
testDynamicLogLevel(bindProtocol, connectProtocol, isSpnego,
274+
logName,
275+
newLevel);
276+
}
277+
265278
/**
266279
* Run both client and server using the given protocol.
267280
* @param bindProtocol specify either http or https for server
@@ -270,13 +283,14 @@ private void testDynamicLogLevel(final String bindProtocol, final String connect
270283
* @throws Exception if client can't accesss server.
271284
*/
272285
private void testDynamicLogLevel(final String bindProtocol, final String connectProtocol,
273-
final boolean isSpnego, final String newLevel) throws Exception {
286+
final boolean isSpnego, final String loggerName, final String newLevel) throws Exception {
274287
if (!LogLevel.isValidProtocol(bindProtocol)) {
275288
throw new Exception("Invalid server protocol " + bindProtocol);
276289
}
277290
if (!LogLevel.isValidProtocol(connectProtocol)) {
278291
throw new Exception("Invalid client protocol " + connectProtocol);
279292
}
293+
org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(loggerName);
280294
org.apache.logging.log4j.Level oldLevel = log.getLevel();
281295
assertNotEquals("Get default Log Level which shouldn't be ERROR.",
282296
org.apache.logging.log4j.Level.ERROR, oldLevel);
@@ -305,8 +319,8 @@ private void testDynamicLogLevel(final String bindProtocol, final String connect
305319
try {
306320
clientUGI.doAs((PrivilegedExceptionAction<Void>) () -> {
307321
// client command line
308-
getLevel(connectProtocol, authority);
309-
setLevel(connectProtocol, authority, newLevel);
322+
getLevel(connectProtocol, authority, loggerName);
323+
setLevel(connectProtocol, authority, loggerName, newLevel);
310324
return null;
311325
});
312326
} finally {
@@ -324,7 +338,7 @@ private void testDynamicLogLevel(final String bindProtocol, final String connect
324338
* @param authority daemon's web UI address
325339
* @throws Exception if unable to connect
326340
*/
327-
private void getLevel(String protocol, String authority) throws Exception {
341+
private void getLevel(String protocol, String authority, String logName) throws Exception {
328342
String[] getLevelArgs = { "-getlevel", authority, logName, "-protocol", protocol };
329343
CLI cli = new CLI(protocol.equalsIgnoreCase("https") ? sslConf : clientConf);
330344
cli.run(getLevelArgs);
@@ -336,13 +350,27 @@ private void getLevel(String protocol, String authority) throws Exception {
336350
* @param authority daemon's web UI address
337351
* @throws Exception if unable to run or log level does not change as expected
338352
*/
339-
private void setLevel(String protocol, String authority, String newLevel) throws Exception {
353+
private void setLevel(String protocol, String authority, String logName, String newLevel) throws Exception {
340354
String[] setLevelArgs = { "-setlevel", authority, logName, newLevel, "-protocol", protocol };
341355
CLI cli = new CLI(protocol.equalsIgnoreCase("https") ? sslConf : clientConf);
342356
cli.run(setLevelArgs);
343357

358+
org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getLogger(logName);
359+
344360
assertEquals("new level not equal to expected: ", newLevel.toUpperCase(),
345-
log.getLevel().toString());
361+
logger.getLevel().toString());
362+
}
363+
364+
@Test
365+
public void testSettingProtectedLogLevel() throws Exception {
366+
try {
367+
testDynamicLogLevel(LogLevel.PROTOCOL_HTTP, LogLevel.PROTOCOL_HTTP, true, protectedLogName,
368+
"DEBUG");
369+
fail("Expected IO exception due to protected logger");
370+
} catch (IOException e) {
371+
assertTrue(e.getMessage().contains("" + HttpServletResponse.SC_PRECONDITION_FAILED));
372+
assertTrue(e.getMessage().contains("Modification of logger " + protectedLogName + " is disallowed in configuration."));
373+
}
346374
}
347375

348376
/**

0 commit comments

Comments
 (0)