HADOOP-13903. Improvements to KMS logging to help debug authorization errors. (Tristan Stevens via asuresh)
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/be529dad Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/be529dad Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/be529dad Branch: refs/heads/YARN-5734 Commit: be529dade182dd2f3718fc52133f43e83dce191f Parents: 467f5f1 Author: Arun Suresh <asur...@apache.org> Authored: Wed Jan 11 00:26:02 2017 -0800 Committer: Arun Suresh <asur...@apache.org> Committed: Wed Jan 11 00:26:02 2017 -0800 ---------------------------------------------------------------------- .../hadoop/crypto/key/kms/server/KMSACLs.java | 36 ++++++++++++++++++-- .../hadoop/crypto/key/kms/server/KMSAudit.java | 30 ++++++++++++++-- .../crypto/key/kms/server/KMSAuditLogger.java | 21 ++++++++++-- 3 files changed, 80 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/be529dad/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java index c36fcf8..096f756 100644 --- a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java +++ b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java @@ -236,9 +236,26 @@ public class KMSACLs implements Runnable, KeyACLs { */ public boolean hasAccess(Type type, UserGroupInformation ugi) { boolean access = acls.get(type).isUserAllowed(ugi); + if (LOG.isDebugEnabled()) { + LOG.debug("Checking user [{}] for: {} {} ", ugi.getShortUserName(), + type.toString(), acls.get(type).getAclString()); + } if (access) { AccessControlList blacklist = blacklistedAcls.get(type); access = (blacklist == null) || !blacklist.isUserInList(ugi); + if (LOG.isDebugEnabled()) { + if (blacklist == null) { + LOG.debug("No blacklist for {}", type.toString()); + } else if (access) { + LOG.debug("user is in {}" , blacklist.getAclString()); + } else { + LOG.debug("user is not in {}" , blacklist.getAclString()); + } + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("User: [{}], Type: {} Result: {}", ugi.getShortUserName(), + type.toString(), access); } return access; } @@ -259,8 +276,12 @@ public class KMSACLs implements Runnable, KeyACLs { @Override public boolean hasAccessToKey(String keyName, UserGroupInformation ugi, KeyOpType opType) { - return checkKeyAccess(keyName, ugi, opType) + boolean access = checkKeyAccess(keyName, ugi, opType) || checkKeyAccess(whitelistKeyAcls, ugi, opType); + if (!access) { + KMSWebApp.getKMSAudit().unauthorized(ugi, opType, keyName); + } + return access; } private boolean checkKeyAccess(String keyName, UserGroupInformation ugi, @@ -269,9 +290,15 @@ public class KMSACLs implements Runnable, KeyACLs { if (keyAcl == null) { // If No key acl defined for this key, check to see if // there are key defaults configured for this operation + LOG.debug("Key: {} has no ACLs defined, using defaults.", keyName); keyAcl = defaultKeyAcls; } - return checkKeyAccess(keyAcl, ugi, opType); + boolean access = checkKeyAccess(keyAcl, ugi, opType); + if (LOG.isDebugEnabled()) { + LOG.debug("User: [{}], OpType: {}, KeyName: {} Result: {}", + ugi.getShortUserName(), opType.toString(), keyName, access); + } + return access; } private boolean checkKeyAccess(Map<KeyOpType, AccessControlList> keyAcl, @@ -280,8 +307,13 @@ public class KMSACLs implements Runnable, KeyACLs { if (acl == null) { // If no acl is specified for this operation, // deny access + LOG.debug("No ACL available for key, denying access for {}", opType); return false; } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Checking user [{}] for: {}: {}" + ugi.getShortUserName(), + opType.toString(), acl.getAclString()); + } return acl.isUserAllowed(ugi); } } http://git-wip-us.apache.org/repos/asf/hadoop/blob/be529dad/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAudit.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAudit.java b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAudit.java index 7fdfc34..13a2d5c 100644 --- a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAudit.java +++ b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAudit.java @@ -23,6 +23,8 @@ import static org.apache.hadoop.crypto.key.kms.server.KMSAuditLogger.OpStatus; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.crypto.key.kms.server.KMSACLs.Type; +import org.apache.hadoop.crypto.key.kms.server.KeyAuthorizationKeyProvider.KeyOpType; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.util.Time; @@ -168,7 +170,25 @@ public class KMSAudit { } } - private void op(final OpStatus opStatus, final KMS.KMSOp op, + /** + * Logs to the audit service a single operation on the KMS or on a key. + * + * @param opStatus + * The outcome of the audited event + * @param op + * The operation being audited (either {@link KMS.KMSOp} or + * {@link Type} N.B this is passed as an {@link Object} to allow + * either enum to be passed in. + * @param ugi + * The user's security context + * @param key + * The String name of the key if applicable + * @param remoteHost + * The hostname of the requesting service + * @param extraMsg + * Any extra details for auditing + */ + private void op(final OpStatus opStatus, final Object op, final UserGroupInformation ugi, final String key, final String remoteHost, final String extraMsg) { final String user = ugi == null ? null: ugi.getShortUserName(); @@ -215,6 +235,12 @@ public class KMSAudit { op(OpStatus.UNAUTHORIZED, op, user, key, "Unknown", ""); } + public void unauthorized(UserGroupInformation user, KeyOpType op, + String key) { + op(OpStatus.UNAUTHORIZED, op, user, key, "Unknown", ""); + + } + public void error(UserGroupInformation user, String method, String url, String extraMsg) { op(OpStatus.ERROR, null, user, null, "Unknown", "Method:'" + method @@ -228,7 +254,7 @@ public class KMSAudit { + " URL:" + url + " ErrorMsg:'" + extraMsg + "'"); } - private static String createCacheKey(String user, String key, KMS.KMSOp op) { + private static String createCacheKey(String user, String key, Object op) { return user + "#" + key + "#" + op; } http://git-wip-us.apache.org/repos/asf/hadoop/blob/be529dad/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAuditLogger.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAuditLogger.java b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAuditLogger.java index a539724..2e2ba1d 100644 --- a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAuditLogger.java +++ b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSAuditLogger.java @@ -23,6 +23,7 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.crypto.key.kms.server.KMSACLs.Type; import org.apache.hadoop.security.UserGroupInformation; /** @@ -46,7 +47,7 @@ interface KMSAuditLogger { */ class AuditEvent { private final AtomicLong accessCount = new AtomicLong(-1); - private final KMS.KMSOp op; + private final Object op; private final String keyName; private final String user; private final String impersonator; @@ -55,7 +56,21 @@ interface KMSAuditLogger { private final long startTime = System.currentTimeMillis(); private long endTime = startTime; - AuditEvent(KMS.KMSOp op, UserGroupInformation ugi, String keyName, + /** + * @param op + * The operation being audited (either {@link KMS.KMSOp} or + * {@link Type} N.B this is passed as an {@link Object} to allow + * either enum to be passed in. + * @param ugi + * The user's security context + * @param keyName + * The String name of the key if applicable + * @param remoteHost + * The hostname of the requesting service + * @param msg + * Any extra details for auditing + */ + AuditEvent(Object op, UserGroupInformation ugi, String keyName, String remoteHost, String msg) { this.keyName = keyName; if (ugi == null) { @@ -79,7 +94,7 @@ interface KMSAuditLogger { return accessCount; } - public KMS.KMSOp getOp() { + public Object getOp() { return op; } --------------------------------------------------------------------- To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org For additional commands, e-mail: common-commits-h...@hadoop.apache.org