RANGER-657: Solr plugin doesn't support for user principals with /$HOST in it
(cherry picked from commit f1135ea2ea6cd48209b73a25be77613c9d355abf) Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/d557e97d Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/d557e97d Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/d557e97d Branch: refs/heads/ranger-0.5 Commit: d557e97d6ddf424997649a17131e0e2e829b388e Parents: 836aa92 Author: Don Bosco Durai <[email protected]> Authored: Sun Oct 11 20:51:37 2015 -0700 Committer: Don Bosco Durai <[email protected]> Committed: Tue Nov 17 15:07:06 2015 -0800 ---------------------------------------------------------------------- .../apache/ranger/audit/provider/MiscUtil.java | 79 +++++- .../ranger/audit/queue/AuditFileSpool.java | 2 +- .../solr/authorizer/RangerSolrAuthorizer.java | 257 +++++++++++-------- 3 files changed, 236 insertions(+), 102 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d557e97d/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java ---------------------------------------------------------------------- diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java b/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java index a3a3a84..9586f73 100644 --- a/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java +++ b/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java @@ -37,6 +37,8 @@ import javax.security.auth.Subject; import javax.security.auth.login.AppConfigurationEntry; import javax.security.auth.login.Configuration; import javax.security.auth.login.LoginContext; + +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.security.UserGroupInformation; @@ -481,6 +483,33 @@ public class MiscUtil { return subjectLoginUser; } + public static String getKerberosNamesRules() { + return KerberosName.getRules(); + } + /** + * + * @param principal + * This could be in the format abc/[email protected] + * @return + */ + static public String getShortNameFromPrincipalName(String principal) { + if (principal == null) { + return null; + } + try { + // Assuming it is kerberos name for now + KerberosName kerbrosName = new KerberosName(principal); + String userName = kerbrosName.getShortName(); + userName = StringUtils.substringBefore(userName, "/"); + userName = StringUtils.substringBefore(userName, "@"); + return userName; + } catch (Throwable t) { + logger.error("Error converting kerberos name. principal=" + + principal + ", KerberosName.rules=" + KerberosName.getRules()); + } + return principal; + } + /** * @param userName * @return @@ -492,7 +521,6 @@ public class MiscUtil { try { UserGroupInformation ugi = UserGroupInformation .createRemoteUser(userName); - // UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); String groups[] = ugi.getGroupNames(); if (groups != null && groups.length > 0) { java.util.Set<String> groupsSet = new java.util.HashSet<String>(); @@ -545,6 +573,55 @@ public class MiscUtil { } + public static void authWithConfig(String appName, Configuration config) { + try { + if (config != null) { + logger.info("Getting AppConfigrationEntry[] for appName=" + + appName + ", config=" + config.toString()); + AppConfigurationEntry[] entries = config + .getAppConfigurationEntry(appName); + if (entries != null) { + logger.info("Got " + entries.length + + " AppConfigrationEntry elements for appName=" + + appName); + for (AppConfigurationEntry appEntry : entries) { + logger.info("APP_ENTRY:getLoginModuleName()=" + + appEntry.getLoginModuleName()); + logger.info("APP_ENTRY:getControlFlag()=" + + appEntry.getControlFlag()); + logger.info("APP_ENTRY.getOptions()=" + + appEntry.getOptions()); + } + } + + LoginContext loginContext = new LoginContext(appName, + new Subject(), null, config); + logger.info("Login in for appName=" + appName); + loginContext.login(); + logger.info("Principals after login=" + + loginContext.getSubject().getPrincipals()); + logger.info("UserGroupInformation.loginUserFromSubject(): appName=" + + appName + + ", principals=" + + loginContext.getSubject().getPrincipals()); + + UserGroupInformation ugi = MiscUtil + .createUGIFromSubject(loginContext.getSubject()); + if (ugi != null) { + MiscUtil.setUGILoginUser(ugi, loginContext.getSubject()); + } + + // UserGroupInformation.loginUserFromSubject(loginContext + // .getSubject()); + logger.info("POST UserGroupInformation.loginUserFromSubject UGI=" + + UserGroupInformation.getLoginUser()); + } + } catch (Throwable t) { + logger.fatal("Error logging as appName=" + appName + ", config=" + + config.toString()); + } + } + public static void authWithKerberos(String keytab, String principal, String nameRules) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d557e97d/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java ---------------------------------------------------------------------- diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java b/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java index bab496c..17ddab9 100644 --- a/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java +++ b/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java @@ -107,7 +107,7 @@ public class AuditFileSpool implements Runnable { boolean isWriting = true; boolean isDrain = false; - boolean isDestDown = true; + boolean isDestDown = false; private Gson gson = null; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d557e97d/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java ---------------------------------------------------------------------- diff --git a/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java b/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java index 8e0ada8..a8ecf15 100644 --- a/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java +++ b/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java @@ -28,9 +28,12 @@ import java.util.List; import java.util.Map; import java.util.Set; +import javax.security.auth.login.Configuration; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.ranger.audit.provider.MiscUtil; import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; import org.apache.ranger.authorization.utils.StringUtil; import org.apache.ranger.plugin.audit.RangerMultiResourceAuditHandler; @@ -50,26 +53,25 @@ public class RangerSolrAuthorizer implements AuthorizationPlugin { public static final String PROP_USE_PROXY_IP = "xasecure.solr.use_proxy_ip"; public static final String PROP_PROXY_IP_HEADER = "xasecure.solr.proxy_ip_header"; + public static final String PROP_SOLR_APP_NAME = "xasecure.solr.app.name"; public static final String KEY_COLLECTION = "collection"; public static final String ACCESS_TYPE_CREATE = "create"; public static final String ACCESS_TYPE_UPDATE = "update"; public static final String ACCESS_TYPE_QUERY = "query"; - public static final String ACCESS_TYPE_OTHER = "other"; + public static final String ACCESS_TYPE_OTHERS = "others"; public static final String ACCESS_TYPE_ADMIN = "solr_admin"; private static volatile RangerBasePlugin solrPlugin = null; boolean useProxyIP = false; String proxyIPHeader = "HTTP_X_FORWARDED_FOR"; + String solrAppName = "Client"; public RangerSolrAuthorizer() { logger.info("RangerSolrAuthorizer()"); - if (solrPlugin == null) { - logger.info("RangerSolrAuthorizer(): init called"); - solrPlugin = new RangerBasePlugin("solr", "solr"); - } + } /* @@ -82,16 +84,51 @@ public class RangerSolrAuthorizer implements AuthorizationPlugin { logger.info("init()"); try { - solrPlugin.init(); - useProxyIP = RangerConfiguration.getInstance().getBoolean( PROP_USE_PROXY_IP, useProxyIP); proxyIPHeader = RangerConfiguration.getInstance().get( PROP_PROXY_IP_HEADER, proxyIPHeader); + // First get from the -D property + solrAppName = System.getProperty("solr.kerberos.jaas.appname", + solrAppName); + // Override if required from Ranger properties + solrAppName = RangerConfiguration.getInstance().get( + PROP_SOLR_APP_NAME, solrAppName); + + logger.info("init(): useProxyIP=" + useProxyIP); + logger.info("init(): proxyIPHeader=" + proxyIPHeader); + logger.info("init(): solrAppName=" + solrAppName); + logger.info("init(): KerberosName.rules=" + + MiscUtil.getKerberosNamesRules()); + authToJAASFile(); } catch (Throwable t) { logger.fatal("Error init", t); } + + try { + if (solrPlugin == null) { + logger.info("RangerSolrAuthorizer(): init called"); + solrPlugin = new RangerBasePlugin("solr", "solr"); + solrPlugin.init(); + } + } catch (Throwable t) { + logger.fatal("Error creating and initializing RangerBasePlugin()"); + } + } + + private void authToJAASFile() { + try { + // logger.info("DEFAULT UGI=" + + // UserGroupInformation.getLoginUser()); + + Configuration config = javax.security.auth.login.Configuration + .getConfiguration(); + MiscUtil.authWithConfig(solrAppName, config); + logger.info("POST AUTH UGI=" + UserGroupInformation.getLoginUser()); + } catch (Throwable t) { + logger.error("Error authenticating for appName=" + solrAppName, t); + } } /* @@ -118,69 +155,75 @@ public class RangerSolrAuthorizer implements AuthorizationPlugin { */ @Override public AuthorizationResponse authorize(AuthorizationContext context) { - // TODO: Change this to Debug only - if (logger.isInfoEnabled()) { - logAuthorizationConext(context); - } + boolean isDenied = false; - RangerMultiResourceAuditHandler auditHandler = new RangerMultiResourceAuditHandler(); + try { + if (logger.isDebugEnabled()) { + logAuthorizationConext(context); + } - String userName = null; - Set<String> userGroups = null; - String ip = null; - Date eventTime = StringUtil.getUTCDate(); + RangerMultiResourceAuditHandler auditHandler = new RangerMultiResourceAuditHandler(); - // Set the User and Groups - Principal principal = context.getUserPrincipal(); - if (principal != null) { - userName = StringUtils.substringBefore(principal.getName(), "@"); - userGroups = getGroupsForUser(userName); - } + String userName = getUserName(context); + Set<String> userGroups = getGroupsForUser(userName); + String ip = null; + Date eventTime = StringUtil.getUTCDate(); - // // Set the IP - if (useProxyIP) { - ip = context.getHttpHeader(proxyIPHeader); - } - if (ip == null) { - ip = context.getHttpHeader("REMOTE_ADDR"); - } - - String requestData = context.getResource() + ":" + context.getParams(); + // // Set the IP + if (useProxyIP) { + ip = context.getHttpHeader(proxyIPHeader); + } + if (ip == null) { + ip = context.getHttpHeader("REMOTE_ADDR"); + } - // Create the list of requests for access check. Each field is broken - // into a request - List<RangerAccessRequestImpl> rangerRequests = new ArrayList<RangerAccessRequestImpl>(); - for (CollectionRequest collectionRequest : context - .getCollectionRequests()) { + String requestData = context.getResource() + ":" + + context.getParams(); - List<RangerAccessRequestImpl> requestsForCollection = createRequests( - userName, userGroups, ip, eventTime, context, - collectionRequest, requestData); - rangerRequests.addAll(requestsForCollection); - } + // Create the list of requests for access check. Each field is + // broken + // into a request + List<RangerAccessRequestImpl> rangerRequests = new ArrayList<RangerAccessRequestImpl>(); + for (CollectionRequest collectionRequest : context + .getCollectionRequests()) { - boolean isDenied = false; - try { - // Let's check the access for each request/resource - for (RangerAccessRequestImpl rangerRequest : rangerRequests) { - RangerAccessResult result = solrPlugin.isAccessAllowed( - rangerRequest, auditHandler); - if (result == null || !result.getIsAllowed()) { - isDenied = true; - // rejecting on first failure - break; + List<RangerAccessRequestImpl> requestsForCollection = createRequests( + userName, userGroups, ip, eventTime, context, + collectionRequest, requestData); + rangerRequests.addAll(requestsForCollection); + } + if (logger.isDebugEnabled()) { + logger.debug("rangerRequests.size()=" + rangerRequests.size()); + } + try { + // Let's check the access for each request/resource + for (RangerAccessRequestImpl rangerRequest : rangerRequests) { + RangerAccessResult result = solrPlugin.isAccessAllowed( + rangerRequest, auditHandler); + if (logger.isDebugEnabled()) { + logger.debug("rangerRequest=" + result); + } + if (result == null || !result.getIsAllowed()) { + isDenied = true; + // rejecting on first failure + break; + } } + } finally { + auditHandler.flushAudit(); } - } finally { - auditHandler.flushAudit(); + } catch (Throwable t) { + MiscUtil.logErrorMessageByInterval(logger, t.getMessage(), t); } - AuthorizationResponse response = null; if (isDenied) { response = new AuthorizationResponse(403); } else { response = new AuthorizationResponse(200); } + if (logger.isDebugEnabled()) { + logger.debug("context=" + context + ": returning: " + isDenied); + } return response; } @@ -188,53 +231,59 @@ public class RangerSolrAuthorizer implements AuthorizationPlugin { * @param context */ private void logAuthorizationConext(AuthorizationContext context) { - String collections = ""; - int i = -1; - for (CollectionRequest collectionRequest : context - .getCollectionRequests()) { - i++; - if (i > 0) { - collections += ","; + try { + // Note: This method should be called with isDebugEnabled() or + // isInfoEnabled() scope + + String collections = ""; + int i = -1; + for (CollectionRequest collectionRequest : context + .getCollectionRequests()) { + i++; + if (i > 0) { + collections += ","; + } + collections += collectionRequest.collectionName; } - collections += collectionRequest.collectionName; - } - String headers = ""; - i = -1; - @SuppressWarnings("unchecked") - Enumeration<String> eList = context.getHeaderNames(); - while (eList.hasMoreElements()) { - i++; - if (i > 0) { - headers += ","; + String headers = ""; + i = -1; + @SuppressWarnings("unchecked") + Enumeration<String> eList = context.getHeaderNames(); + while (eList.hasMoreElements()) { + i++; + if (i > 0) { + headers += ","; + } + String header = eList.nextElement(); + String value = context.getHttpHeader(header); + headers += header + "=" + value; } - String header = eList.nextElement(); - String value = context.getHttpHeader(header); - headers += header + "=" + value; - } - String ipAddress = context.getHttpHeader("HTTP_X_FORWARDED_FOR"); + String ipAddress = context.getHttpHeader("HTTP_X_FORWARDED_FOR"); - if (ipAddress == null) { - ipAddress = context.getHttpHeader("REMOTE_ADDR"); - } + if (ipAddress == null) { + ipAddress = context.getHttpHeader("REMOTE_HOST"); + } + if (ipAddress == null) { + ipAddress = context.getHttpHeader("REMOTE_ADDR"); + } - Principal principal = context.getUserPrincipal(); - String userName = null; - if (principal != null) { - userName = principal.getName(); - userName = StringUtils.substringBefore(userName, "/"); - userName = StringUtils.substringBefore(userName, "@"); + String userName = getUserName(context); + Set<String> groups = getGroupsForUser(userName); + + logger.info("AuthorizationContext: context.getResource()=" + + context.getResource() + ", solarParams=" + + context.getParams() + ", requestType=" + + context.getRequestType() + ", ranger.requestType=" + + mapToRangerAccessType(context) + ", userPrincipal=" + + context.getUserPrincipal() + ", userName=" + userName + + ", groups=" + groups + ", ipAddress=" + ipAddress + + ", collections=" + collections + ", headers=" + headers); + } catch (Throwable t) { + logger.error("Error getting request context!!!", t); } - logger.info("AuthorizationContext: context.getResource()=" - + context.getResource() + ", solarParams=" - + context.getParams() + ", requestType=" - + context.getRequestType() + ", userPrincipal=" - + context.getUserPrincipal() + ", userName=" + userName - + ", ipAddress=" + ipAddress + ", collections=" + collections - + ", headers=" + headers); - } /** @@ -292,18 +341,24 @@ public class RangerSolrAuthorizer implements AuthorizationPlugin { return rangerRequest; } + private String getUserName(AuthorizationContext context) { + Principal principal = context.getUserPrincipal(); + if (principal != null) { + return MiscUtil.getShortNameFromPrincipalName(principal.getName()); + } + return null; + } + /** * @param name * @return */ private Set<String> getGroupsForUser(String name) { - // TODO: Need to implement this method - - return null; + return MiscUtil.getGroupsForRequestUser(name); } String mapToRangerAccessType(AuthorizationContext context) { - String accessType = ACCESS_TYPE_OTHER; + String accessType = ACCESS_TYPE_OTHERS; RequestType requestType = context.getRequestType(); if (requestType.equals(RequestType.ADMIN)) { @@ -313,11 +368,13 @@ public class RangerSolrAuthorizer implements AuthorizationPlugin { } else if (requestType.equals(RequestType.WRITE)) { accessType = ACCESS_TYPE_UPDATE; } else if (requestType.equals(RequestType.UNKNOWN)) { - logger.info("UNKNOWN request type. Mapping it to " + accessType); - accessType = ACCESS_TYPE_OTHER; + logger.info("UNKNOWN request type. Mapping it to " + accessType + + ". Resource=" + context.getResource()); + accessType = ACCESS_TYPE_OTHERS; } else { logger.info("Request type is not supported. requestType=" - + requestType + ". Mapping it to " + accessType); + + requestType + ". Mapping it to " + accessType + + ". Resource=" + context.getResource()); } return accessType; }
