/* * Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.wso2.carbon.identity.entitlement.filter; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.util.AXIOMUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.entitlement.filter.callback.BasicAuthCallBackHandler; import org.wso2.carbon.identity.entitlement.filter.callback.EntitlementFilterCallBackHandler; import org.wso2.carbon.identity.entitlement.filter.exception.EntitlementFilterException; import org.wso2.carbon.identity.entitlement.proxy.PEPProxy; import org.wso2.carbon.identity.entitlement.proxy.PEPProxyConfig; import org.wso2.carbon.identity.entitlement.proxy.exception.EntitlementProxyException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.xml.namespace.QName; import java.util.HashMap; import java.util.Map; public class EntitlementFilter implements Filter { private static final Log log = LogFactory.getLog(EntitlementFilter.class); private PEPProxy pepProxy; private String client; private String remoteServiceUrl; private String remoteServiceUserName; private String remoteServicePassword; private String thriftHost; private String thriftPort; private String reuseSession; private String cacheType; private int invalidationInterval; private int maxCacheEntries; private String subjectScope; private String subjectAttributeName; private String authRedirectURL; /** * In this init method the required attributes are taken from web.xml, if there are not provided they will be set to default. * authRedirectURL attribute have to provided */ @Override public void init(FilterConfig filterConfig) throws EntitlementFilterException { //This Attributes are mandatory So have to be specified in the web.xml authRedirectURL = filterConfig.getInitParameter(EntitlementConstants.AUTH_REDIRECT_URL); remoteServiceUserName = filterConfig.getServletContext().getInitParameter(EntitlementConstants.USERNAME); remoteServicePassword = filterConfig.getServletContext().getInitParameter(EntitlementConstants.PASSWORD); remoteServiceUrl = filterConfig.getServletContext().getInitParameter(EntitlementConstants.REMOTE_SERVICE_URL); //This Attributes are not mandatory client = filterConfig.getServletContext().getInitParameter(EntitlementConstants.CLIENT); if (client == null) { client = EntitlementConstants.defaultClient; } subjectScope = filterConfig.getServletContext().getInitParameter(EntitlementConstants.SUBJECT_SCOPE); if (subjectScope == null) { subjectScope = EntitlementConstants.defaultSubjectScope; } subjectAttributeName = filterConfig.getServletContext().getInitParameter(EntitlementConstants.SUBJECT_ATTRIBUTE_NAME); if (subjectAttributeName == null) { subjectAttributeName = EntitlementConstants.defaultSubjectAttributeName; } cacheType = filterConfig.getInitParameter(EntitlementConstants.CACHE_TYPE); if (cacheType == null) { cacheType = EntitlementConstants.defaultCacheType; } if (filterConfig.getInitParameter(EntitlementConstants.MAX_CACHE_ENTRIES) != null) { maxCacheEntries = Integer.parseInt(filterConfig.getInitParameter(EntitlementConstants.MAX_CACHE_ENTRIES)); } else { maxCacheEntries = 0; } if (filterConfig.getInitParameter(EntitlementConstants.INVALIDATION_INTERVAL) != null) { invalidationInterval = Integer.parseInt(filterConfig.getInitParameter(EntitlementConstants.INVALIDATION_INTERVAL)); } else { invalidationInterval = 0; } if (filterConfig.getInitParameter(EntitlementConstants.THRIFT_HOST) != null) { thriftHost = filterConfig.getInitParameter(EntitlementConstants.THRIFT_HOST); } else { thriftHost = EntitlementConstants.defaultThriftHost; } if (filterConfig.getInitParameter(EntitlementConstants.THRIFT_PORT) != null) { thriftPort = filterConfig.getInitParameter(EntitlementConstants.THRIFT_PORT); } else { thriftPort = EntitlementConstants.defaultThriftPort; } Map<String, Map<String, String>> appToPDPClientConfigMap = new HashMap<String, Map<String, String>>(); Map<String, String> clientConfigMap = new HashMap<String, String>(); if(client!=null){ if(client.equals(EntitlementConstants.SOAP)){ clientConfigMap.put(EntitlementConstants.CLIENT, client); clientConfigMap.put(EntitlementConstants.SERVER_URL, remoteServiceUrl); clientConfigMap.put(EntitlementConstants.USERNAME, remoteServiceUserName); clientConfigMap.put(EntitlementConstants.PASSWORD, remoteServicePassword); clientConfigMap.put(EntitlementConstants.REUSE_SESSION, reuseSession); } else if (client.equals(EntitlementConstants.BASIC_AUTH)) { clientConfigMap.put(EntitlementConstants.CLIENT, client); clientConfigMap.put(EntitlementConstants.SERVER_URL, remoteServiceUrl); clientConfigMap.put(EntitlementConstants.USERNAME, remoteServiceUserName); clientConfigMap.put(EntitlementConstants.PASSWORD, remoteServicePassword); }else if (client.equals(EntitlementConstants.THRIFT)) { clientConfigMap.put(EntitlementConstants.CLIENT, client); clientConfigMap.put(EntitlementConstants.SERVER_URL, remoteServiceUrl); clientConfigMap.put(EntitlementConstants.USERNAME, remoteServiceUserName); clientConfigMap.put(EntitlementConstants.PASSWORD, remoteServicePassword); clientConfigMap.put(EntitlementConstants.REUSE_SESSION, reuseSession); clientConfigMap.put(EntitlementConstants.THRIFT_HOST, thriftHost); clientConfigMap.put(EntitlementConstants.THRIFT_PORT, thriftPort); }else { throw new EntitlementFilterException("EntitlementMediator initialization error: Unsupported client"); } }else { clientConfigMap.put(EntitlementConstants.SERVER_URL, remoteServiceUrl); clientConfigMap.put(EntitlementConstants.USERNAME, remoteServiceUserName); clientConfigMap.put(EntitlementConstants.PASSWORD, remoteServicePassword); } appToPDPClientConfigMap.put("EntitlementMediator", clientConfigMap); PEPProxyConfig config = new PEPProxyConfig(appToPDPClientConfigMap, "EntitlementMediator", cacheType, invalidationInterval, maxCacheEntries); try { pepProxy = new PEPProxy(config); } catch (EntitlementProxyException e) { throw new EntitlementFilterException("Error while initializing the Entitlement PEP Proxy",e); } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws EntitlementFilterException { String simpleDecision = EntitlementConstants.DENY; String userName; String action; String resource; String env = ""; userName = findUserName((HttpServletRequest) servletRequest, subjectScope, subjectAttributeName); resource = findResource((HttpServletRequest) servletRequest); action = findAction((HttpServletRequest) servletRequest); if (((HttpServletRequest) servletRequest).getRequestURI().contains("/updateCacheAuth.do")) { try { pepProxy.clear(); } catch (Exception e) { log.error("Error while Making the Decision ", e); } } else { try { String decision = pepProxy.getDecision(userName, resource, action, env); OMElement decisionElement = AXIOMUtil.stringToOM(decision); String namespace = ""; if (decisionElement.getNamespace().getNamespaceURI() != null) { namespace = decisionElement.getNamespace().getNamespaceURI(); } simpleDecision = decisionElement.getFirstChildWithName(new QName(namespace, "Result")). getFirstChildWithName(new QName(namespace, "Decision")).getText(); } catch (Exception e) { throw new EntitlementFilterException("Exception while making the decision " , e); } } completeAuthorization(simpleDecision, servletRequest, servletResponse, filterChain); } @Override public void destroy() { pepProxy = null; client = null; remoteServiceUrl = null; remoteServiceUserName = null; remoteServicePassword = null; thriftHost = null; thriftPort = null; reuseSession = null; cacheType = null; invalidationInterval = 0; maxCacheEntries = 0; subjectScope = null; subjectAttributeName = null; authRedirectURL = null; } private String findUserName(HttpServletRequest request, String subjectScope, String subjectAttributeName) throws EntitlementFilterException { String subject; if (subjectScope.equals(EntitlementConstants.SESSION)) { subject = (String) request.getSession(false).getAttribute(subjectAttributeName); } else if (subjectScope.equals(EntitlementConstants.REQUEST_PARAM)) { subject = request.getParameter(subjectAttributeName); } else if (subjectScope.equals(EntitlementConstants.REQUEST_ATTIBUTE)) { subject = (String) request.getAttribute(subjectAttributeName); } else if (subjectScope.equals(EntitlementConstants.BASIC_AUTH)) { EntitlementFilterCallBackHandler callBackHandler = new BasicAuthCallBackHandler(request); subject = callBackHandler.getUserName(); } else { log.error(subjectScope + " is an invalid" + " configuration for subjectScope parameter in web.xml. Valid configurations are" + " \'" + EntitlementConstants.REQUEST_PARAM + "\', " + EntitlementConstants.REQUEST_ATTIBUTE + "\' and \'" + EntitlementConstants.SESSION + "\'"); throw new EntitlementFilterException(subjectScope + " is an invalid" + " configuration for subjectScope parameter in web.xml. Valid configurations are" + " \'" + EntitlementConstants.REQUEST_PARAM + "\', " + EntitlementConstants.REQUEST_ATTIBUTE + "\' and \'" + EntitlementConstants.SESSION + "\'"); } if (subject == null || "null".equals(subject)) { log.error("Username not provided in " + subjectScope); throw new EntitlementFilterException("Username not provided in " + subjectScope); } return subject; } private String findResource(HttpServletRequest request) { return request.getRequestURI(); } private String findAction(HttpServletRequest request) { return request.getMethod(); } private void completeAuthorization(String decision, ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws EntitlementFilterException { try { if (decision.equals(EntitlementConstants.PERMIT)) { if (((HttpServletRequest) servletRequest).getRequestURI().contains("/updateCacheAuth.do")) { pepProxy.clear(); log.info("PEP cache has been updated"); servletResponse.getWriter().print("PEP cache has been updated"); } else { filterChain.doFilter(servletRequest, servletResponse); } } else if (decision.equals(EntitlementConstants.DENY)) { log.debug("User not authorized to perform the action"); servletRequest.getRequestDispatcher(authRedirectURL). forward(servletRequest, servletResponse); } else if (decision.equals(EntitlementConstants.NOT_APPLICABLE)) { log.debug("No applicable policies found"); servletRequest.getRequestDispatcher(authRedirectURL). forward(servletRequest, servletResponse); } else if (decision.equals(EntitlementConstants.INDETERMINATE)) { log.debug("Indeterminate"); servletRequest.getRequestDispatcher(authRedirectURL). forward(servletRequest, servletResponse); } else { log.error("Unrecognized decision returned from PDP"); servletRequest.getRequestDispatcher(authRedirectURL). forward(servletRequest, servletResponse); } } catch (Exception e) { log.error("Error occurred while completing authorization", e); throw new EntitlementFilterException("Error occurred while completing authorization", e); } } }