Skip to content

Commit 0c1366f

Browse files
RajuBeemreddy1Raju Beemreddydhruvin-kalavadiadependabot[bot]jainadc9
authored
Secure the subscription passwords (#543)
* 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]>
1 parent cb5703b commit 0c1366f

File tree

8 files changed

+247
-34
lines changed

8 files changed

+247
-34
lines changed

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@
441441
<dependency>
442442
<groupId>ch.qos.logback</groupId>
443443
<artifactId>logback-classic</artifactId>
444-
<version>1.2.13</version>
444+
<version>1.2.11</version>
445445
</dependency>
446446

447447
</dependencies>

src/main/java/com/ericsson/ei/services/SubscriptionService.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class SubscriptionService implements ISubscriptionService {
5050
private static final Logger LOGGER = LoggerFactory.getLogger(SubscriptionService.class);
5151

5252
@Value("${spring.application.name}")
53-
private String SpringApplicationName;
53+
private String springApplicationName;
5454

5555
@Value("${spring.data.mongodb.database}")
5656
private String dataBaseName;
@@ -99,7 +99,7 @@ public Subscription getSubscription(String subscriptionName)
9999
try {
100100
subscription = mapper.readValue(input, Subscription.class);
101101
// Inject aggregationtype
102-
subscription.setAggregationtype(SpringApplicationName);
102+
subscription.setAggregationtype(springApplicationName);
103103
return subscription;
104104
} catch (IOException e) {
105105
LOGGER.error("Malformed JSON string", e);
@@ -129,6 +129,10 @@ public boolean modifySubscription(Subscription subscription, String subscription
129129
ObjectMapper mapper = new ObjectMapper();
130130
Document result = null;
131131
try {
132+
String password = subscription.getPassword();
133+
if (isEncryptionReady(subscription.getAuthenticationType(), subscription.getUserName(), password)) {
134+
subscription.setPassword(encryptPassword(password));
135+
}
132136
String stringSubscription = mapper.writeValueAsString(subscription);
133137

134138
final MongoCondition subscriptionNameCondition = MongoCondition.subscriptionNameCondition(
@@ -196,7 +200,7 @@ public List<Subscription> getSubscriptions() throws SubscriptionNotFoundExceptio
196200
try {
197201
subscription = mapper.readValue(input, Subscription.class);
198202
// Inject aggregationtype
199-
subscription.setAggregationtype(SpringApplicationName);
203+
subscription.setAggregationtype(springApplicationName);
200204
subscriptions.add(subscription);
201205
} catch (IOException e) {
202206
LOGGER.error("Failed to get subscription.", e);

src/main/java/com/ericsson/ei/subscription/SubscriptionHandler.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.fasterxml.jackson.databind.JsonNode;
2929
import com.fasterxml.jackson.databind.ObjectMapper;
3030
import com.fasterxml.jackson.databind.node.ArrayNode;
31+
import com.fasterxml.jackson.databind.node.ObjectNode;
3132

3233
import lombok.Getter;
3334
import lombok.Setter;
@@ -97,11 +98,16 @@ private void extractConditions(String aggregatedObject,
9798
try {
9899
JsonNode subscriptionJson = new ObjectMapper().readTree(
99100
subscriptionData);
100-
LOGGER.debug("SubscriptionJson : " + subscriptionJson.toString());
101-
LOGGER.debug("Aggregated Object : " + aggregatedObject + " for the event id: " + id);
101+
102+
// Remove password from subscription details and put empty value before logging.
103+
JsonNode subscriptoinToDisplay = new ObjectMapper().readTree(subscriptionJson.toString());
104+
LOGGER.debug("SubscriptionJson : {}",
105+
((ObjectNode) subscriptoinToDisplay).put("password", "").toPrettyString());
106+
107+
LOGGER.debug("Aggregated Object : {} for event id: {}", aggregatedObject, id);
102108
ArrayNode requirementNode = (ArrayNode) subscriptionJson.get(
103109
"requirements");
104-
LOGGER.debug("Requirements : " + requirementNode.toString());
110+
LOGGER.debug("Requirements : {}", requirementNode);
105111
Iterator<JsonNode> requirementIterator = requirementNode.elements();
106112
SubscriptionField subscriptionField = new SubscriptionField(subscriptionJson);
107113
String subscriptionName = subscriptionField.get("subscriptionName");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.ericsson.ei.logFilter;
2+
3+
import ch.qos.logback.classic.spi.ILoggingEvent;
4+
import ch.qos.logback.core.filter.Filter;
5+
import ch.qos.logback.core.spi.FilterReply;
6+
import org.springframework.context.annotation.PropertySource;
7+
8+
import java.time.LocalDateTime;
9+
import java.time.format.DateTimeFormatter;
10+
import java.time.temporal.ChronoUnit;
11+
12+
@PropertySource("classpath:logback.xml")
13+
public class LogFilter extends Filter<ILoggingEvent> {
14+
15+
public boolean filter(LocalDateTime start, LocalDateTime end, String logLine) {
16+
DateTimeFormatter logFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss,SSS");
17+
LocalDateTime current=start;
18+
while(current.isBefore(end))
19+
{
20+
String time=current.format(logFormatter);
21+
if(logLine.contains(time))
22+
{
23+
return (true);
24+
}
25+
else
26+
{
27+
current=current.plus(1, ChronoUnit.MILLIS);
28+
}
29+
30+
31+
}
32+
return (false);
33+
}
34+
35+
@Override
36+
public FilterReply decide(ILoggingEvent iLoggingEvent) {
37+
return null;
38+
}
39+
}
40+

src/test/java/com/ericsson/ei/services/SubscriptionServiceTest.java

+91-24
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@
1616
*/
1717
package com.ericsson.ei.services;
1818

19-
import static org.junit.Assert.assertEquals;
20-
import static org.junit.Assert.assertNull;
21-
import static org.junit.Assert.assertTrue;
22-
23-
import java.io.File;
24-
import java.io.IOException;
25-
import java.util.ArrayList;
26-
import java.util.List;
27-
28-
import javax.annotation.PostConstruct;
29-
19+
import com.ericsson.ei.App;
20+
import com.ericsson.ei.controller.model.Subscription;
21+
import com.ericsson.ei.exception.SubscriptionNotFoundException;
22+
import com.ericsson.ei.logFilter.LogFilter;
23+
import com.ericsson.ei.mongo.MongoCondition;
24+
import com.ericsson.ei.mongo.MongoDBHandler;
25+
import com.ericsson.ei.test.utils.TestConfigs;
26+
import com.ericsson.ei.utils.TestContextInitializer;
27+
import com.ericsson.eiffelcommons.subscriptionobject.RestPostSubscriptionObject;
28+
import com.ericsson.eiffelcommons.subscriptionobject.SubscriptionObject;
29+
import com.fasterxml.jackson.databind.ObjectMapper;
30+
import com.mongodb.BasicDBObject;
31+
import com.mongodb.client.MongoClient;
3032
import org.apache.commons.io.FileUtils;
3133
import org.json.JSONArray;
3234
import org.json.JSONException;
@@ -49,18 +51,18 @@
4951
import org.springframework.test.context.TestPropertySource;
5052
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
5153

52-
import com.ericsson.ei.App;
53-
import com.ericsson.ei.controller.model.Subscription;
54-
import com.ericsson.ei.exception.SubscriptionNotFoundException;
55-
import com.ericsson.ei.mongo.MongoCondition;
56-
import com.ericsson.ei.mongo.MongoDBHandler;
57-
import com.ericsson.ei.test.utils.TestConfigs;
58-
import com.ericsson.ei.utils.TestContextInitializer;
59-
import com.ericsson.eiffelcommons.subscriptionobject.RestPostSubscriptionObject;
60-
import com.ericsson.eiffelcommons.subscriptionobject.SubscriptionObject;
61-
import com.fasterxml.jackson.databind.ObjectMapper;
62-
import com.mongodb.BasicDBObject;
63-
import com.mongodb.client.MongoClient;
54+
import javax.annotation.PostConstruct;
55+
import java.io.File;
56+
import java.io.IOException;
57+
import java.nio.file.Files;
58+
import java.nio.file.Path;
59+
import java.nio.file.Paths;
60+
import java.time.LocalDateTime;
61+
import java.util.ArrayList;
62+
import java.util.List;
63+
import java.util.Scanner;
64+
65+
import static org.junit.Assert.*;
6466

6567
@TestPropertySource(properties = {
6668
"spring.data.mongodb.database: SubscriptionServiceTest",
@@ -88,6 +90,9 @@ public class SubscriptionServiceTest {
8890
@Autowired
8991
private ISubscriptionService subscriptionService;
9092

93+
@Autowired
94+
private SubscriptionService subService;
95+
9196
@Autowired
9297
private MongoDBHandler mongoDBHandler;
9398

@@ -360,4 +365,66 @@ private void deleteSubscriptionsByName(String subscriptionName) throws AccessExc
360365
Mockito.when(authentication.getName()).thenReturn("ABC");
361366
subscriptionService.deleteSubscription(subscriptionName);
362367
}
363-
}
368+
369+
@Test
370+
public void testLogForPasswordAdd() throws Exception {
371+
Path logFilePath= Paths.get("/var/tmp/eiffel-intelligence.log");
372+
try {
373+
374+
Scanner scanner = new Scanner(logFilePath);
375+
LocalDateTime start = LocalDateTime.now();
376+
Subscription subscription2 = mapper.readValue(jsonArray.getJSONObject(0).toString(), Subscription.class);
377+
String expectedSubscriptionName = subscription2.getSubscriptionName();
378+
subscription2.setAuthenticationType("BASIC_AUTH");
379+
String expectedSubscriptionPassword = subscription2.getPassword();
380+
subService.addSubscription(subscription2);
381+
LocalDateTime end = LocalDateTime.now();
382+
LogFilter log = new LogFilter();
383+
while (scanner.hasNextLine()) {
384+
String line = scanner.nextLine();
385+
if (log.filter(start, end, line)) {
386+
if ((line.contains(expectedSubscriptionName) && (line.contains("password")))) {
387+
assertFalse(line.contains(expectedSubscriptionPassword));
388+
}
389+
}
390+
}
391+
scanner.close();
392+
}
393+
catch(Exception e) {
394+
LOGGER.error(e.getMessage(),e);
395+
} finally {
396+
Files.write(logFilePath, new byte[0]);
397+
}
398+
}
399+
@Test
400+
public void testLogForPasswordUpdate() throws Exception {
401+
Path logFilePath=Paths.get("/var/tmp/eiffel-intelligence.log");
402+
try {
403+
404+
Scanner scanner = new Scanner(logFilePath);
405+
LocalDateTime start = LocalDateTime.now();
406+
Subscription subscription2 = mapper.readValue(jsonArray.getJSONObject(0).toString(), Subscription.class);
407+
String expectedSubscriptionName = subscription2.getSubscriptionName();
408+
subscription2.setAuthenticationType("BASIC_AUTH");
409+
subscription2.setPassword("token123");
410+
String expectedSubscriptionPassword = subscription2.getPassword();
411+
subscriptionService.modifySubscription(subscription2,expectedSubscriptionName);
412+
LocalDateTime end = LocalDateTime.now();
413+
LogFilter log = new LogFilter();
414+
while (scanner.hasNextLine()) {
415+
String line = scanner.nextLine();
416+
if (log.filter(start, end, line)) {
417+
if ((line.contains(expectedSubscriptionName) && (line.contains("password")))) {
418+
assertFalse(line.contains(expectedSubscriptionPassword));
419+
}
420+
}
421+
}
422+
scanner.close();
423+
}
424+
catch(Exception e) {
425+
LOGGER.error(e.getMessage(),e);
426+
} finally {
427+
Files.write(logFilePath, new byte[0]);
428+
}
429+
}
430+
}
+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Configuration documentation can be found here:
2+
# https://github.com/eiffel-community/eiffel-intelligence/blob/master/wiki/configuration.md
3+
spring.application.name: eiffel-intelligence
4+
server.port: 8090
5+
spring.mvc.pathmatch.matching-strategy: ANT_PATH_MATCHER
6+
logging.level.root: INFO
7+
logging.level.org.springframework.web: ERROR
8+
logging.level.com.ericsson.ei: ERROR
9+
10+
rules.path: /rules/ArtifactRules-Eiffel-Agen-Version.json
11+
rules.replacement.marker: %IdentifyRulesEventId%
12+
13+
# WARNING! Do not enable this in a production environment!
14+
test.aggregation.enabled: false
15+
16+
rabbitmq.host: localhost
17+
rabbitmq.port: 5672
18+
rabbitmq.user: myuser
19+
rabbitmq.password: myuser
20+
rabbitmq.tls.version:
21+
rabbitmq.exchange.name: ei-exchange
22+
rabbitmq.domain.id: ei-domain
23+
rabbitmq.component.name: eiffel-intelligence
24+
rabbitmq.queue.suffix: messageQueue
25+
rabbitmq.queue.durable: true
26+
rabbitmq.binding.key: #
27+
rabbitmq.waitlist.queue.suffix: waitList
28+
29+
bindingkeys.collection.name: binding_keys
30+
31+
spring.data.mongodb.uri: mongodb://localhost:27017
32+
spring.data.mongodb.database: eiffel_intelligence
33+
34+
server.session.timeout: 1200
35+
sessions.collection.name: sessions
36+
37+
aggregations.collection.name: aggregations
38+
aggregations.collection.ttl:
39+
event.object.map.collection.name: event_object_map
40+
subscriptions.collection.name: subscriptions
41+
subscriptions.repeat.handler.collection.name: subscriptions_repeat_handler
42+
waitlist.collection.name: wait_list
43+
waitlist.collection.ttl: 600
44+
waitlist.resend.initial.delay: 2000
45+
waitlist.resend.fixed.rate: 15000
46+
failed.notifications.collection.name: failed_notifications
47+
failed.notifications.collection.ttl: 600
48+
notification.retry: 3
49+
notification.httpRequest.timeout: 5000
50+
51+
email.sender: [email protected]
52+
email.subject: Email Subscription Notification
53+
54+
spring.mail.host:
55+
spring.mail.port:
56+
spring.mail.username:
57+
spring.mail.password:
58+
spring.mail.properties.mail.smtp.auth: false
59+
spring.mail.properties.mail.smtp.starttls.enable: false
60+
61+
event.repository.url:
62+
event.repository.shallow: true
63+
64+
ldap.enabled: false
65+
ldap.server.list: [{\
66+
"url": "",\
67+
"base.dn": "",\
68+
"username": "",\
69+
"password": "",\
70+
"user.filter": ""\
71+
}]
72+
73+
### DEVELOPER SETTINGS
74+
75+
spring.mongodb.embedded.version: 3.4.1
76+
# We remove the embedded mongodb in tests since in most of them we set up our own before Spring
77+
# starts and activate it manually in tests where we need the Spring's own embedded mongo DB
78+
spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration
79+
80+
threads.core.pool.size: 200
81+
threads.queue.capacity: 7000
82+
threads.max.pool.size: 250
83+
scheduled.threadpool.size: 200
84+
jasypt.encryptor.password=test
85+

src/test/resources/logback.xml

+13-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@
55
<pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n</pattern>
66
</encoder>
77
</appender>
8-
<root level="info">
8+
9+
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
10+
<file>/var/tmp/eiffel-intelligence.log</file>
11+
<encoder>
12+
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
13+
</encoder>
14+
<filter class="com.ericsson.ei.logFilter.LogFilter" />
15+
</appender>
16+
17+
<root level="DEBUG">
918
<appender-ref ref="STDOUT" />
19+
<appender-ref ref="FILE" />
1020
</root>
11-
<logger name="org.mockserver.mock" level="error" />
12-
</configuration>
21+
<logger name="org.mockserver.mock" level="ERROR" />
22+
</configuration>

src/test/resources/subscription_CLME.json

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
],
2727
"subscriptionName" : "Single_CLME_Subscription_Test",
2828
"userName" : "ABC",
29+
"password": "token",
2930
"ldapUserName": ""
3031
}
3132
]

0 commit comments

Comments
 (0)