Skip to content

Commit 95a8d10

Browse files
Merge pull request #282 from SolaceProducts/DATAGO-116001-custom-cert-ema-work
DATAGO-116001: event-management-agent: Configure JCSMP to use default JDK truststore for Event Portal connections
2 parents 78ed163 + 8559ebe commit 95a8d10

File tree

8 files changed

+157
-21
lines changed

8 files changed

+157
-21
lines changed

service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.solace.maas.ep.event.management.agent.plugin.command.model.CommandRequest;
1010
import com.solace.maas.ep.event.management.agent.plugin.command.model.CommandResult;
1111
import com.solace.maas.ep.event.management.agent.plugin.command.model.JobStatus;
12+
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
1213
import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService;
1314
import com.solace.maas.ep.event.management.agent.plugin.solace.processor.semp.SempClient;
1415
import com.solace.maas.ep.event.management.agent.plugin.solace.processor.semp.SolaceHttpSemp;
@@ -53,6 +54,7 @@
5354
@Slf4j
5455
@Service
5556
@ConditionalOnProperty(name = "event-portal.gateway.messaging.standalone", havingValue = "false")
57+
@SuppressWarnings({"PMD.GodClass"})
5658
public class CommandManager {
5759
public static final String ERROR_EXECUTING_COMMAND = "Error executing command";
5860
private final TerraformManager terraformManager;
@@ -66,6 +68,7 @@ public class CommandManager {
6668
private final SempPatchCommandManager sempPatchCommandManager;
6769
private final SempGetCommandManager sempGetCommandManager;
6870
private final TerraformLogProcessingService terraformLoggingService;
71+
private final EnvironmentUtil environmentUtil;
6972

7073
public CommandManager(TerraformManager terraformManager,
7174
CommandMapper commandMapper,
@@ -77,7 +80,8 @@ public CommandManager(TerraformManager terraformManager,
7780
final SempDeleteCommandManager sempDeleteCommandManager,
7881
TerraformLogProcessingService terraformLoggingService,
7982
SempPatchCommandManager sempPatchCommandManager,
80-
SempGetCommandManager sempGetCommandManager) {
83+
SempGetCommandManager sempGetCommandManager,
84+
EnvironmentUtil environmentUtil) {
8185
this.terraformManager = terraformManager;
8286
this.commandMapper = commandMapper;
8387
this.commandPublisher = commandPublisher;
@@ -90,6 +94,7 @@ public CommandManager(TerraformManager terraformManager,
9094
this.terraformLoggingService = terraformLoggingService;
9195
this.sempPatchCommandManager = sempPatchCommandManager;
9296
this.sempGetCommandManager = sempGetCommandManager;
97+
this.environmentUtil = environmentUtil;
9398
}
9499

95100
public void execute(CommandMessage request) {
@@ -116,6 +121,10 @@ public void handleError(Exception e, CommandMessage message) {
116121

117122
@SuppressWarnings("PMD")
118123
private void configPush(CommandRequest request) {
124+
125+
if (environmentUtil.isCustomCACertPresent()) {
126+
log.info("Custom CA certificates present. Using combined truststore with default and custom CA certificates for configPush operation.");
127+
}
119128
List<Path> executionLogFilesToClean = new ArrayList<>();
120129
boolean attachErrorToTerraformCommand = false;
121130
try {
@@ -136,6 +145,7 @@ private void configPush(CommandRequest request) {
136145
log.info("Skipping TLS verification for config push to serviceId {}.", request.getServiceId());
137146
}
138147

148+
139149
for (CommandBundle bundle : request.getCommandBundles()) {
140150
boolean exitEarlyOnFailedCommand = bundle.getExitOnFailure();
141151

service/application/src/main/java/com/solace/maas/ep/event/management/agent/scanManager/ScanManager.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.solace.maas.ep.common.messages.ScanStatusMessage;
55
import com.solace.maas.ep.common.model.ScanType;
66
import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties;
7+
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
78
import com.solace.maas.ep.event.management.agent.plugin.constants.RouteConstants;
89
import com.solace.maas.ep.event.management.agent.plugin.constants.ScanStatus;
910
import com.solace.maas.ep.event.management.agent.plugin.manager.loader.PluginLoader;
@@ -46,19 +47,25 @@ public class ScanManager {
4647
// This is an optional dependency since it is not available in standalone mode.
4748
// If the bean is not present, the publisher will not be used.
4849
private final Optional<ScanStatusPublisher> scanStatusPublisherOpt;
50+
private final EnvironmentUtil environmentUtil;
4951

5052
@Autowired
5153
public ScanManager(MessagingServiceDelegateServiceImpl messagingServiceDelegateService,
5254
ScanService scanService,
5355
EventPortalProperties eventPortalProperties,
54-
Optional<ScanStatusPublisher> scanStatusPublisher) {
56+
Optional<ScanStatusPublisher> scanStatusPublisher,
57+
EnvironmentUtil environmentUtil) {
5558
this.messagingServiceDelegateService = messagingServiceDelegateService;
5659
this.scanService = scanService;
5760
this.scanStatusPublisherOpt = scanStatusPublisher;
5861
runtimeAgentId = eventPortalProperties.getRuntimeAgentId();
62+
this.environmentUtil = environmentUtil;
5963
}
6064

6165
public String scan(ScanRequestBO scanRequestBO) {
66+
if (environmentUtil.isCustomCACertPresent()) {
67+
log.info("Custom CA certificates present. Using combined truststore with default and custom CA certificates for scan operation.");
68+
}
6269
Validate.notBlank(scanRequestBO.getOrgId(), " Organization ID cannot be null or empty");
6370
String messagingServiceId = scanRequestBO.getMessagingServiceId();
6471
String scanId = scanRequestBO.getScanId();

service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService;
2020
import com.solace.maas.ep.event.management.agent.plugin.terraform.manager.TerraformLogProcessingService;
2121
import com.solace.maas.ep.event.management.agent.plugin.terraform.manager.TerraformManager;
22+
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
2223
import com.solace.maas.ep.event.management.agent.plugin.vmr.VmrProcessor;
2324
import com.solace.maas.ep.event.management.agent.processor.CommandLogStreamingProcessor;
2425
import com.solace.maas.ep.event.management.agent.publisher.CommandLogsPublisher;
@@ -70,8 +71,15 @@ public SolaceConfiguration solaceConfiguration() {
7071

7172
@Bean
7273
@Primary
73-
public VMRProperties vmrProperties(EventPortalPluginProperties eventPortalPluginProperties) {
74-
return new VMRProperties(eventPortalPluginProperties);
74+
public EnvironmentUtil environmentUtil() {
75+
return mock(EnvironmentUtil.class);
76+
}
77+
78+
@Bean
79+
@Primary
80+
public VMRProperties vmrProperties(EventPortalPluginProperties eventPortalPluginProperties,
81+
EnvironmentUtil environmentUtil) {
82+
return new VMRProperties(eventPortalPluginProperties, environmentUtil);
7583
}
7684

7785
@Bean
@@ -177,7 +185,8 @@ public CommandManager getCommandManager(TerraformManager terraformManager,
177185
SempDeleteCommandManager sempDeleteCommandManager,
178186
TerraformLogProcessingService terraformLogProcessingService,
179187
SempPatchCommandManager sempPatchCommandManager,
180-
SempGetCommandManager sempGetCommandManager) {
188+
SempGetCommandManager sempGetCommandManager,
189+
EnvironmentUtil environmentUtil) {
181190
return new CommandManager(
182191
terraformManager,
183192
commandMapper,
@@ -189,7 +198,8 @@ public CommandManager getCommandManager(TerraformManager terraformManager,
189198
sempDeleteCommandManager,
190199
terraformLogProcessingService,
191200
sempPatchCommandManager,
192-
sempGetCommandManager
201+
sempGetCommandManager,
202+
environmentUtil
193203
);
194204
}
195205

service/application/src/test/java/com/solace/maas/ep/event/management/agent/webProxy/VMRPropertiesTests.java renamed to service/application/src/test/java/com/solace/maas/ep/event/management/agent/plugin/config/VMRPropertiesTests.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
package com.solace.maas.ep.event.management.agent.webProxy;
1+
package com.solace.maas.ep.event.management.agent.plugin.config;
22

3-
import com.solace.maas.ep.event.management.agent.plugin.config.VMRProperties;
43
import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.EventPortalPluginProperties;
5-
import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.GatewayProperties;
64
import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.GatewayMessagingProperties;
5+
import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.GatewayProperties;
76
import com.solace.maas.ep.event.management.agent.plugin.messagingService.MessagingServiceConnectionProperties;
87
import com.solace.maas.ep.event.management.agent.plugin.messagingService.MessagingServiceUsersProperties;
8+
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
9+
import com.solace.messaging.config.SolaceProperties;
910
import lombok.SneakyThrows;
1011
import org.junit.jupiter.api.AfterEach;
1112
import org.junit.jupiter.api.BeforeEach;
@@ -37,6 +38,9 @@ class VMRPropertiesTests {
3738
@Mock
3839
private GatewayMessagingProperties gatewayMessagingProperties;
3940

41+
@Mock
42+
private EnvironmentUtil environmentUtil;
43+
4044
// Class under test
4145
private VMRProperties vmrProperties;
4246

@@ -47,7 +51,8 @@ void setUp() {
4751
// MockitoExtension handles mock initialization
4852
when(eventPortalPluginProperties.getGateway()).thenReturn(gatewayProperties);
4953
when(gatewayProperties.getMessaging()).thenReturn(gatewayMessagingProperties);
50-
vmrProperties = new VMRProperties(eventPortalPluginProperties);
54+
55+
vmrProperties = new VMRProperties(eventPortalPluginProperties, environmentUtil);
5156

5257
// Backup system properties
5358
systemPropertiesBackup = new Properties();
@@ -256,4 +261,38 @@ void testNoGatewayConnectionProperties() {
256261
.hasCauseExactlyInstanceOf(NoSuchElementException.class)
257262
.hasRootCauseMessage("Event Portal gateway connection properties not found.");
258263
}
264+
265+
@Test
266+
@SneakyThrows
267+
void testConfigureDefaultTrustStoreWhenCustomCaCertsPresent() {
268+
// Mock environmentUtil to return true (custom CA certs are configured)
269+
when(environmentUtil.isCustomCACertPresent()).thenReturn(true);
270+
271+
MessagingServiceConnectionProperties connectionProps = createConnectionProperties(false, null, null, null, null, null);
272+
when(gatewayMessagingProperties.getConnections()).thenReturn(Collections.singletonList(connectionProps));
273+
274+
Properties properties = vmrProperties.getVmrProperties();
275+
276+
// Verify that truststore path is set when custom CA certs are present
277+
assertThat(properties.getProperty(SolaceProperties.TransportLayerSecurityProperties.TRUST_STORE_PATH))
278+
.isNotNull()
279+
.endsWith("cacerts");
280+
}
281+
282+
@Test
283+
@SneakyThrows
284+
void testConfigureDefaultTrustStoreWhenCustomCaCertsNotPresent() {
285+
// Mock environmentUtil to return false (custom CA certs NOT configured)
286+
when(environmentUtil.isCustomCACertPresent()).thenReturn(false);
287+
288+
MessagingServiceConnectionProperties connectionProps = createConnectionProperties(false, null, null, null, null, null);
289+
when(gatewayMessagingProperties.getConnections()).thenReturn(Collections.singletonList(connectionProps));
290+
291+
Properties properties = vmrProperties.getVmrProperties();
292+
293+
// Verify that truststore path is NOT set when custom CA certs are not present
294+
assertThat(properties.getProperty(SolaceProperties.TransportLayerSecurityProperties.TRUST_STORE_PATH))
295+
.isNull();
296+
}
297+
259298
}

service/application/src/test/java/com/solace/maas/ep/event/management/agent/scanManager/ScanManagerHandleErrorTest.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.solace.maas.ep.common.model.ScanType;
66
import com.solace.maas.ep.event.management.agent.TestConfig;
77
import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties;
8+
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
89
import com.solace.maas.ep.event.management.agent.publisher.ScanStatusPublisher;
910
import com.solace.maas.ep.event.management.agent.service.MessagingServiceDelegateServiceImpl;
1011
import com.solace.maas.ep.event.management.agent.service.ScanService;
@@ -38,6 +39,9 @@ class ScanManagerHandleErrorTest {
3839
@Mock
3940
private ScanStatusPublisher scanStatusPublisher;
4041

42+
@Mock
43+
private EnvironmentUtil environmentUtil;
44+
4145
@Test
4246
void testScanManagerConnectedHandleError(){
4347
when(eventPortalProperties.getOrganizationId()).thenReturn("orgId");
@@ -49,7 +53,8 @@ void testScanManagerConnectedHandleError(){
4953
messagingServiceDelegateService,
5054
scanService,
5155
eventPortalProperties,
52-
Optional.of(scanStatusPublisher)
56+
Optional.of(scanStatusPublisher),
57+
environmentUtil
5358
);
5459
scanManagerUnderTest.handleError(mockEx,createScanCommandMessage());
5560
verify(scanStatusPublisher, times(1)).sendOverallScanStatus(any(),any());
@@ -66,7 +71,8 @@ void testScanManagerStandaloneHandleError(){
6671
messagingServiceDelegateService,
6772
scanService,
6873
eventPortalProperties,
69-
Optional.empty()
74+
Optional.empty(),
75+
environmentUtil
7076
);
7177
// should just do "nothing" and not throw an exception when scanStatusPublisher is not present
7278
assertDoesNotThrow(() ->

service/application/src/test/java/com/solace/maas/ep/event/management/agent/scanManager/ScanManagerTest.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.solace.maas.ep.event.management.agent.TestConfig;
44
import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties;
5+
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
56
import com.solace.maas.ep.event.management.agent.plugin.confluentSchemaRegistry.route.delegate.ConfluentSchemaRegistryRouteDelegateImpl;
67
import com.solace.maas.ep.event.management.agent.plugin.kafka.route.delegate.KafkaRouteDelegateImpl;
78
import com.solace.maas.ep.event.management.agent.plugin.localstorage.route.delegate.DataCollectionFileWriterDelegateImpl;
@@ -15,41 +16,45 @@
1516
import lombok.SneakyThrows;
1617
import org.junit.jupiter.api.Assertions;
1718
import org.junit.jupiter.api.Test;
18-
import org.mockito.InjectMocks;
19-
import org.mockito.Mock;
2019
import org.mockito.MockedStatic;
2120
import org.mockito.Mockito;
2221
import org.springframework.beans.factory.annotation.Autowired;
2322
import org.springframework.boot.test.context.SpringBootTest;
2423
import org.springframework.test.context.ActiveProfiles;
24+
import org.springframework.test.context.bean.override.mockito.MockitoBean;
25+
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
2526

2627
import java.util.Arrays;
2728
import java.util.HashSet;
2829
import java.util.List;
2930

3031
import static org.assertj.core.api.Assertions.assertThatNoException;
32+
import static org.mockito.ArgumentMatchers.eq;
3133
import static org.mockito.Mockito.mock;
3234
import static org.mockito.Mockito.when;
3335

3436
@ActiveProfiles("TEST")
3537
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = TestConfig.class)
3638
class ScanManagerTest {
3739

38-
@Mock
40+
@MockitoBean
3941
MessagingServiceDelegateServiceImpl messagingServiceDelegateService;
4042

41-
@Mock
43+
@MockitoBean
4244
private EventPortalProperties eventPortalProperties;
4345

44-
@InjectMocks
46+
@MockitoSpyBean
4547
ScanManager scanManager;
4648

4749
@Autowired
4850
ConfluentSchemaRegistryRouteDelegateImpl confluentSchemaRegistryRouteDelegate;
4951

50-
@Mock
52+
@MockitoBean
5153
private ScanService scanService;
5254

55+
@Autowired
56+
private EnvironmentUtil environmentUtil;
57+
5358

5459
@Test
5560
@SneakyThrows
@@ -177,7 +182,7 @@ void testScanManager() {
177182
when(kafkaRouteDelegate.generateRouteList(destinations, List.of(), "KAFKA_ALL", messagingServiceId))
178183
.thenReturn(routes);
179184

180-
when(scanService.singleScan(
185+
when(scanService.singleScan(eq(
181186
SingleScanSpecification
182187
.builder()
183188
.orgId("orgId")
@@ -189,7 +194,7 @@ void testScanManager() {
189194
.runtimeAgentId("runtimeAgent1")
190195
.routeBundles(List.of())
191196
.build()
192-
)).thenReturn(Mockito.anyString());
197+
))).thenReturn(Mockito.anyString());
193198
scanManager.scan(scanRequestBO);
194199

195200
assertThatNoException();
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.solace.maas.ep.event.management.agent.plugin.common.util;
2+
3+
import org.springframework.stereotype.Component;
4+
5+
@Component
6+
public class EnvironmentUtil {
7+
8+
/**
9+
* Checks if custom CA certificates are present via the CUSTOM_CA_CERTS_PRESENT environment variable.
10+
* Currently, Only Private CEMAs are capable of importing and using custom ca certs for operating ep runtime operations
11+
* on brokers that may be setup with certs signed by custom ca
12+
* @return true if CUSTOM_CA_CERTS_PRESENT is set to "1", false otherwise
13+
*/
14+
public boolean isCustomCACertPresent() {
15+
String customCaCertsPresent = System.getenv("CUSTOM_CA_CERTS_PRESENT");
16+
return "1".equals(customCaCertsPresent);
17+
}
18+
}

0 commit comments

Comments
 (0)