You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by sh...@apache.org on 2020/11/04 14:17:32 UTC

[unomi] 02/02: Adjust backport of security fix

This is an automated email from the ASF dual-hosted git repository.

shuber pushed a commit to branch unomi-1.4.x
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit 157b0f084b35a0546d97624f550c9bb24b2c7a35
Author: Serge Huber <sh...@jahia.com>
AuthorDate: Wed Nov 4 15:16:51 2020 +0100

    Adjust backport of security fix
---
 .../test/java/org/apache/unomi/itests/BaseIT.java  |   2 +
 .../org/apache/unomi/itests/ContextServletIT.java  | 222 ---------------------
 .../java/org/apache/unomi/itests/TestUtils.java    |  58 +++++-
 .../conditions/PropertyConditionEvaluatorTest.java |   4 +-
 4 files changed, 57 insertions(+), 229 deletions(-)

diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index d84660a..491b3f3 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -31,8 +31,10 @@ import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
 import org.ops4j.pax.exam.options.MavenArtifactUrlReference;
 import org.ops4j.pax.exam.options.MavenUrlReference;
+import org.ops4j.pax.exam.util.Filter;
 import org.osgi.framework.BundleContext;
 
+import javax.inject.Inject;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
diff --git a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
index 812f36c..b47bd4d 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
@@ -121,228 +121,6 @@ public class ContextServletIT extends BaseIT {
 		segmentService.removeSegmentDefinition(SEGMENT_ID,false);
 	}
 
-	@Test
-	public void testUpdateEventFromContextAuthorizedThirdParty_Success() throws IOException, InterruptedException {
-		//Arrange
-		String eventId = "test-event-id1";
-		String profileId = "test-profile-id";
-		String sessionId = "test-session-id";
-		String scope = "test-scope";
-		String eventTypeOriginal = "test-event-type-original";
-		String eventTypeUpdated = "test-event-type-updated";
-		Profile profile = new Profile(profileId);
-		Session session = new Session(sessionId, profile, new Date(), scope);
-		Event event = new Event(eventId, eventTypeOriginal, session, profile, scope, null, null, new Date());
-		profileService.save(profile);
-		this.eventService.send(event);
-		refreshPersistence();
-		Thread.sleep(2000);
-		event.setEventType(eventTypeUpdated); //change the event so we can see the update effect
-
-		//Act
-		ContextRequest contextRequest = new ContextRequest();
-		contextRequest.setSessionId(session.getItemId());
-		contextRequest.setEvents(Arrays.asList(event));
-		HttpPost request = new HttpPost(URL + CONTEXT_URL);
-		request.addHeader(THIRD_PARTY_HEADER_NAME, UNOMI_KEY);
-		request.setEntity(new StringEntity(objectMapper.writeValueAsString(contextRequest), ContentType.create("application/json")));
-		TestUtils.executeContextJSONRequest(request, sessionId);
-		refreshPersistence();
-		Thread.sleep(2000); //Making sure event is updated in DB
-
-		//Assert
-		event = this.eventService.getEvent(eventId);
-		assertEquals(2, event.getVersion().longValue());
-		assertEquals(eventTypeUpdated,event.getEventType());
-	}
-
-	@Test
-	public void testUpdateEventFromContextUnAuthorizedThirdParty_Fail() throws IOException, InterruptedException {
-		//Arrange
-		String eventId = "test-event-id2";
-		String profileId = "test-profile-id";
-		String sessionId = "test-session-id";
-		String scope = "test-scope";
-		String eventTypeOriginal = "test-event-type-original";
-		String eventTypeUpdated = "test-event-type-updated";
-		Profile profile = new Profile(profileId);
-		Session session = new Session(sessionId, profile, new Date(), scope);
-		Event event = new Event(eventId, eventTypeOriginal, session, profile, scope, null, null, new Date());
-		profileService.save(profile);
-		this.eventService.send(event);
-		refreshPersistence();
-		Thread.sleep(2000);
-		event.setEventType(eventTypeUpdated); //change the event so we can see the update effect
-
-		//Act
-		ContextRequest contextRequest = new ContextRequest();
-		contextRequest.setSessionId(session.getItemId());
-		contextRequest.setEvents(Arrays.asList(event));
-		HttpPost request = new HttpPost(URL + CONTEXT_URL);
-		request.setEntity(new StringEntity(objectMapper.writeValueAsString(contextRequest), ContentType.create("application/json")));
-		TestUtils.executeContextJSONRequest(request, sessionId);
-		refreshPersistence();
-		Thread.sleep(2000); //Making sure event is updated in DB
-
-		//Assert
-		event = this.eventService.getEvent(eventId);
-		assertEquals(1, event.getVersion().longValue());
-		assertEquals(eventTypeOriginal,event.getEventType());
-	}
-
-
-	@Test
-	public void testUpdateEventFromContextAuthorizedThirdPartyNoItemID_Fail() throws IOException, InterruptedException {
-		//Arrange
-		String eventId = "test-event-id3";
-		String sessionId = "test-session-id";
-		String scope = "test-scope";
-		String eventTypeOriginal = "test-event-type-original";
-		String eventTypeUpdated = "test-event-type-updated";
-		Session session = new Session(sessionId, profile, new Date(), scope);
-		Event event = new Event(eventId, eventTypeOriginal, session, profile, scope, null, null, new Date());
-		this.eventService.send(event);
-		refreshPersistence();
-		Thread.sleep(2000);
-		event.setEventType(eventTypeUpdated); //change the event so we can see the update effect
-
-		//Act
-		ContextRequest contextRequest = new ContextRequest();
-		contextRequest.setSessionId(session.getItemId());
-		contextRequest.setEvents(Arrays.asList(event));
-		HttpPost request = new HttpPost(URL + CONTEXT_URL);
-		request.setEntity(new StringEntity(objectMapper.writeValueAsString(contextRequest), ContentType.create("application/json")));
-		TestUtils.executeContextJSONRequest(request, sessionId);
-		refreshPersistence();
-		Thread.sleep(2000); //Making sure event is updated in DB
-
-		//Assert
-		event = this.eventService.getEvent(eventId);
-		assertEquals(1, event.getVersion().longValue());
-		assertEquals(eventTypeOriginal,event.getEventType());
-	}
-
-	@Test
-	public void testCreateEventsWithNoTimestampParam_profileAddedToSegment() throws IOException, InterruptedException {
-		//Arrange
-		String sessionId = "test-session-id";
-		String scope = "test-scope";
-		Event event = new Event();
-		event.setEventType(SEGMENT_EVENT_TYPE);
-		event.setScope(scope);
-
-		//Act
-		ContextRequest contextRequest = new ContextRequest();
-		contextRequest.setSessionId(sessionId);
-		contextRequest.setRequireSegments(true);
-		contextRequest.setEvents(Arrays.asList(event));
-		HttpPost request = new HttpPost(URL + CONTEXT_URL);
-		request.setEntity(new StringEntity(objectMapper.writeValueAsString(contextRequest), ContentType.create("application/json")));
-		String cookieHeaderValue = TestUtils.executeContextJSONRequest(request, sessionId).getCookieHeaderValue();
-		refreshPersistence();
-		Thread.sleep(1000); //Making sure DB is updated
-
-		//Add the context-profile-id cookie to the second event
-		request.addHeader("Cookie", cookieHeaderValue);
-		ContextResponse response = (TestUtils.executeContextJSONRequest(request, sessionId)).getContextResponse(); //second event
-
-		refreshPersistence();
-
-		//Assert
-		assertEquals(1, response.getProfileSegments().size());
-		assertThat(response.getProfileSegments(),hasItem(SEGMENT_ID));
-	}
-
-	@Test
-	public void testCreateEventWithTimestampParam_pastEvent_profileIsNotAddedToSegment() throws IOException, InterruptedException {
-		//Arrange
-		String sessionId = "test-session-id";
-		String scope = "test-scope";
-		Event event = new Event();
-		event.setEventType(SEGMENT_EVENT_TYPE);
-		event.setScope(scope);
-		String regularURI = URL + CONTEXT_URL;
-		long oldTimestamp = LocalDateTime.now(ZoneId.of("UTC")).minusDays(SEGMENT_NUMBER_OF_DAYS + 1).toInstant(ZoneOffset.UTC).toEpochMilli();
-		String customTimestampURI = regularURI + "?timestamp=" + oldTimestamp;
-
-		//Act
-		ContextRequest contextRequest = new ContextRequest();
-		contextRequest.setSessionId(sessionId);
-		contextRequest.setRequireSegments(true);
-		contextRequest.setEvents(Arrays.asList(event));
-		HttpPost request = new HttpPost(regularURI);
-		request.setEntity(new StringEntity(objectMapper.writeValueAsString(contextRequest), ContentType.create("application/json")));
-		//The first event is with a default timestamp (now)
-		String cookieHeaderValue = TestUtils.executeContextJSONRequest(request, sessionId).getCookieHeaderValue();
-		refreshPersistence();
-		//The second event is with a customized timestamp
-		request.setURI(URI.create(customTimestampURI));
-		request.addHeader("Cookie", cookieHeaderValue);
-		ContextResponse response = (TestUtils.executeContextJSONRequest(request, sessionId)).getContextResponse(); //second event
-		refreshPersistence();
-
-		//Assert
-		assertEquals(0,response.getProfileSegments().size());
-	}
-
-	@Test
-	public void testCreateEventWithTimestampParam_futureEvent_profileIsNotAddedToSegment() throws IOException, InterruptedException {
-		//Arrange
-		String sessionId = "test-session-id";
-		String scope = "test-scope";
-		Event event = new Event();
-		event.setEventType(SEGMENT_EVENT_TYPE);
-		event.setScope(scope);
-		String regularURI = URL + CONTEXT_URL;
-		long futureTimestamp = LocalDateTime.now(ZoneId.of("UTC")).plusDays(1).toInstant(ZoneOffset.UTC).toEpochMilli();
-		String customTimestampURI = regularURI + "?timestamp=" + futureTimestamp;
-
-		//Act
-		ContextRequest contextRequest = new ContextRequest();
-		contextRequest.setSessionId(sessionId);
-		contextRequest.setRequireSegments(true);
-		contextRequest.setEvents(Arrays.asList(event));
-		HttpPost request = new HttpPost(regularURI);
-		request.setEntity(new StringEntity(objectMapper.writeValueAsString(contextRequest), ContentType.create("application/json")));
-		//The first event is with a default timestamp (now)
-		String cookieHeaderValue = TestUtils.executeContextJSONRequest(request, sessionId).getCookieHeaderValue();
-		refreshPersistence();
-		//The second event is with a customized timestamp
-		request.setURI(URI.create(customTimestampURI));
-		request.addHeader("Cookie", cookieHeaderValue);
-		ContextResponse response = (TestUtils.executeContextJSONRequest(request, sessionId)).getContextResponse(); //second event
-		refreshPersistence();
-
-		//Assert
-		assertEquals(0,response.getProfileSegments().size());
-	}
-
-	@Test
-	public void testCreateEventWithProfileId_Success() throws IOException, InterruptedException {
-		//Arrange
-		String eventId = "test-event-id4";
-		String profileId = "test-profile-id";
-		String eventType = "test-event-type";
-		Event event = new Event();
-		event.setEventType(eventType);
-		event.setItemId(eventId);
-
-		ContextRequest contextRequest = new ContextRequest();
-		contextRequest.setProfileId(profileId);
-		contextRequest.setEvents(Arrays.asList(event));
-
-		//Act
-		HttpPost request = new HttpPost(URL + CONTEXT_URL);
-		request.addHeader(THIRD_PARTY_HEADER_NAME, UNOMI_KEY);
-		request.setEntity(new StringEntity(objectMapper.writeValueAsString(contextRequest), ContentType.create("application/json")));
-		TestUtils.executeContextJSONRequest(request);
-		refreshPersistence();
-		Thread.sleep(2000); //Making sure event is updated in DB
-
-		//Assert
-		Profile profile =  this.profileService.load(profileId);
-		assertEquals(profileId, profile.getItemId());
-	}
 
 	@Test
 	public void testOGNLVulnerability() throws IOException, InterruptedException {
diff --git a/itests/src/test/java/org/apache/unomi/itests/TestUtils.java b/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
index 066adbd..5e385f5 100644
--- a/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
+++ b/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
@@ -18,6 +18,7 @@
 package org.apache.unomi.itests;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpPost;
@@ -25,13 +26,22 @@ import org.apache.http.entity.ContentType;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.util.EntityUtils;
 import org.apache.unomi.api.ContextResponse;
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.Session;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.services.DefinitionsService;
 import org.apache.unomi.persistence.spi.CustomObjectMapper;
+import org.apache.unomi.persistence.spi.PersistenceService;
 import org.junit.Assert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 
 public class TestUtils {
 	private static final String JSON_MYME_TYPE = "application/json";
+	private final static Logger LOGGER = LoggerFactory.getLogger(TestUtils.class);
 
 	public static <T> T retrieveResourceFromResponse(HttpResponse response, Class<T> clazz) throws IOException {
 		if (response == null) {
@@ -47,24 +57,31 @@ public class TestUtils {
 			T value = mapper.readValue(jsonFromResponse, clazz);
 			return value;
 		} catch (Throwable t) {
+			LOGGER.error("Error parsing response JSON", t);
 			t.printStackTrace();
 		}
 		return null;
 	}
 
-	public RequestResponse executeContextJSONRequest(HttpPost request, String sessionId) throws IOException {
+	public static RequestResponse executeContextJSONRequest(HttpPost request, String sessionId) throws IOException {
 		try (CloseableHttpResponse response = HttpClientBuilder.create().build().execute(request)) {
 			// validate mimeType
-			String mimeType = ContentType.getOrDefault(response.getEntity()).getMimeType();
+			HttpEntity entity = response.getEntity();
+			String mimeType = ContentType.getOrDefault(entity).getMimeType();
+			if (!JSON_MYME_TYPE.equals(mimeType)) {
+				String entityContent = EntityUtils.toString(entity);
+				LOGGER.warn("Invalid response: " + entityContent);
+			}
 			Assert.assertEquals("Response content type should be " + JSON_MYME_TYPE, JSON_MYME_TYPE, mimeType);
 
 			// validate context
 			ContextResponse context = TestUtils.retrieveResourceFromResponse(response, ContextResponse.class);
 			Assert.assertNotNull("Context should not be null", context);
 			Assert.assertNotNull("Context profileId should not be null", context.getProfileId());
-			Assert.assertEquals("Context sessionId should be the same as the sessionId used to request the context", sessionId,
-				context.getSessionId());
-
+			if (sessionId != null) {
+				Assert.assertEquals("Context sessionId should be the same as the sessionId used to request the context", sessionId,
+						context.getSessionId());
+			}
 			String cookieHeader = null;
 			if (response.containsHeader("Set-Cookie")) {
 				cookieHeader = response.getHeaders("Set-Cookie")[0].toString().substring(12);
@@ -73,6 +90,37 @@ public class TestUtils {
 		}
 	}
 
+	public static RequestResponse executeContextJSONRequest(HttpPost request) throws IOException {
+		return executeContextJSONRequest(request, null);
+	}
+
+	public static boolean removeAllProfiles(DefinitionsService definitionsService, PersistenceService persistenceService) {
+		Condition condition = new Condition(definitionsService.getConditionType("profilePropertyCondition"));
+		condition.setParameter("propertyName","itemType");
+		condition.setParameter("comparisonOperator","equals");
+		condition.setParameter("propertyValue","profile");
+
+		return persistenceService.removeByQuery(condition, Profile.class);
+	}
+
+	public static boolean removeAllEvents(DefinitionsService definitionsService, PersistenceService persistenceService) {
+		Condition condition = new Condition(definitionsService.getConditionType("eventPropertyCondition"));
+		condition.setParameter("propertyName","itemType");
+		condition.setParameter("comparisonOperator","equals");
+		condition.setParameter("propertyValue","event");
+
+		return persistenceService.removeByQuery(condition, Event.class);
+	}
+
+	public static boolean removeAllSessions(DefinitionsService definitionsService, PersistenceService persistenceService) {
+		Condition condition = new Condition(definitionsService.getConditionType("sessionPropertyCondition"));
+		condition.setParameter("propertyName","itemType");
+		condition.setParameter("comparisonOperator","equals");
+		condition.setParameter("propertyValue","session");
+
+		return persistenceService.removeByQuery(condition, Session.class);
+	}
+
 	public static class RequestResponse {
 		private ContextResponse contextResponse;
 		private String cookieHeaderValue;
diff --git a/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluatorTest.java b/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluatorTest.java
index a9bbf88..6dd4b8b 100644
--- a/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluatorTest.java
+++ b/plugins/baseplugin/src/test/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluatorTest.java
@@ -161,9 +161,9 @@ public class PropertyConditionEvaluatorTest {
             // we ignore these exceptions as they are expected.
         }
         vulnFile = new File("target/vuln-file.txt");
-        assertFalse("Vulnerability successfully executed ! File created at " + vulnFileCanonicalPath, vulnFile.exists());
+        assertFalse("Vulnerability successfully executed ! File created at " + vulnFile.getCanonicalPath(), vulnFile.exists());
         try {
-            propertyConditionEvaluator.getOGNLPropertyValue(mockEvent, "(#runtimeclass = #this.getClass().forName(\"java.lang.Runtime\")).(#getruntimemethod = #runtimeclass.getDeclaredMethods().{^ #this.name.equals(\"getRuntime\")}[0]).(#rtobj = #getruntimemethod.invoke(null,null)).(#execmethod = #runtimeclass.getDeclaredMethods().{? #this.name.equals(\"exec\")}.{? #this.getParameters()[0].getType().getName().equals(\"java.lang.String\")}.{? #this.getParameters().length < 2}[0]).(#execme [...]
+            propertyConditionEvaluator.getOGNLPropertyValue(mockEvent, "(#runtimeclass = #this.getClass().forName(\"java.lang.Runtime\")).(#getruntimemethod = #runtimeclass.getDeclaredMethods().{^ #this.name.equals(\"getRuntime\")}[0]).(#rtobj = #getruntimemethod.invoke(null,null)).(#execmethod = #runtimeclass.getDeclaredMethods().{? #this.name.equals(\"exec\")}.{? #this.getParameters()[0].getType().getName().equals(\"java.lang.String\")}.{? #this.getParameters().length < 2}[0]).(#execme [...]
         } catch (RuntimeException | MethodFailedException re) {
             // we ignore these exceptions as they are expected.
         }