Repository: incubator-unomi Updated Branches: refs/heads/UNOMI-14 73a6c0fa4 -> 209efd568
UNOMI-15 : Use token to authenticate third party servers Project: http://git-wip-us.apache.org/repos/asf/incubator-unomi/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-unomi/commit/209efd56 Tree: http://git-wip-us.apache.org/repos/asf/incubator-unomi/tree/209efd56 Diff: http://git-wip-us.apache.org/repos/asf/incubator-unomi/diff/209efd56 Branch: refs/heads/UNOMI-14 Commit: 209efd568732502300b346855e043d16e4f5d382 Parents: 73a6c0f Author: Thomas Draier <[email protected]> Authored: Wed Feb 3 14:32:19 2016 +0100 Committer: Thomas Draier <[email protected]> Committed: Wed Feb 3 14:32:19 2016 +0100 ---------------------------------------------------------------------- .../apache/unomi/api/services/EventService.java | 14 ++++ kar/src/main/feature/feature.xml | 1 + services/pom.xml | 7 ++ .../services/services/EventServiceImpl.java | 71 ++++++++++++++++++-- .../services/services/ThirdPartyServer.java | 67 ++++++++++++++++++ .../resources/OSGI-INF/blueprint/blueprint.xml | 14 +++- .../resources/org.apache.unomi.thirdparty.cfg | 20 ++++++ .../org/apache/unomi/web/ContextServlet.java | 24 +++++-- .../unomi/web/EventsCollectorServlet.java | 13 ++-- .../resources/OSGI-INF/blueprint/blueprint.xml | 1 + 10 files changed, 213 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/api/src/main/java/org/apache/unomi/api/services/EventService.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/unomi/api/services/EventService.java b/api/src/main/java/org/apache/unomi/api/services/EventService.java index fe81130..5e74e83 100644 --- a/api/src/main/java/org/apache/unomi/api/services/EventService.java +++ b/api/src/main/java/org/apache/unomi/api/services/EventService.java @@ -56,6 +56,20 @@ public interface EventService { int send(Event event); /** + * Check if the sender is allowed to sent the speecified event. Restricted event must be explicitely allowed for a sender. + * @param event + * @param thirdPartyId + * @return + */ + boolean isEventAllowed(Event event, String thirdPartyId); + + /** + * Get the third party server name, if the request is originated from a known peer + * @return + */ + String authenticateThirdPartyServer(String key, String ip); + + /** * Retrieves the list of available event properties. * * @return a list of available event properties http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/kar/src/main/feature/feature.xml ---------------------------------------------------------------------- diff --git a/kar/src/main/feature/feature.xml b/kar/src/main/feature/feature.xml index 72e3e7f..5e63b8b 100644 --- a/kar/src/main/feature/feature.xml +++ b/kar/src/main/feature/feature.xml @@ -27,6 +27,7 @@ <configfile finalname="/etc/org.apache.unomi.persistence.elasticsearch.cfg">mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version}/cfg/elasticsearchcfg</configfile> <configfile finalname="/etc/org.apache.unomi.plugins.request.cfg">mvn:org.apache.unomi/unomi-plugins-request/${project.version}/cfg/requestcfg</configfile> <configfile finalname="/etc/org.apache.unomi.services.cfg">mvn:org.apache.unomi/unomi-services/${project.version}/cfg/servicescfg</configfile> + <configfile finalname="/etc/org.apache.unomi.thirdparty.cfg">mvn:org.apache.unomi/unomi-services/${project.version}/cfg/thirdpartycfg</configfile> <configfile finalname="/etc/org.apache.unomi.geonames.cfg">mvn:org.apache.unomi/cxs-geonames-services/${project.version}/cfg/geonamescfg</configfile> <configfile finalname="/etc/elasticsearch.yml">mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version}/yml/elasticsearchconfig</configfile> <bundle start-level="75">mvn:commons-io/commons-io/2.4</bundle> http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/services/pom.xml ---------------------------------------------------------------------- diff --git a/services/pom.xml b/services/pom.xml index ea3efce..03fd7b7 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -174,6 +174,13 @@ <type>cfg</type> <classifier>servicescfg</classifier> </artifact> + <artifact> + <file> + src/main/resources/org.apache.unomi.thirdparty.cfg + </file> + <type>cfg</type> + <classifier>thirdpartycfg</classifier> + </artifact> </artifacts> </configuration> </execution> http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java index 4b207d9..22cdcda 100644 --- a/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java @@ -24,38 +24,72 @@ import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.api.services.DefinitionsService; import org.apache.unomi.api.services.EventListenerService; import org.apache.unomi.api.services.EventService; -import org.apache.unomi.api.services.ProfileService; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.*; public class EventServiceImpl implements EventService { + private static final Logger logger = LoggerFactory.getLogger(SegmentServiceImpl.class.getName()); private List<EventListenerService> eventListeners = new ArrayList<EventListenerService>(); private PersistenceService persistenceService; - private ProfileService profileService; - private DefinitionsService definitionsService; private BundleContext bundleContext; private Set<String> predefinedEventTypeIds = new LinkedHashSet<String>(); + private Set<String> restrictedEventTypeIds = new LinkedHashSet<String>(); + + private Map<String, ThirdPartyServer> thirdPartyServers = new HashMap<>(); + + public void setThirdPartyConfiguration(Map<String,String> thirdPartyConfiguration) { + this.thirdPartyServers = new HashMap<>(); + for (Map.Entry<String, String> entry : thirdPartyConfiguration.entrySet()) { + String[] keys = StringUtils.split(entry.getKey(),'.'); + if (keys[0].equals("thirdparty")) { + if (!thirdPartyServers.containsKey(keys[1])) { + thirdPartyServers.put(keys[1], new ThirdPartyServer(keys[1])); + } + ThirdPartyServer thirdPartyServer = thirdPartyServers.get(keys[1]); + if (keys[2].equals("allowedEvents")) { + thirdPartyServer.setAllowedEvents(new HashSet<>(Arrays.asList(StringUtils.split(entry.getValue(), ',')))); + } else if (keys[2].equals("key")) { + thirdPartyServer.setKey(entry.getValue()); + } else if (keys[2].equals("ipAddresses")) { + Set<InetAddress> inetAddresses = new HashSet<>(); + for (String ip : StringUtils.split(entry.getValue(), ',')) { + try { + inetAddresses.add(InetAddress.getByName(ip)); + } catch (UnknownHostException e) { + logger.error("Cannot resolve address",e); + } + } + thirdPartyServer.setIpAddresses(inetAddresses); + } + } + } + } + public void setPredefinedEventTypeIds(Set<String> predefinedEventTypeIds) { this.predefinedEventTypeIds = predefinedEventTypeIds; } - public void setPersistenceService(PersistenceService persistenceService) { - this.persistenceService = persistenceService; + public void setRestrictedEventTypeIds(Set<String> restrictedEventTypeIds) { + this.restrictedEventTypeIds = restrictedEventTypeIds; } - public void setProfileService(ProfileService profileService) { - this.profileService = profileService; + public void setPersistenceService(PersistenceService persistenceService) { + this.persistenceService = persistenceService; } public void setDefinitionsService(DefinitionsService definitionsService) { @@ -66,6 +100,29 @@ public class EventServiceImpl implements EventService { this.bundleContext = bundleContext; } + public boolean isEventAllowed(Event event, String thirdPartyId) { + if (restrictedEventTypeIds.contains(event.getEventType())) { + return thirdPartyServers.containsKey(thirdPartyId) && thirdPartyServers.get(thirdPartyId).getAllowedEvents().contains(event.getEventType()); + } + return true; + } + + public String authenticateThirdPartyServer(String key, String ip) { + if (key != null) { + for (Map.Entry<String, ThirdPartyServer> entry : thirdPartyServers.entrySet()) { + ThirdPartyServer server = entry.getValue(); + try { + if (server.getKey().equals(key) && server.getIpAddresses().contains(InetAddress.getByName(ip))) { + return server.getId(); + } + } catch (UnknownHostException e) { + logger.error("Cannot resolve address",e); + } + } + } + return null; + } + public int send(Event event) { if (event.isPersistent()) { persistenceService.save(event); http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/services/src/main/java/org/apache/unomi/services/services/ThirdPartyServer.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/ThirdPartyServer.java b/services/src/main/java/org/apache/unomi/services/services/ThirdPartyServer.java new file mode 100644 index 0000000..c4587d7 --- /dev/null +++ b/services/src/main/java/org/apache/unomi/services/services/ThirdPartyServer.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.unomi.services.services; + +import java.net.InetAddress; +import java.util.HashSet; +import java.util.Set; + +/** + * Representation of a third party server, containing key, ip address, and allowed events + */ +public class ThirdPartyServer { + private String id; + + private String key; + + private Set<InetAddress> ipAddresses; + + private Set<String> allowedEvents = new HashSet<>(); + + public ThirdPartyServer(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public String getKey() { + return key; + } + + public Set<InetAddress> getIpAddresses() { + return ipAddresses; + } + + public Set<String> getAllowedEvents() { + return allowedEvents; + } + + public void setKey(String key) { + this.key = key; + } + + public void setIpAddresses(Set<InetAddress> ipAddresses) { + this.ipAddresses = ipAddresses; + } + + public void setAllowedEvents(Set<String> allowedEvents) { + this.allowedEvents = allowedEvents; + } +} http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml ---------------------------------------------------------------------- diff --git a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 7d3bc87..2af329c 100644 --- a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -46,7 +46,6 @@ <bean id="eventServiceImpl" class="org.apache.unomi.services.services.EventServiceImpl"> <property name="persistenceService" ref="persistenceService"/> - <property name="profileService" ref="profileServiceImpl"/> <property name="definitionsService" ref="definitionsServiceImpl"/> <property name="bundleContext" ref="blueprintBundleContext"/> <property name="predefinedEventTypeIds"> @@ -58,6 +57,19 @@ <value>profileUpdated</value> </set> </property> + <property name="restrictedEventTypeIds"> + <set> + <value>login</value> + <value>facebookLogin</value> + <value>sessionCreated</value> + <value>sessionReassigned</value> + <value>profileUpdated</value> + <value>ruleFired</value> + </set> + </property> + <property name="thirdPartyConfiguration"> + <cm:cm-properties persistent-id="org.apache.unomi.thirdparty" update="true" /> + </property> </bean> <service id="eventService" ref="eventServiceImpl" auto-export="interfaces"/> http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/services/src/main/resources/org.apache.unomi.thirdparty.cfg ---------------------------------------------------------------------- diff --git a/services/src/main/resources/org.apache.unomi.thirdparty.cfg b/services/src/main/resources/org.apache.unomi.thirdparty.cfg new file mode 100644 index 0000000..06c3278 --- /dev/null +++ b/services/src/main/resources/org.apache.unomi.thirdparty.cfg @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF 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. +# + +thirdparty.jahia.key=670c26d1cc413346c3b2fd9ce65dab41 +thirdparty.jahia.ipAddresses=127.0.0.1,::1 +thirdparty.jahia.allowedEvents=login,download http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/wab/src/main/java/org/apache/unomi/web/ContextServlet.java ---------------------------------------------------------------------- diff --git a/wab/src/main/java/org/apache/unomi/web/ContextServlet.java b/wab/src/main/java/org/apache/unomi/web/ContextServlet.java index 2e43302..5b8b333 100644 --- a/wab/src/main/java/org/apache/unomi/web/ContextServlet.java +++ b/wab/src/main/java/org/apache/unomi/web/ContextServlet.java @@ -23,6 +23,7 @@ import org.apache.commons.io.IOUtils; import org.apache.unomi.api.*; import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.api.services.EventService; +import org.apache.unomi.api.services.PrivacyService; import org.apache.unomi.api.services.ProfileService; import org.apache.unomi.api.services.RulesService; import org.apache.unomi.persistence.spi.CustomObjectMapper; @@ -53,6 +54,7 @@ public class ContextServlet extends HttpServlet { private ProfileService profileService; private EventService eventService; private RulesService rulesService; + private PrivacyService privacyService; private String profileIdCookieName = "context-profile-id"; private String profileIdCookieDomain; @@ -253,17 +255,25 @@ public class ContextServlet extends HttpServlet { private int handleRequest(ContextRequest contextRequest, Profile profile, Session session, ContextResponse data, ServletRequest request, ServletResponse response, Date timestamp) throws IOException { + List<String> filteredEventTypes = privacyService.getFilteredEventTypes(profile.getItemId()); + + String thirdPartyId = eventService.authenticateThirdPartyServer(((HttpServletRequest)request).getHeader("X-Unomi-Peer"), request.getRemoteAddr()); + int changes = EventService.NO_CHANGE; // execute provided events if any if(contextRequest.getEvents() != null && !(profile instanceof Persona)) { for (Event event : contextRequest.getEvents()){ if(event.getEventType() != null) { - Event eventToSend; - if(event.getProperties() != null){ - eventToSend = new Event(event.getEventType(), session, profile, contextRequest.getSource().getScope(), event.getSource(), event.getTarget(), event.getProperties(), timestamp); - } else { - eventToSend = new Event(event.getEventType(), session, profile, contextRequest.getSource().getScope(), event.getSource(), event.getTarget(), timestamp); + Event eventToSend = new Event(event.getEventType(), session, profile, contextRequest.getSource().getScope(), event.getSource(), event.getTarget(), event.getProperties(), timestamp); + if (!eventService.isEventAllowed(event, thirdPartyId)) { + logger.debug("Event is not allowed : {}", event.getEventType()); + continue; + } + if (filteredEventTypes != null && filteredEventTypes.contains(event.getEventType())) { + logger.debug("Profile is filtering event type {}", event.getEventType()); + continue; } + event.getAttributes().put(Event.HTTP_REQUEST_ATTRIBUTE, request); event.getAttributes().put(Event.HTTP_RESPONSE_ATTRIBUTE, response); logger.debug("Received event " + event.getEventType() + " for profile=" + profile.getItemId() + " session=" + session.getItemId() + " target=" + event.getTarget() + " timestamp=" + timestamp); @@ -365,4 +375,8 @@ public class ContextServlet extends HttpServlet { public void setProfileIdCookieDomain(String profileIdCookieDomain) { this.profileIdCookieDomain = profileIdCookieDomain; } + + public void setPrivacyService(PrivacyService privacyService) { + this.privacyService = privacyService; + } } http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java ---------------------------------------------------------------------- diff --git a/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java b/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java index c34ead2..24aa727 100644 --- a/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java +++ b/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java @@ -35,6 +35,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import java.util.List; +import java.util.Map; public class EventsCollectorServlet extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(EventsCollectorServlet.class.getName()); @@ -130,16 +131,16 @@ public class EventsCollectorServlet extends HttpServlet { return; } + String thirdPartyId = eventService.authenticateThirdPartyServer(((HttpServletRequest)request).getHeader("X-Unomi-Peer"), request.getRemoteAddr()); + int changes = 0; for (Event event : events.getEvents()){ if(event.getEventType() != null){ - Event eventToSend; - if(event.getProperties() != null){ - eventToSend = new Event(event.getEventType(), session, profile, event.getScope(), event.getSource(), event.getTarget(), event.getProperties(), timestamp); - } else { - eventToSend = new Event(event.getEventType(), session, profile, event.getScope(), event.getSource(), event.getTarget(), timestamp); + Event eventToSend = new Event(event.getEventType(), session, profile, event.getScope(), event.getSource(), event.getTarget(), event.getProperties(), timestamp); + if (!eventService.isEventAllowed(event, thirdPartyId)) { + logger.debug("Event is not allowed : {}", event.getEventType()); + continue; } - if (filteredEventTypes != null && filteredEventTypes.contains(event.getEventType())) { logger.debug("Profile is filtering event type {}", event.getEventType()); continue; http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/209efd56/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml ---------------------------------------------------------------------- diff --git a/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml index eab2e9a..6103121 100644 --- a/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -38,6 +38,7 @@ <property name="profileService" ref="profileService"/> <property name="eventService" ref="eventService"/> <property name="rulesService" ref="rulesService"/> + <property name="privacyService" ref="privacyService" /> <property name="profileIdCookieDomain" value="${web.contextserver.domain}" /> </bean>
