Skip to content

Commit

Permalink
Secure the subscription passwords (#543)
Browse files Browse the repository at this point in the history
* Missing the encryption of the passwords when updating the subscription.

Fixed the issue by encrypting the passwords when updation of the subscription.
Also updated the code not to print the passwords in debug logs.

* Update main.yml

updated the main.yml to trigger local changes

* Revert the change to enable only for community branch

* Revert work flow changes

* Missing the encryption of the passwords when updating the subscription.

Fixed the issue by encrypting the passwords when updation of the subscription.
Also updated the code not to print the passwords in debug logs.

* Update main.yml

updated the main.yml to trigger local changes

* Revert the change to enable only for community branch

* Revert work flow changes

* Rebase master

* Added Nidhi changes for testcases

---------

Co-authored-by: Raju Beemreddy <[email protected]>
Co-authored-by: Dhruvin Kalavadia (EXT) <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jainad Chinta <[email protected]>
  • Loading branch information
5 people authored Apr 10, 2024
1 parent cb5703b commit 0c1366f
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 34 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.13</version>
<version>1.2.11</version>
</dependency>

</dependencies>
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/com/ericsson/ei/services/SubscriptionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class SubscriptionService implements ISubscriptionService {
private static final Logger LOGGER = LoggerFactory.getLogger(SubscriptionService.class);

@Value("${spring.application.name}")
private String SpringApplicationName;
private String springApplicationName;

@Value("${spring.data.mongodb.database}")
private String dataBaseName;
Expand Down Expand Up @@ -99,7 +99,7 @@ public Subscription getSubscription(String subscriptionName)
try {
subscription = mapper.readValue(input, Subscription.class);
// Inject aggregationtype
subscription.setAggregationtype(SpringApplicationName);
subscription.setAggregationtype(springApplicationName);
return subscription;
} catch (IOException e) {
LOGGER.error("Malformed JSON string", e);
Expand Down Expand Up @@ -129,6 +129,10 @@ public boolean modifySubscription(Subscription subscription, String subscription
ObjectMapper mapper = new ObjectMapper();
Document result = null;
try {
String password = subscription.getPassword();
if (isEncryptionReady(subscription.getAuthenticationType(), subscription.getUserName(), password)) {
subscription.setPassword(encryptPassword(password));
}
String stringSubscription = mapper.writeValueAsString(subscription);

final MongoCondition subscriptionNameCondition = MongoCondition.subscriptionNameCondition(
Expand Down Expand Up @@ -196,7 +200,7 @@ public List<Subscription> getSubscriptions() throws SubscriptionNotFoundExceptio
try {
subscription = mapper.readValue(input, Subscription.class);
// Inject aggregationtype
subscription.setAggregationtype(SpringApplicationName);
subscription.setAggregationtype(springApplicationName);
subscriptions.add(subscription);
} catch (IOException e) {
LOGGER.error("Failed to get subscription.", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import lombok.Getter;
import lombok.Setter;
Expand Down Expand Up @@ -97,11 +98,16 @@ private void extractConditions(String aggregatedObject,
try {
JsonNode subscriptionJson = new ObjectMapper().readTree(
subscriptionData);
LOGGER.debug("SubscriptionJson : " + subscriptionJson.toString());
LOGGER.debug("Aggregated Object : " + aggregatedObject + " for the event id: " + id);

// Remove password from subscription details and put empty value before logging.
JsonNode subscriptoinToDisplay = new ObjectMapper().readTree(subscriptionJson.toString());
LOGGER.debug("SubscriptionJson : {}",
((ObjectNode) subscriptoinToDisplay).put("password", "").toPrettyString());

LOGGER.debug("Aggregated Object : {} for event id: {}", aggregatedObject, id);
ArrayNode requirementNode = (ArrayNode) subscriptionJson.get(
"requirements");
LOGGER.debug("Requirements : " + requirementNode.toString());
LOGGER.debug("Requirements : {}", requirementNode);
Iterator<JsonNode> requirementIterator = requirementNode.elements();
SubscriptionField subscriptionField = new SubscriptionField(subscriptionJson);
String subscriptionName = subscriptionField.get("subscriptionName");
Expand Down
40 changes: 40 additions & 0 deletions src/test/java/com/ericsson/ei/logFilter/LogFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.ericsson.ei.logFilter;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
import org.springframework.context.annotation.PropertySource;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

@PropertySource("classpath:logback.xml")
public class LogFilter extends Filter<ILoggingEvent> {

public boolean filter(LocalDateTime start, LocalDateTime end, String logLine) {
DateTimeFormatter logFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss,SSS");
LocalDateTime current=start;
while(current.isBefore(end))
{
String time=current.format(logFormatter);
if(logLine.contains(time))
{
return (true);
}
else
{
current=current.plus(1, ChronoUnit.MILLIS);
}


}
return (false);
}

@Override
public FilterReply decide(ILoggingEvent iLoggingEvent) {
return null;
}
}

115 changes: 91 additions & 24 deletions src/test/java/com/ericsson/ei/services/SubscriptionServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@
*/
package com.ericsson.ei.services;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import com.ericsson.ei.App;
import com.ericsson.ei.controller.model.Subscription;
import com.ericsson.ei.exception.SubscriptionNotFoundException;
import com.ericsson.ei.logFilter.LogFilter;
import com.ericsson.ei.mongo.MongoCondition;
import com.ericsson.ei.mongo.MongoDBHandler;
import com.ericsson.ei.test.utils.TestConfigs;
import com.ericsson.ei.utils.TestContextInitializer;
import com.ericsson.eiffelcommons.subscriptionobject.RestPostSubscriptionObject;
import com.ericsson.eiffelcommons.subscriptionobject.SubscriptionObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoClient;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONException;
Expand All @@ -49,18 +51,18 @@
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.ericsson.ei.App;
import com.ericsson.ei.controller.model.Subscription;
import com.ericsson.ei.exception.SubscriptionNotFoundException;
import com.ericsson.ei.mongo.MongoCondition;
import com.ericsson.ei.mongo.MongoDBHandler;
import com.ericsson.ei.test.utils.TestConfigs;
import com.ericsson.ei.utils.TestContextInitializer;
import com.ericsson.eiffelcommons.subscriptionobject.RestPostSubscriptionObject;
import com.ericsson.eiffelcommons.subscriptionobject.SubscriptionObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoClient;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import static org.junit.Assert.*;

@TestPropertySource(properties = {
"spring.data.mongodb.database: SubscriptionServiceTest",
Expand Down Expand Up @@ -88,6 +90,9 @@ public class SubscriptionServiceTest {
@Autowired
private ISubscriptionService subscriptionService;

@Autowired
private SubscriptionService subService;

@Autowired
private MongoDBHandler mongoDBHandler;

Expand Down Expand Up @@ -360,4 +365,66 @@ private void deleteSubscriptionsByName(String subscriptionName) throws AccessExc
Mockito.when(authentication.getName()).thenReturn("ABC");
subscriptionService.deleteSubscription(subscriptionName);
}
}

@Test
public void testLogForPasswordAdd() throws Exception {
Path logFilePath= Paths.get("/var/tmp/eiffel-intelligence.log");
try {

Scanner scanner = new Scanner(logFilePath);
LocalDateTime start = LocalDateTime.now();
Subscription subscription2 = mapper.readValue(jsonArray.getJSONObject(0).toString(), Subscription.class);
String expectedSubscriptionName = subscription2.getSubscriptionName();
subscription2.setAuthenticationType("BASIC_AUTH");
String expectedSubscriptionPassword = subscription2.getPassword();
subService.addSubscription(subscription2);
LocalDateTime end = LocalDateTime.now();
LogFilter log = new LogFilter();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (log.filter(start, end, line)) {
if ((line.contains(expectedSubscriptionName) && (line.contains("password")))) {
assertFalse(line.contains(expectedSubscriptionPassword));
}
}
}
scanner.close();
}
catch(Exception e) {
LOGGER.error(e.getMessage(),e);
} finally {
Files.write(logFilePath, new byte[0]);
}
}
@Test
public void testLogForPasswordUpdate() throws Exception {
Path logFilePath=Paths.get("/var/tmp/eiffel-intelligence.log");
try {

Scanner scanner = new Scanner(logFilePath);
LocalDateTime start = LocalDateTime.now();
Subscription subscription2 = mapper.readValue(jsonArray.getJSONObject(0).toString(), Subscription.class);
String expectedSubscriptionName = subscription2.getSubscriptionName();
subscription2.setAuthenticationType("BASIC_AUTH");
subscription2.setPassword("token123");
String expectedSubscriptionPassword = subscription2.getPassword();
subscriptionService.modifySubscription(subscription2,expectedSubscriptionName);
LocalDateTime end = LocalDateTime.now();
LogFilter log = new LogFilter();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (log.filter(start, end, line)) {
if ((line.contains(expectedSubscriptionName) && (line.contains("password")))) {
assertFalse(line.contains(expectedSubscriptionPassword));
}
}
}
scanner.close();
}
catch(Exception e) {
LOGGER.error(e.getMessage(),e);
} finally {
Files.write(logFilePath, new byte[0]);
}
}
}
85 changes: 85 additions & 0 deletions src/test/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Configuration documentation can be found here:
# https://github.com/eiffel-community/eiffel-intelligence/blob/master/wiki/configuration.md
spring.application.name: eiffel-intelligence
server.port: 8090
spring.mvc.pathmatch.matching-strategy: ANT_PATH_MATCHER
logging.level.root: INFO
logging.level.org.springframework.web: ERROR
logging.level.com.ericsson.ei: ERROR

rules.path: /rules/ArtifactRules-Eiffel-Agen-Version.json
rules.replacement.marker: %IdentifyRulesEventId%

# WARNING! Do not enable this in a production environment!
test.aggregation.enabled: false

rabbitmq.host: localhost
rabbitmq.port: 5672
rabbitmq.user: myuser
rabbitmq.password: myuser
rabbitmq.tls.version:
rabbitmq.exchange.name: ei-exchange
rabbitmq.domain.id: ei-domain
rabbitmq.component.name: eiffel-intelligence
rabbitmq.queue.suffix: messageQueue
rabbitmq.queue.durable: true
rabbitmq.binding.key: #
rabbitmq.waitlist.queue.suffix: waitList

bindingkeys.collection.name: binding_keys

spring.data.mongodb.uri: mongodb://localhost:27017
spring.data.mongodb.database: eiffel_intelligence

server.session.timeout: 1200
sessions.collection.name: sessions

aggregations.collection.name: aggregations
aggregations.collection.ttl:
event.object.map.collection.name: event_object_map
subscriptions.collection.name: subscriptions
subscriptions.repeat.handler.collection.name: subscriptions_repeat_handler
waitlist.collection.name: wait_list
waitlist.collection.ttl: 600
waitlist.resend.initial.delay: 2000
waitlist.resend.fixed.rate: 15000
failed.notifications.collection.name: failed_notifications
failed.notifications.collection.ttl: 600
notification.retry: 3
notification.httpRequest.timeout: 5000

email.sender: [email protected]
email.subject: Email Subscription Notification

spring.mail.host:
spring.mail.port:
spring.mail.username:
spring.mail.password:
spring.mail.properties.mail.smtp.auth: false
spring.mail.properties.mail.smtp.starttls.enable: false

event.repository.url:
event.repository.shallow: true

ldap.enabled: false
ldap.server.list: [{\
"url": "",\
"base.dn": "",\
"username": "",\
"password": "",\
"user.filter": ""\
}]

### DEVELOPER SETTINGS

spring.mongodb.embedded.version: 3.4.1
# We remove the embedded mongodb in tests since in most of them we set up our own before Spring
# starts and activate it manually in tests where we need the Spring's own embedded mongo DB
spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration

threads.core.pool.size: 200
threads.queue.capacity: 7000
threads.max.pool.size: 250
scheduled.threadpool.size: 200
jasypt.encryptor.password=test

16 changes: 13 additions & 3 deletions src/test/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@
<pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n</pattern>
</encoder>
</appender>
<root level="info">

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/var/tmp/eiffel-intelligence.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
</encoder>
<filter class="com.ericsson.ei.logFilter.LogFilter" />
</appender>

<root level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<logger name="org.mockserver.mock" level="error" />
</configuration>
<logger name="org.mockserver.mock" level="ERROR" />
</configuration>
1 change: 1 addition & 0 deletions src/test/resources/subscription_CLME.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
],
"subscriptionName" : "Single_CLME_Subscription_Test",
"userName" : "ABC",
"password": "token",
"ldapUserName": ""
}
]

0 comments on commit 0c1366f

Please sign in to comment.