Java tutorial
/* * Copyright 2016 Brigham Young University * * Licensed 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 edu.byu.wso2.apim.extensions; import edu.byu.wso2.apim.extensions.helpers.BYUEntity; import edu.byu.wso2.apim.extensions.helpers.BYUEntityHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.ManagedLifecycle; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseLog; import org.apache.synapse.core.SynapseEnvironment; import org.apache.synapse.mediators.AbstractMediator; import org.springframework.util.AntPathMatcher; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.http.HttpServletRequest; import javax.sql.DataSource; import java.sql.*; import java.util.ArrayList; import java.util.List; /** * Steps to determine if a client can use an actor: * 1) get application id from properties - key value 'applicationid' * 2) get keytype from properties - key value 'keytype' * 3) get usertype from properties - key value 'usertype' - is set to APPLICATION for client credentials grant * 4) query client_id from API Manager database - use property WSO2AMDsName to get the datasource name * 5) call GRO and IAM with client_id and url of the call - REST_FULL_REQUEST_PATH * 6) set ResultPropertyName property with result so sequence can decide what to do. * */ public class CheckActorPermissions extends AbstractMediator implements ManagedLifecycle { private static Log log = LogFactory.getLog(CheckActorPermissions.class); private static String APPLICATION_ID_KEY = "applicationid"; private static String KEYTYPE_KEY = "keytype"; private static String USERTYPE_KEY = "usertype"; private static String CLIENT_ID_KEY = "client_id"; private static String FULL_URL_KEY = "REST_FULL_REQUEST_PATH"; private static String CONTEXT_URL_KEY = "REST_API_CONTEXT"; private SynapseLog synLog = null; private final AntPathMatcher pathMatcher = new AntPathMatcher(); private DataSource proDs = null; private String PRODsName = null; private String resultPropertyName = null; public void init(SynapseEnvironment synapseEnvironment) { if (log.isInfoEnabled()) { log.info("Initializing CheckActorPermissions Mediator"); } if (log.isDebugEnabled()) log.debug("CheckActorPermissions: looking up Person/GRO datasource" + PRODsName); try { this.proDs = (DataSource) new InitialContext().lookup(PRODsName); } catch (NamingException e) { e.printStackTrace(); } if (log.isDebugEnabled()) log.debug("CheckActorPermissions: acquired datasource"); } public boolean mediate(MessageContext synapseContext) { synLog = getLog(synapseContext); if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Start : CheckActorPermissions mediator"); if (synLog.isTraceTraceEnabled()) { synLog.traceTrace("Message : " + synapseContext.getEnvelope()); } } String application_id = (String) synapseContext.getProperty(APPLICATION_ID_KEY); String keytype = (String) synapseContext.getProperty(KEYTYPE_KEY); String target_URL = (String) synapseContext.getProperty(FULL_URL_KEY); String client_id = (String) synapseContext.getProperty(CLIENT_ID_KEY); if (client_id == null) { synLog.error( "Property to use for client_id not set - make sure JWTDecoder class mediator is prior to this one in the sequence and JWT contains BYU custom claims"); return false; } if (synLog.isTraceOrDebugEnabled()) synLog.traceOrDebug("CheckActorPermissions: lookup starting for client_id:" + client_id); if (client_id == null) { synLog.error("Could not get a client_id for the application_id - stopping sequence"); return false; } boolean canUseActor = checkActorPermissionsInGRO(synapseContext, client_id, target_URL); /*need to set the return property to the results of the test */ if (getResultPropertyName() == null) { synLog.error("ResultPropertyName not set - stopping sequence"); return false; } synapseContext.setProperty(getResultPropertyName(), canUseActor); if (log.isDebugEnabled()) synLog.traceOrDebug("CheckActorPermissions: ending"); return true; } public boolean checkActorPermissionsInGRO(MessageContext synapseContext, String client_id, String target_URL) { boolean canUseActor = false; if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Start : CheckActorPermissionsInGRO"); } /* step 1 - check for a service with a matching pattern. This must be done in code - can't match patterns in the db if service doesn't resolve - can't use actors. */ Service service = resolve(target_URL); if (service == null) { if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("no service mapping found - can't use actors"); } return false; } /* step 2 - get person_id associated with the client_id. If there isn't one - can't use actors. */ BYUEntity byuEntity = new BYUEntityHelper(getPRODsName()).getBYUEntityFromConsumerKey(client_id); if (byuEntity == null) { if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("no person_id associated with client_id " + client_id + " - can't use actors"); } return false; } /* step 3 - check to see if the person_id is allowed to access this web service with an actor if count comes back as 0 - can't use actors */ Connection con = null; PreparedStatement statement = null; ResultSet resultSet = null; String query = "select count(*) from gro.person_group g, gro.group_definition d, gro.access_policy p \n" + "where g.group_id = d.group_api \n" + "and d.group_definition_id = p.group_definition_id \n" + "and p.WEB_SERVICE_ID = ? \n" + "and p.policy_type = 'Provider' \n" + "and g.person_id = ?"; if (synLog.isTraceOrDebugEnabled()) synLog.traceOrDebug("CheckActorPermissionsInGRO: lookup starting for person_id " + byuEntity.getPersonId() + " and web service " + service.toString()); try { con = proDs.getConnection(); if (synLog.isTraceOrDebugEnabled()) synLog.traceOrDebug("connection acquired. creating statement and executing query"); statement = con.prepareStatement(query); statement.setLong(1, service.getWebServiceId()); statement.setString(2, byuEntity.getPersonId()); resultSet = statement.executeQuery(); if (resultSet.next()) { if (resultSet.getInt(1) > 0) if (synLog.isTraceOrDebugEnabled()) synLog.traceOrDebug("client_id authorization succeeded"); canUseActor = true; } else { if (synLog.isTraceOrDebugEnabled()) synLog.traceOrDebug("client_id authorization failed"); canUseActor = false; } } catch (SQLException e) { e.printStackTrace(); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { /* ignored */ } } if (statement != null) { try { statement.close(); } catch (SQLException e) { /* ignored */ } } if (con != null) { try { con.close(); } catch (SQLException e) { /* ignored */ } } } if (synLog.isTraceOrDebugEnabled()) synLog.traceOrDebug("CheckActorPermissionsInGRO: ending with value - " + String.valueOf(canUseActor)); return canUseActor; } public Service resolve(String requestUrl) { final List<Service> services = getServices(); for (Service serviceDefinition : services) { if (pathMatcher.match(serviceDefinition.getUrlPattern(), requestUrl)) { return serviceDefinition; } } return null; } private List<Service> getServices() { if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Start : getServices"); } List<Service> serviceList = new ArrayList<Service>(); Connection con = null; PreparedStatement statement = null; ResultSet resultSet = null; String query = "select web_service_id, url_pattern from common.web_service order by url_pattern"; if (synLog.isTraceOrDebugEnabled()) synLog.traceOrDebug("getServices: retrieving web services with url patterns from common.web_service"); try { con = proDs.getConnection(); if (synLog.isTraceOrDebugEnabled()) synLog.traceOrDebug("connection acquired. creating statement and executing query"); statement = con.prepareStatement(query); resultSet = statement.executeQuery(); while (resultSet.next()) { serviceList .add(new Service(resultSet.getLong("web_service_id"), resultSet.getString("url_pattern"))); } } catch (SQLException e) { e.printStackTrace(); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { /* ignored */ } } if (statement != null) { try { statement.close(); } catch (SQLException e) { /* ignored */ } } if (con != null) { try { con.close(); } catch (SQLException e) { /* ignored */ } } } if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("getService: ending"); } return serviceList; } public void destroy() { if (log.isInfoEnabled()) { log.info("Destroying CheckActorPermissions Mediator"); } } /* DataSource name to use for lookup */ public String getPRODsName() { return PRODsName; } public void setPRODsName(String PRODsName) { this.PRODsName = PRODsName; } public String getResultPropertyName() { return resultPropertyName; } public void setResultPropertyName(String resultPropertyName) { this.resultPropertyName = resultPropertyName; } }