Repository: incubator-ranger Updated Branches: refs/heads/master 6f48a6207 -> fa59f97bc
RANGER-1135: Knox and Storm plugins should use secure policy download endpoint in kerberos mode Signed-off-by: Velmurugan Periasamy <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/baac2ba9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/baac2ba9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/baac2ba9 Branch: refs/heads/master Commit: baac2ba9fcbcdf00b08d69c98fa31f453ababc39 Parents: 6f48a62 Author: Madhan Neethiraj <[email protected]> Authored: Thu Aug 4 19:47:13 2016 -0700 Committer: Velmurugan Periasamy <[email protected]> Committed: Fri Aug 5 19:07:08 2016 -0400 ---------------------------------------------------------------------- .../ranger/plugin/util/RangerRESTUtils.java | 5 ++ .../client/RangerAdminJersey2RESTClient.java | 51 +++++++++++---- .../authorization/knox/RangerPDPKnoxFilter.java | 68 +++++++++++++++++--- .../storm/authorizer/RangerStormAuthorizer.java | 60 +++++++++++++++-- 4 files changed, 160 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/baac2ba9/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java index 9a47280..878d172 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java @@ -87,6 +87,11 @@ public class RangerRESTUtils { return url; } + public String getSecureUrlForPolicyUpdate(String baseUrl, String serviceName) { + String url = baseUrl + REST_URL_POLICY_GET_FOR_SECURE_SERVICE_IF_UPDATED + serviceName; + return url; + } + public boolean isSsl(String _baseUrl) { return StringUtils.isEmpty(_baseUrl) ? false : _baseUrl.toLowerCase().startsWith("https"); } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/baac2ba9/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java ---------------------------------------------------------------------- diff --git a/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java b/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java index 4166786..29a5026 100644 --- a/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java +++ b/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java @@ -20,6 +20,7 @@ package org.apache.ranger.admin.client; import java.lang.reflect.Type; +import java.security.PrivilegedAction; import java.util.Date; import java.util.List; @@ -34,7 +35,9 @@ import javax.ws.rs.core.Response; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.security.AccessControlException; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.ranger.plugin.util.*; +import org.apache.ranger.audit.provider.MiscUtil; import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; import org.glassfish.jersey.client.ClientProperties; @@ -61,8 +64,7 @@ public class RangerAdminJersey2RESTClient implements RangerAdminClient { String _pluginId = null; int _restClientConnTimeOutMs; int _restClientReadTimeOutMs; - - + @Override public void init(String serviceName, String appId, String configPropertyPrefix) { if(LOG.isDebugEnabled()) { @@ -89,18 +91,46 @@ public class RangerAdminJersey2RESTClient implements RangerAdminClient { } @Override - public ServicePolicies getServicePoliciesIfUpdated(long lastKnownVersion) throws Exception { + public ServicePolicies getServicePoliciesIfUpdated(final long lastKnownVersion) throws Exception { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerAdminJersey2RESTClient.getServicePoliciesIfUpdated(" + lastKnownVersion + ")"); } - ServicePolicies servicePolicies = null; - String url = _utils.getUrlForPolicyUpdate(_baseUrl, _serviceName); + + UserGroupInformation user = MiscUtil.getUGILoginUser(); + boolean isSecureMode = user != null && UserGroupInformation.isSecurityEnabled(); + + String url = null; try { - Response response = _client.target(url) - .queryParam(RangerRESTUtils.REST_PARAM_LAST_KNOWN_POLICY_VERSION, Long.toString(lastKnownVersion)) - .queryParam(RangerRESTUtils.REST_PARAM_PLUGIN_ID, _pluginId) - .request(MediaType.APPLICATION_JSON_TYPE) - .get(); + ServicePolicies servicePolicies = null; + Response response = null; + if(isSecureMode){ + if(LOG.isDebugEnabled()) { + LOG.debug("Checking Service policy if updated as user : " + user); + } + url = _utils.getSecureUrlForPolicyUpdate(_baseUrl, _serviceName); + final String secureUrl = url; + PrivilegedAction<Response> action = new PrivilegedAction<Response>() { + public Response run() { + return _client.target(secureUrl) + .queryParam(RangerRESTUtils.REST_PARAM_LAST_KNOWN_POLICY_VERSION, Long.toString(lastKnownVersion)) + .queryParam(RangerRESTUtils.REST_PARAM_PLUGIN_ID, _pluginId) + .request(MediaType.APPLICATION_JSON_TYPE) + .get(); + }; + }; + response = user.doAs(action); + }else{ + if(LOG.isDebugEnabled()) { + LOG.debug("Checking Service policy if updated with old api call"); + } + url = _utils.getUrlForPolicyUpdate(_baseUrl, _serviceName); + response = _client.target(url) + .queryParam(RangerRESTUtils.REST_PARAM_LAST_KNOWN_POLICY_VERSION, Long.toString(lastKnownVersion)) + .queryParam(RangerRESTUtils.REST_PARAM_PLUGIN_ID, _pluginId) + .request(MediaType.APPLICATION_JSON_TYPE) + .get(); + } + int httpResponseCode = response == null ? -1 : response.getStatus(); String body = null; @@ -280,5 +310,4 @@ public class RangerAdminJersey2RESTClient implements RangerAdminClient { return _client; } - } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/baac2ba9/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java ---------------------------------------------------------------------- diff --git a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java index 90db945..616cfcc 100644 --- a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java +++ b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java @@ -25,6 +25,7 @@ import java.util.HashSet; import java.util.Set; import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -39,19 +40,51 @@ import org.apache.hadoop.gateway.filter.AbstractGatewayFilter; import org.apache.hadoop.gateway.security.GroupPrincipal; import org.apache.hadoop.gateway.security.ImpersonatedPrincipal; import org.apache.hadoop.gateway.security.PrimaryPrincipal; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.ranger.audit.provider.MiscUtil; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessResult; public class RangerPDPKnoxFilter implements Filter { private static final Log LOG = LogFactory.getLog(RangerPDPKnoxFilter.class); + + private static final String KNOX_GATEWAY_JASS_CONFIG_SECTION = "com.sun.security.jgss.initiate"; + private String resourceRole = null; - static final KnoxRangerPlugin plugin = new KnoxRangerPlugin(); + private static volatile KnoxRangerPlugin plugin = null; @Override public void init(FilterConfig filterConfig) throws ServletException { resourceRole = getInitParameter(filterConfig, "resource.role"); - plugin.init(); + + KnoxRangerPlugin me = plugin; + + if(me == null) { + synchronized (RangerPDPKnoxFilter.class) { + me = plugin; + + if(me == null) { + try { + Subject subject = getKnoxSubject(); + + UserGroupInformation ugi = MiscUtil.createUGIFromSubject(subject); + + if (ugi != null) { + MiscUtil.setUGILoginUser(ugi, subject); + } + + LOG.info("LoginUser=" + MiscUtil.getUGILoginUser()); + } catch (Throwable t) { + LOG.error("Error getting principal.", t); + } + + LOG.info("Creating KnoxRangerPlugin"); + plugin = new KnoxRangerPlugin(); + plugin.init(); + } + } + } } private String getInitParameter(FilterConfig filterConfig, String paramName) { @@ -110,16 +143,19 @@ public class RangerPDPKnoxFilter implements Filter { .groups(groups) .clientIp(clientIp) .build(); - - RangerAccessResult result = plugin.isAccessAllowed(accessRequest); - boolean accessAllowed = result != null && result.getIsAllowed(); - boolean audited = result != null && result.getIsAudited(); - + boolean accessAllowed = false; + + if (plugin != null) { + RangerAccessResult result = plugin.isAccessAllowed(accessRequest); + + accessAllowed = result != null && result.getIsAllowed(); + } + if (LOG.isDebugEnabled()) { LOG.debug("Access allowed: " + accessAllowed); - LOG.debug("Audit enabled: " + audited); } + if (accessAllowed) { chain.doFilter(request, response); } else { @@ -156,5 +192,21 @@ public class RangerPDPKnoxFilter implements Filter { return resourceRole; } + private Subject getKnoxSubject() { + Subject ret = null; + + try { + LoginContext lc = new LoginContext(KNOX_GATEWAY_JASS_CONFIG_SECTION); + + lc.login(); + + ret = lc.getSubject(); + } catch (Exception excp) { + LOG.error("Failed to get Storm server login subject", excp); + } + + return ret; + } + } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/baac2ba9/storm-agent/src/main/java/org/apache/ranger/authorization/storm/authorizer/RangerStormAuthorizer.java ---------------------------------------------------------------------- diff --git a/storm-agent/src/main/java/org/apache/ranger/authorization/storm/authorizer/RangerStormAuthorizer.java b/storm-agent/src/main/java/org/apache/ranger/authorization/storm/authorizer/RangerStormAuthorizer.java index b31ce31..e1516fb 100644 --- a/storm-agent/src/main/java/org/apache/ranger/authorization/storm/authorizer/RangerStormAuthorizer.java +++ b/storm-agent/src/main/java/org/apache/ranger/authorization/storm/authorizer/RangerStormAuthorizer.java @@ -22,8 +22,10 @@ import java.security.Principal; import java.util.Map; import java.util.Set; +import javax.security.auth.login.LoginContext; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.ranger.audit.provider.MiscUtil; import org.apache.ranger.authorization.storm.StormRangerPlugin; import org.apache.ranger.authorization.utils.StringUtil; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; @@ -37,11 +39,15 @@ import org.apache.storm.Config; import org.apache.storm.security.auth.IAuthorizer; import org.apache.storm.security.auth.ReqContext; +import javax.security.auth.Subject; + public class RangerStormAuthorizer implements IAuthorizer { private static final Logger LOG = LoggerFactory.getLogger(RangerStormAuthorizer.class); - - static final StormRangerPlugin plugin = new StormRangerPlugin(); + + private static final String STORM_CLIENT_JASS_CONFIG_SECTION = "StormClient"; + + private static volatile StormRangerPlugin plugin = null; static final Set<String> noAuthzOperations = Sets.newHashSet(new String[] { "getNimbusConf", "getClusterInfo" }); @@ -84,6 +90,8 @@ public class RangerStormAuthorizer implements IAuthorizer { if(noAuthzOperations.contains(aOperationName)) { accessAllowed = true; + } else if(plugin == null) { + LOG.info("Ranger plugin not initialized yet! Skipping authorization; allowedFlag => [" + accessAllowed + "], Audit Enabled:" + isAuditEnabled); } else { String userName = null ; String[] groups = null ; @@ -105,7 +113,7 @@ public class RangerStormAuthorizer implements IAuthorizer { if (userName != null) { String clientIp = (aRequestContext.remoteAddress() == null ? null : aRequestContext.remoteAddress().getHostAddress() ) ; - RangerAccessRequest accessRequest = plugin.buildAccessRequest(userName, groups, clientIp, topologyName, aOperationName); + RangerAccessRequest accessRequest = plugin.buildAccessRequest(userName, groups, clientIp, topologyName, aOperationName); RangerAccessResult result = plugin.isAccessAllowed(accessRequest); accessAllowed = result != null && result.getIsAllowed(); isAuditEnabled = result != null && result.getIsAudited(); @@ -142,7 +150,49 @@ public class RangerStormAuthorizer implements IAuthorizer { @Override public void prepare(Map aStormConfigMap) { - plugin.init(); + StormRangerPlugin me = plugin; + + if (me == null) { + synchronized(RangerStormAuthorizer.class) { + me = plugin; + + if (me == null) { + try { + Subject subject = getStormSubject(); + + UserGroupInformation ugi = MiscUtil.createUGIFromSubject(subject); + + if (ugi != null) { + MiscUtil.setUGILoginUser(ugi, subject); + } + + LOG.info("LoginUser=" + MiscUtil.getUGILoginUser()); + } catch (Throwable t) { + LOG.error("Error getting principal.", t); + } + + LOG.info("Creating StormRangerPlugin"); + + plugin = new StormRangerPlugin(); + plugin.init(); + } + } + } + } + + private Subject getStormSubject() { + Subject ret = null; + + try { + LoginContext lc = new LoginContext(STORM_CLIENT_JASS_CONFIG_SECTION); + + lc.login(); + + ret = lc.getSubject(); + } catch (Exception excp) { + LOG.error("Failed to get Storm server login subject", excp); + } + + return ret; } - }
