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.
}