TestAuditLogs to use LogCapturer

This commit is contained in:
Viraj Jasani 2023-03-05 14:31:43 -08:00
parent 201883960b
commit 1483940d3a
No known key found for this signature in database
GPG Key ID: 2DFADE221012D134
1 changed files with 51 additions and 57 deletions

View File

@ -20,12 +20,7 @@ package org.apache.hadoop.hdfs.server.namenode;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -46,12 +41,15 @@ import org.apache.hadoop.hdfs.web.WebHdfsTestUtil;
import org.apache.hadoop.hdfs.web.WebHdfsFileSystem; import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
import org.apache.hadoop.security.AccessControlException; import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.test.GenericTestUtils.LogCapturer;
import org.apache.log4j.Appender; import org.apache.log4j.Appender;
import org.apache.log4j.AsyncAppender; import org.apache.log4j.AsyncAppender;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
@ -66,11 +64,10 @@ public class TestAuditLogs {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(TestAuditLogs.class); private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(TestAuditLogs.class);
private static final File AUDIT_LOG_FILE =
new File(System.getProperty("hadoop.log.dir"), "hdfs-audit.log");
final boolean useAsyncEdits; final boolean useAsyncEdits;
private static LogCapturer auditLogCapture;
@Parameters @Parameters
public static Collection<Object[]> data() { public static Collection<Object[]> data() {
Collection<Object[]> params = new ArrayList<>(); Collection<Object[]> params = new ArrayList<>();
@ -111,9 +108,6 @@ public class TestAuditLogs {
@Before @Before
public void setupCluster() throws Exception { public void setupCluster() throws Exception {
try (PrintWriter writer = new PrintWriter(AUDIT_LOG_FILE)) {
writer.print("");
}
// must configure prior to instantiating the namesystem because it // must configure prior to instantiating the namesystem because it
// will reconfigure the logger if async is enabled // will reconfigure the logger if async is enabled
conf = new HdfsConfiguration(); conf = new HdfsConfiguration();
@ -132,21 +126,17 @@ public class TestAuditLogs {
"org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit"); "org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit");
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Appender> appenders = Collections.list(logger.getAllAppenders()); List<Appender> appenders = Collections.list(logger.getAllAppenders());
assertEquals(1, appenders.size()); // additional appender added by LogCapturer
assertEquals(2, appenders.size());
assertTrue(appenders.get(0) instanceof AsyncAppender); assertTrue(appenders.get(0) instanceof AsyncAppender);
fnames = util.getFileNames(fileName); fnames = util.getFileNames(fileName);
util.waitReplication(fs, fileName, (short)3); util.waitReplication(fs, fileName, (short)3);
userGroupInfo = UserGroupInformation.createUserForTesting(username, groups); userGroupInfo = UserGroupInformation.createUserForTesting(username, groups);
LOG.info("Audit log file: {}, exists: {}, length: {}", AUDIT_LOG_FILE, AUDIT_LOG_FILE.exists(),
AUDIT_LOG_FILE.length());
} }
@After @After
public void teardownCluster() throws Exception { public void teardownCluster() throws Exception {
try (PrintWriter writer = new PrintWriter(AUDIT_LOG_FILE)) {
writer.print("");
}
util.cleanup(fs, "/srcdat"); util.cleanup(fs, "/srcdat");
if (fs != null) { if (fs != null) {
fs.close(); fs.close();
@ -158,6 +148,17 @@ public class TestAuditLogs {
} }
} }
@BeforeClass
public static void beforeClass() {
auditLogCapture = LogCapturer.captureLogs(FSNamesystem.AUDIT_LOG);
}
@AfterClass
public static void afterClass() {
auditLogCapture.stopCapturing();
}
/** test that allowed operation puts proper entry in audit log */ /** test that allowed operation puts proper entry in audit log */
@Test @Test
public void testAuditAllowed() throws Exception { public void testAuditAllowed() throws Exception {
@ -273,54 +274,47 @@ public class TestAuditLogs {
verifySuccessCommandsAuditLogs(1, "foo", "cmd=create"); verifySuccessCommandsAuditLogs(1, "foo", "cmd=create");
} }
private void verifySuccessCommandsAuditLogs(int leastExpected, String file, String cmd) private void verifySuccessCommandsAuditLogs(int leastExpected, String file, String cmd) {
throws IOException { String[] auditLogOutputLines = auditLogCapture.getOutput().split("\\n");
int success = 0;
try (BufferedReader reader = new BufferedReader(new FileReader(AUDIT_LOG_FILE))) { for (String auditLogLine : auditLogOutputLines) {
String line; if (!auditLogLine.contains("allowed=")) {
int success = 0; continue;
while ((line = reader.readLine()) != null) {
assertNotNull(line);
LOG.info("Line: {}", line);
if (SUCCESS_PATTERN.matcher(line).matches() && line.contains(file) && line.contains(
cmd)) {
assertTrue("Expected audit event not found in audit log",
AUDIT_PATTERN.matcher(line).matches());
LOG.info("Successful verification. Log line: {}", line);
success++;
}
} }
if (success < leastExpected) { String line = "allowed=" + auditLogLine.split("allowed=")[1];
throw new AssertionError( LOG.info("Line: {}", line);
"Least expected: " + leastExpected + ". Actual success: " + success); if (SUCCESS_PATTERN.matcher(line).matches() && line.contains(file) && line.contains(cmd)) {
assertTrue("Expected audit event not found in audit log",
AUDIT_PATTERN.matcher(line).matches());
LOG.info("Successful verification. Log line: {}", line);
success++;
} }
} }
if (success < leastExpected) {
throw new AssertionError(
"Least expected: " + leastExpected + ". Actual success: " + success);
}
} }
private void verifyFailedCommandsAuditLogs(int leastExpected, String file, String cmd) private void verifyFailedCommandsAuditLogs(int expected, String file, String cmd) {
throws IOException { String[] auditLogOutputLines = auditLogCapture.getOutput().split("\\n");
int success = 0;
try (BufferedReader reader = new BufferedReader(new FileReader(AUDIT_LOG_FILE))) { for (String auditLogLine : auditLogOutputLines) {
String line; if (!auditLogLine.contains("allowed=")) {
int success = 0; continue;
while ((line = reader.readLine()) != null) {
assertNotNull(line);
LOG.info("Line: {}", line);
if (FAILURE_PATTERN.matcher(line).matches() && line.contains(file) && line.contains(
cmd)) {
assertTrue("Expected audit event not found in audit log",
AUDIT_PATTERN.matcher(line).matches());
LOG.info("Failure verification. Log line: {}", line);
success++;
}
} }
assertEquals("Expected: " + leastExpected + ". Actual failure: " + success, leastExpected, String line = "allowed=" + auditLogLine.split("allowed=")[1];
success); LOG.info("Line: {}", line);
if (success < leastExpected) { if (FAILURE_PATTERN.matcher(line).matches() && line.contains(file) && line.contains(
throw new AssertionError( cmd)) {
"Least expected: " + leastExpected + ". Actual success: " + success); assertTrue("Expected audit event not found in audit log",
AUDIT_PATTERN.matcher(line).matches());
LOG.info("Failure verification. Log line: {}", line);
success++;
} }
} }
assertEquals("Expected: " + expected + ". Actual failure: " + success, expected,
success);
} }
} }