YARN-4163: Audit getQueueInfo and getApplications calls. Contributed by Chang Li.

This commit is contained in:
Eric Payne 2017-10-23 17:37:50 -05:00
parent 5ee67c1202
commit 6b0dba318d
3 changed files with 215 additions and 18 deletions

View File

@ -140,6 +140,7 @@
import org.apache.hadoop.yarn.ipc.YarnRPC; import org.apache.hadoop.yarn.ipc.YarnRPC;
import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier; import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants; import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants;
import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.Keys;
import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager;
import org.apache.hadoop.yarn.server.resourcemanager.reservation.Plan; import org.apache.hadoop.yarn.server.resourcemanager.reservation.Plan;
import org.apache.hadoop.yarn.server.resourcemanager.reservation.ReservationAllocation; import org.apache.hadoop.yarn.server.resourcemanager.reservation.ReservationAllocation;
@ -930,6 +931,8 @@ public void remove() {
callerUGI.getUserName(), allowAccess)); callerUGI.getUserName(), allowAccess));
} }
RMAuditLogger.logSuccess(callerUGI.getUserName(),
AuditConstants.GET_APPLICATIONS_REQUEST, "ClientRMService");
GetApplicationsResponse response = GetApplicationsResponse response =
recordFactory.newRecordInstance(GetApplicationsResponse.class); recordFactory.newRecordInstance(GetApplicationsResponse.class);
response.setApplicationList(reports); response.setApplicationList(reports);
@ -980,6 +983,13 @@ public GetQueueInfoResponse getQueueInfo(GetQueueInfoRequest request)
GetQueueInfoResponse response = GetQueueInfoResponse response =
recordFactory.newRecordInstance(GetQueueInfoResponse.class); recordFactory.newRecordInstance(GetQueueInfoResponse.class);
RMAuditLogger.ArgsBuilder arguments = new RMAuditLogger.ArgsBuilder()
.append(Keys.QUEUENAME, request.getQueueName())
.append(Keys.INCLUDEAPPS,
String.valueOf(request.getIncludeApplications()))
.append(Keys.INCLUDECHILDQUEUES,
String.valueOf(request.getIncludeChildQueues()))
.append(Keys.RECURSIVE, String.valueOf(request.getRecursive()));
try { try {
QueueInfo queueInfo = QueueInfo queueInfo =
scheduler.getQueueInfo(request.getQueueName(), scheduler.getQueueInfo(request.getQueueName(),
@ -1006,8 +1016,14 @@ public GetQueueInfoResponse getQueueInfo(GetQueueInfoRequest request)
} }
queueInfo.setApplications(appReports); queueInfo.setApplications(appReports);
response.setQueueInfo(queueInfo); response.setQueueInfo(queueInfo);
RMAuditLogger.logSuccess(callerUGI.getUserName(),
AuditConstants.GET_QUEUE_INFO_REQUEST,
"ClientRMService", arguments);
} catch (IOException ioe) { } catch (IOException ioe) {
LOG.info("Failed to getQueueInfo for " + request.getQueueName(), ioe); LOG.info("Failed to getQueueInfo for " + request.getQueueName(), ioe);
RMAuditLogger.logFailure(callerUGI.getUserName(),
AuditConstants.GET_QUEUE_INFO_REQUEST, "UNKNOWN", "ClientRMService",
ioe.getMessage(), arguments);
} }
return response; return response;

View File

@ -38,7 +38,8 @@ public class RMAuditLogger {
static enum Keys {USER, OPERATION, TARGET, RESULT, IP, PERMISSIONS, static enum Keys {USER, OPERATION, TARGET, RESULT, IP, PERMISSIONS,
DESCRIPTION, APPID, APPATTEMPTID, CONTAINERID, DESCRIPTION, APPID, APPATTEMPTID, CONTAINERID,
CALLERCONTEXT, CALLERSIGNATURE} CALLERCONTEXT, CALLERSIGNATURE, QUEUENAME,
INCLUDEAPPS, INCLUDECHILDQUEUES, RECURSIVE}
public static class AuditConstants { public static class AuditConstants {
static final String SUCCESS = "SUCCESS"; static final String SUCCESS = "SUCCESS";
@ -53,6 +54,10 @@ public static class AuditConstants {
public static final String GET_APP_STATE = "Get Application State"; public static final String GET_APP_STATE = "Get Application State";
public static final String GET_APP_PRIORITY = "Get Application Priority"; public static final String GET_APP_PRIORITY = "Get Application Priority";
public static final String GET_APP_QUEUE = "Get Application Queue"; public static final String GET_APP_QUEUE = "Get Application Queue";
public static final String GET_QUEUE_INFO_REQUEST =
"Get Queue Info Request";
public static final String GET_APPLICATIONS_REQUEST =
"Get Applications Request";
public static final String FINISH_SUCCESS_APP = "Application Finished - Succeeded"; public static final String FINISH_SUCCESS_APP = "Application Finished - Succeeded";
public static final String FINISH_FAILED_APP = "Application Finished - Failed"; public static final String FINISH_FAILED_APP = "Application Finished - Failed";
public static final String FINISH_KILLED_APP = "Application Finished - Killed"; public static final String FINISH_KILLED_APP = "Application Finished - Killed";
@ -88,12 +93,11 @@ static String createSuccessLog(String user, String operation, String target,
} }
/** /**
* A helper api for creating an audit log for a successful event. * A helper function for creating the common portion of a successful
* log message.
*/ */
static String createSuccessLog(String user, String operation, String target, private static StringBuilder createStringBuilderForSuccessEvent(String user,
ApplicationId appId, ApplicationAttemptId attemptId, String operation, String target, InetAddress ip) {
ContainerId containerId, CallerContext callerContext,
InetAddress ip) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
start(Keys.USER, user, b); start(Keys.USER, user, b);
if (ip != null) { if (ip != null) {
@ -102,6 +106,18 @@ static String createSuccessLog(String user, String operation, String target,
add(Keys.OPERATION, operation, b); add(Keys.OPERATION, operation, b);
add(Keys.TARGET, target ,b); add(Keys.TARGET, target ,b);
add(Keys.RESULT, AuditConstants.SUCCESS, b); add(Keys.RESULT, AuditConstants.SUCCESS, b);
return b;
}
/**
* A helper api for creating an audit log for a successful event.
*/
static String createSuccessLog(String user, String operation, String target,
ApplicationId appId, ApplicationAttemptId attemptId,
ContainerId containerId, CallerContext callerContext,
InetAddress ip) {
StringBuilder b =
createStringBuilderForSuccessEvent(user, operation, target, ip);
if (appId != null) { if (appId != null) {
add(Keys.APPID, appId.toString(), b); add(Keys.APPID, appId.toString(), b);
} }
@ -138,6 +154,20 @@ private static void appendCallerContext(StringBuilder sb, CallerContext callerCo
} }
} }
/**
* A general helper api for creating an audit log for a successful event.
*/
@SuppressWarnings("rawtypes")
static String createSuccessLog(String user, String operation, String target,
InetAddress ip, ArgsBuilder args) {
StringBuilder b =
createStringBuilderForSuccessEvent(user, operation, target, ip);
if(args != null) {
add(args, b);
}
return b.toString();
}
/** /**
* Create a readable and parseable audit log string for a successful event. * Create a readable and parseable audit log string for a successful event.
* *
@ -159,12 +189,53 @@ public static void logSuccess(String user, String operation, String target,
} }
} }
/**
* Create a general readable and parseable audit log string for a successful
* event.
*
* @param user User who made the service request to the ResourceManager.
* @param operation Operation requested by the user.
* @param target The target on which the operation is being performed.
* @param args The ArgsBuilder arguments for the operation request.
*
* <br><br>
* Note that the {@link RMAuditLogger} uses tabs ('\t') as a key-val delimiter
* and hence the value fields should not contains tabs ('\t').
* <br>
* This method will attempt to retrieve the remote IP
*/
public static void logSuccess(String user, String operation, String target,
ArgsBuilder args) {
logSuccess(user, operation, target, Server.getRemoteIp(), args);
}
/**
* Create a general readable and parseable audit log string for a successful
* event.
*
* @param user User who made the service request to the ResourceManager.
* @param operation Operation requested by the user.
* @param target The target on which the operation is being performed.
* @param ip The ip address of the caller.
* @param args The ArgsBuilder arguments for the operation request.
*
* <br><br>
* Note that the {@link RMAuditLogger} uses tabs ('\t') as a key-val delimiter
* and hence the value fields should not contains tabs ('\t').
*/
public static void logSuccess(String user, String operation, String target,
InetAddress ip, ArgsBuilder args) {
if (LOG.isInfoEnabled()) {
LOG.info(createSuccessLog(user, operation, target, ip, args));
}
}
/** /**
* Create a readable and parseable audit log string for a successful event. * Create a readable and parseable audit log string for a successful event.
* *
* @param user User who made the service request to the ResourceManager. * @param user User who made the service request to the ResourceManager.
* @param operation Operation requested by the user. * @param operation Operation requested by the user.
* @param target The target on which the operation is being performed. * @param target The target on which the operation is being performed.
* @param appId Application Id in which operation was performed. * @param appId Application Id in which operation was performed.
* @param attemptId Application Attempt Id in which operation was performed. * @param attemptId Application Attempt Id in which operation was performed.
* *
@ -252,10 +323,8 @@ public static void logSuccess(String user, String operation, String target) {
} }
} }
static String createFailureLog(String user, String operation, String perm, private static StringBuilder createStringBuilderForFailureLog(String user,
String target, String description, ApplicationId appId, String operation, String target, String description, String perm) {
ApplicationAttemptId attemptId, ContainerId containerId,
CallerContext callerContext) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
start(Keys.USER, user, b); start(Keys.USER, user, b);
addRemoteIP(b); addRemoteIP(b);
@ -264,6 +333,18 @@ static String createFailureLog(String user, String operation, String perm,
add(Keys.RESULT, AuditConstants.FAILURE, b); add(Keys.RESULT, AuditConstants.FAILURE, b);
add(Keys.DESCRIPTION, description, b); add(Keys.DESCRIPTION, description, b);
add(Keys.PERMISSIONS, perm, b); add(Keys.PERMISSIONS, perm, b);
return b;
}
/**
* A helper api for creating an audit log for a failure event.
*/
static String createFailureLog(String user, String operation, String perm,
String target, String description, ApplicationId appId,
ApplicationAttemptId attemptId, ContainerId containerId,
CallerContext callerContext) {
StringBuilder b = createStringBuilderForFailureLog(user,
operation, target, description, perm);
if (appId != null) { if (appId != null) {
add(Keys.APPID, appId.toString(), b); add(Keys.APPID, appId.toString(), b);
} }
@ -287,6 +368,20 @@ static String createFailureLog(String user, String operation, String perm,
attemptId, containerId, null); attemptId, containerId, null);
} }
/**
* A helper api for creating an audit log for a failure event.
*/
@SuppressWarnings("rawtypes")
static String createFailureLog(String user, String operation, String perm,
String target, String description, ArgsBuilder args) {
StringBuilder b = createStringBuilderForFailureLog(user,
operation, target, description, perm);
if(args != null) {
add(args, b);
}
return b.toString();
}
/** /**
* Create a readable and parseable audit log string for a failed event. * Create a readable and parseable audit log string for a failed event.
* *
@ -391,7 +486,29 @@ public static void logFailure(String user, String operation, String perm,
} }
/** /**
* A helper api to add remote IP address * Create a readable and parseable audit log string for a failed event.
*
* @param user User who made the service request.
* @param operation Operation requested by the user.
* @param perm Target permissions.
* @param target The target on which the operation is being performed.
* @param description The failure description
* @param args The arguments for the operation request.
*
* <br><br>
* Note that the {@link RMAuditLogger} uses tabs ('\t') as a key-val delimiter
* and hence the value fields should not contains tabs ('\t').
*/
public static void logFailure(String user, String operation, String perm,
String target, String description, ArgsBuilder args) {
if (LOG.isWarnEnabled()) {
LOG.warn(createFailureLog(user, operation, perm, target, description,
args));
}
}
/**
* A helper api to add remote IP address.
*/ */
static void addRemoteIP(StringBuilder b) { static void addRemoteIP(StringBuilder b) {
InetAddress ip = Server.getRemoteIp(); InetAddress ip = Server.getRemoteIp();
@ -417,4 +534,35 @@ static void add(Keys key, String value, StringBuilder b) {
b.append(AuditConstants.PAIR_SEPARATOR).append(key.name()) b.append(AuditConstants.PAIR_SEPARATOR).append(key.name())
.append(AuditConstants.KEY_VAL_SEPARATOR).append(value); .append(AuditConstants.KEY_VAL_SEPARATOR).append(value);
} }
/**
* Appends the key-val pair to the passed builder in the following format
* <pair-delim>key=value
*/
static void add(ArgsBuilder args, StringBuilder b) {
b.append(AuditConstants.PAIR_SEPARATOR).append(args.getArgs());
}
/**
* Builder to create and pass a list of arbitrary key value pairs for logging.
*/
public static class ArgsBuilder {
private StringBuilder b;
public ArgsBuilder() {
b = new StringBuilder();
}
public ArgsBuilder append(Keys key, String value) {
if (b.length() != 0) {
b.append(AuditConstants.PAIR_SEPARATOR);
}
b.append(key.name()).append(AuditConstants.KEY_VAL_SEPARATOR).append(value);
return this;
}
public StringBuilder getArgs() {
return b;
}
}
} }

View File

@ -59,6 +59,7 @@ public class TestRMAuditLogger {
private static final String TARGET = "tgt"; private static final String TARGET = "tgt";
private static final String PERM = "admin group"; private static final String PERM = "admin group";
private static final String DESC = "description of an audit log"; private static final String DESC = "description of an audit log";
private static final String QUEUE = "root";
private static final ApplicationId APPID = mock(ApplicationId.class); private static final ApplicationId APPID = mock(ApplicationId.class);
private static final ApplicationAttemptId ATTEMPTID = mock(ApplicationAttemptId.class); private static final ApplicationAttemptId ATTEMPTID = mock(ApplicationAttemptId.class);
private static final ContainerId CONTAINERID = mock(ContainerId.class); private static final ContainerId CONTAINERID = mock(ContainerId.class);
@ -119,14 +120,22 @@ private void testSuccessLogFormatHelper(boolean checkIP, ApplicationId appId,
private void testSuccessLogFormatHelper(boolean checkIP, ApplicationId appId, private void testSuccessLogFormatHelper(boolean checkIP, ApplicationId appId,
ApplicationAttemptId attemptId, ContainerId containerId, ApplicationAttemptId attemptId, ContainerId containerId,
CallerContext callerContext, InetAddress remoteIp) { CallerContext callerContext, InetAddress remoteIp) {
testSuccessLogFormatHelper(checkIP, appId, attemptId, containerId,
callerContext, remoteIp, null);
}
private void testSuccessLogFormatHelper(boolean checkIP, ApplicationId appId,
ApplicationAttemptId attemptId, ContainerId containerId,
CallerContext callerContext, InetAddress remoteIp,
RMAuditLogger.ArgsBuilder args) {
String sLog; String sLog;
if (checkIP) { InetAddress tmpIp = checkIP ? remoteIp : null;
sLog = RMAuditLogger.createSuccessLog(USER, OPERATION, TARGET, appId, if (args != null) {
attemptId, containerId, callerContext, remoteIp); sLog = RMAuditLogger.createSuccessLog(USER, OPERATION, TARGET,
tmpIp, args);
} else { } else {
sLog = RMAuditLogger.createSuccessLog(USER, OPERATION, TARGET, appId, sLog = RMAuditLogger.createSuccessLog(USER, OPERATION, TARGET, appId,
attemptId, containerId, callerContext, null); attemptId, containerId, callerContext, tmpIp);
} }
StringBuilder expLog = new StringBuilder(); StringBuilder expLog = new StringBuilder();
expLog.append("USER=test\t"); expLog.append("USER=test\t");
@ -158,6 +167,10 @@ private void testSuccessLogFormatHelper(boolean checkIP, ApplicationId appId,
expLog.append("\tCALLERSIGNATURE=signature"); expLog.append("\tCALLERSIGNATURE=signature");
} }
} }
if (args != null) {
expLog.append("\tQUEUENAME=root");
expLog.append("\tRECURSIVE=true");
}
assertEquals(expLog.toString(), sLog); assertEquals(expLog.toString(), sLog);
} }
@ -234,6 +247,10 @@ private void testSuccessLogFormat(boolean checkIP) {
testSuccessLogFormatHelper(checkIP, APPID, ATTEMPTID, CONTAINERID, testSuccessLogFormatHelper(checkIP, APPID, ATTEMPTID, CONTAINERID,
new CallerContext.Builder(CALLER_CONTEXT).setSignature(CALLER_SIGNATURE) new CallerContext.Builder(CALLER_CONTEXT).setSignature(CALLER_SIGNATURE)
.build()); .build());
RMAuditLogger.ArgsBuilder args = new RMAuditLogger.ArgsBuilder()
.append(Keys.QUEUENAME, QUEUE).append(Keys.RECURSIVE, "true");
testSuccessLogFormatHelper(checkIP, null, null, null, null,
Server.getRemoteIp(), args);
testSuccessLogFormatHelperWithIP(checkIP, APPID, ATTEMPTID, CONTAINERID); testSuccessLogFormatHelperWithIP(checkIP, APPID, ATTEMPTID, CONTAINERID);
testSuccessLogNulls(checkIP); testSuccessLogNulls(checkIP);
} }
@ -249,9 +266,18 @@ private void testFailureLogFormatHelper(boolean checkIP, ApplicationId appId,
private void testFailureLogFormatHelper(boolean checkIP, ApplicationId appId, private void testFailureLogFormatHelper(boolean checkIP, ApplicationId appId,
ApplicationAttemptId attemptId, ContainerId containerId, ApplicationAttemptId attemptId, ContainerId containerId,
CallerContext callerContext) { CallerContext callerContext) {
String fLog = testFailureLogFormatHelper(checkIP, appId, attemptId, containerId,
callerContext, null);
}
private void testFailureLogFormatHelper(boolean checkIP, ApplicationId appId,
ApplicationAttemptId attemptId, ContainerId containerId,
CallerContext callerContext, RMAuditLogger.ArgsBuilder args) {
String fLog = args == null ?
RMAuditLogger.createFailureLog(USER, OPERATION, PERM, TARGET, DESC, RMAuditLogger.createFailureLog(USER, OPERATION, PERM, TARGET, DESC,
appId, attemptId, containerId, callerContext); appId, attemptId, containerId, callerContext) :
RMAuditLogger.createFailureLog(USER, OPERATION, PERM, TARGET, DESC,
args);
StringBuilder expLog = new StringBuilder(); StringBuilder expLog = new StringBuilder();
expLog.append("USER=test\t"); expLog.append("USER=test\t");
if (checkIP) { if (checkIP) {
@ -278,6 +304,10 @@ private void testFailureLogFormatHelper(boolean checkIP, ApplicationId appId,
expLog.append("\tCALLERSIGNATURE=signature"); expLog.append("\tCALLERSIGNATURE=signature");
} }
} }
if (args != null) {
expLog.append("\tQUEUENAME=root");
expLog.append("\tRECURSIVE=true");
}
assertEquals(expLog.toString(), fLog); assertEquals(expLog.toString(), fLog);
} }
@ -304,6 +334,9 @@ private void testFailureLogFormat(boolean checkIP) {
testFailureLogFormatHelper(checkIP, APPID, ATTEMPTID, CONTAINERID, testFailureLogFormatHelper(checkIP, APPID, ATTEMPTID, CONTAINERID,
new CallerContext.Builder(CALLER_CONTEXT).setSignature(CALLER_SIGNATURE) new CallerContext.Builder(CALLER_CONTEXT).setSignature(CALLER_SIGNATURE)
.build()); .build());
RMAuditLogger.ArgsBuilder args = new RMAuditLogger.ArgsBuilder()
.append(Keys.QUEUENAME, QUEUE).append(Keys.RECURSIVE, "true");
testFailureLogFormatHelper(checkIP, null, null, null, null, args);
} }
/** /**