HBASE-12831 Changing the set of vis labels a user has access to doesn't generate an audit log event

Signed-off-by: Sean Busbey <busbey@apache.org>
This commit is contained in:
Ashish Singhi 2015-01-16 08:43:58 +05:30 committed by Sean Busbey
parent 6b20a0f831
commit 070e2dd89a
2 changed files with 77 additions and 12 deletions

View File

@ -55,6 +55,7 @@ log4j.appender.RFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
log4j.category.SecurityLogger=${hbase.security.logger}
log4j.additivity.SecurityLogger=false
#log4j.logger.SecurityLogger.org.apache.hadoop.hbase.security.access.AccessController=TRACE
#log4j.logger.SecurityLogger.org.apache.hadoop.hbase.security.visibility.VisibilityController=TRACE
#
# Null Appender

View File

@ -24,6 +24,7 @@ import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LA
import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_NAME;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@ -38,15 +39,16 @@ import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.CoprocessorEnvironment;
import org.apache.hadoop.hbase.DoNotRetryIOException;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TagRewriteCell;
import org.apache.hadoop.hbase.MetaTableAccessor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.Tag;
import org.apache.hadoop.hbase.MetaTableAccessor;
import org.apache.hadoop.hbase.TagRewriteCell;
import org.apache.hadoop.hbase.TagType;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.client.Append;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
@ -97,7 +99,6 @@ import org.apache.hadoop.hbase.replication.ReplicationEndpoint;
import org.apache.hadoop.hbase.security.AccessDeniedException;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.access.AccessControlLists;
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
import org.apache.hadoop.hbase.security.access.AccessController;
import org.apache.hadoop.hbase.util.ByteStringer;
import org.apache.hadoop.hbase.util.Bytes;
@ -119,6 +120,8 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
VisibilityLabelsService.Interface, CoprocessorService {
private static final Log LOG = LogFactory.getLog(VisibilityController.class);
private static final Log AUDITLOG = LogFactory.getLog("SecurityLogger."
+ VisibilityController.class.getName());
// flags if we are running on a region of the 'labels' table
private boolean labelsRegion = false;
// Flag denoting whether AcessController is available or not.
@ -726,9 +729,9 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
new VisibilityControllerNotReadyException("VisibilityController not yet initialized!"),
response);
} else {
List<byte[]> labels = new ArrayList<byte[]>(visLabels.size());
try {
checkCallingUserAuth();
List<byte[]> labels = new ArrayList<byte[]>(visLabels.size());
RegionActionResult successResult = RegionActionResult.newBuilder().build();
for (VisibilityLabel visLabel : visLabels) {
byte[] label = visLabel.getLabel().toByteArray();
@ -739,6 +742,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
}
if (!labels.isEmpty()) {
OperationStatus[] opStatus = this.visibilityLabelService.addLabels(labels);
logResult(true, "addLabels", "Adding labels allowed", null, labels, null);
int i = 0;
for (OperationStatus status : opStatus) {
while (response.getResult(i) != successResult)
@ -752,6 +756,10 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
i++;
}
}
} catch (AccessDeniedException e) {
logResult(false, "addLabels", e.getMessage(), null, labels, null);
LOG.error("User is not having required permissions to add labels", e);
setExceptionResults(visLabels.size(), e, response);
} catch (IOException e) {
LOG.error(e);
setExceptionResults(visLabels.size(), e, response);
@ -780,14 +788,17 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
new VisibilityControllerNotReadyException("VisibilityController not yet initialized!"),
response);
} else {
byte[] user = request.getUser().toByteArray();
List<byte[]> labelAuths = new ArrayList<byte[]>(auths.size());
try {
checkCallingUserAuth();
List<byte[]> labelAuths = new ArrayList<byte[]>(auths.size());
for (ByteString authBS : auths) {
labelAuths.add(authBS.toByteArray());
}
OperationStatus[] opStatus = this.visibilityLabelService.setAuths(request.getUser()
.toByteArray(), labelAuths);
OperationStatus[] opStatus = this.visibilityLabelService.setAuths(user, labelAuths);
logResult(true, "setAuths", "Setting authorization for labels allowed", user, labelAuths,
null);
RegionActionResult successResult = RegionActionResult.newBuilder().build();
for (OperationStatus status : opStatus) {
if (status.getOperationStatusCode() == SUCCESS) {
@ -799,6 +810,10 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
response.addResult(failureResultBuilder.build());
}
}
} catch (AccessDeniedException e) {
logResult(false, "setAuths", e.getMessage(), user, labelAuths, null);
LOG.error("User is not having required permissions to set authorization", e);
setExceptionResults(auths.size(), e, response);
} catch (IOException e) {
LOG.error(e);
setExceptionResults(auths.size(), e, response);
@ -807,6 +822,39 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
done.run(response.build());
}
private void logResult(boolean isAllowed, String request, String reason, byte[] user,
List<byte[]> labelAuths, String regex) {
if (AUDITLOG.isTraceEnabled()) {
RequestContext ctx = RequestContext.get();
InetAddress remoteAddr = null;
if (ctx != null) {
remoteAddr = ctx.getRemoteAddress();
}
List<String> labelAuthsStr = new ArrayList<>();
if (labelAuths != null) {
int labelAuthsSize = labelAuths.size();
labelAuthsStr = new ArrayList<>(labelAuthsSize);
for (int i = 0; i < labelAuthsSize; i++) {
labelAuthsStr.add(Bytes.toString(labelAuths.get(i)));
}
}
User requestingUser = null;
try {
requestingUser = VisibilityUtils.getActiveUser();
} catch (IOException e) {
LOG.warn("Failed to get active system user.");
LOG.debug("Details on failure to get active system user.", e);
}
AUDITLOG.trace("Access " + (isAllowed ? "allowed" : "denied") + " for user "
+ (requestingUser != null ? requestingUser.getShortName() : "UNKNOWN") + "; reason: "
+ reason + "; remote address: " + (remoteAddr != null ? remoteAddr : "") + "; request: "
+ request + "; user: " + (user != null ? Bytes.toShort(user) : "null") + "; labels: "
+ labelAuthsStr + "; regex: " + regex);
}
}
@Override
public synchronized void getAuths(RpcController controller, GetAuthsRequest request,
RpcCallback<GetAuthsResponse> done) {
@ -832,6 +880,10 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
else {
labels = this.visibilityLabelService.getUserAuths(user, false);
}
logResult(true, "getAuths", "Get authorizations for user allowed", user, null, null);
} catch (AccessDeniedException e) {
logResult(false, "getAuths", e.getMessage(), user, null, null);
ResponseConverter.setControllerException(controller, e);
} catch (IOException e) {
ResponseConverter.setControllerException(controller, e);
}
@ -854,6 +906,8 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
setExceptionResults(auths.size(), new CoprocessorException(
"VisibilityController not yet initialized"), response);
} else {
byte[] requestUser = request.getUser().toByteArray();
List<byte[]> labelAuths = new ArrayList<byte[]>(auths.size());
try {
// When AC is ON, do AC based user auth check
if (this.acOn && !isSystemOrSuperUser()) {
@ -863,12 +917,14 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
}
checkCallingUserAuth(); // When AC is not in place the calling user should have SYSTEM_LABEL
// auth to do this action.
List<byte[]> labelAuths = new ArrayList<byte[]>(auths.size());
for (ByteString authBS : auths) {
labelAuths.add(authBS.toByteArray());
}
OperationStatus[] opStatus = this.visibilityLabelService.clearAuths(request.getUser()
.toByteArray(), labelAuths);
OperationStatus[] opStatus =
this.visibilityLabelService.clearAuths(requestUser, labelAuths);
logResult(true, "clearAuths", "Removing authorization for labels allowed", requestUser,
labelAuths, null);
RegionActionResult successResult = RegionActionResult.newBuilder().build();
for (OperationStatus status : opStatus) {
if (status.getOperationStatusCode() == SUCCESS) {
@ -880,6 +936,10 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
response.addResult(failureResultBuilder.build());
}
}
} catch (AccessDeniedException e) {
logResult(false, "clearAuths", e.getMessage(), requestUser, labelAuths, null);
LOG.error("User is not having required permissions to clear authorization", e);
setExceptionResults(auths.size(), e, response);
} catch (IOException e) {
LOG.error(e);
setExceptionResults(auths.size(), e, response);
@ -896,6 +956,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
controller.setFailed("VisibilityController not yet initialized");
} else {
List<String> labels = null;
String regex = request.hasRegex() ? request.getRegex() : null;
try {
// We do ACL check here as we create scanner directly on region. It will not make calls to
// AccessController CP methods.
@ -905,8 +966,11 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements
+ (requestingUser != null ? requestingUser.getShortName() : "null")
+ "' is not authorized to perform this action.");
}
String regex = request.hasRegex() ? request.getRegex() : null;
labels = this.visibilityLabelService.listLabels(regex);
logResult(false, "listLabels", "Listing labels allowed", null, null, regex);
} catch (AccessDeniedException e) {
logResult(false, "listLabels", e.getMessage(), null, null, regex);
ResponseConverter.setControllerException(controller, e);
} catch (IOException e) {
ResponseConverter.setControllerException(controller, e);
}