Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.solace.maas.ep.event.management.agent.plugin.command.model.CommandRequest;
import com.solace.maas.ep.event.management.agent.plugin.command.model.CommandResult;
import com.solace.maas.ep.event.management.agent.plugin.command.model.JobStatus;
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService;
import com.solace.maas.ep.event.management.agent.plugin.solace.processor.semp.SempClient;
import com.solace.maas.ep.event.management.agent.plugin.solace.processor.semp.SolaceHttpSemp;
Expand Down Expand Up @@ -53,6 +54,7 @@
@Slf4j
@Service
@ConditionalOnProperty(name = "event-portal.gateway.messaging.standalone", havingValue = "false")
@SuppressWarnings({"PMD.GodClass"})
public class CommandManager {
public static final String ERROR_EXECUTING_COMMAND = "Error executing command";
private final TerraformManager terraformManager;
Expand All @@ -66,6 +68,7 @@ public class CommandManager {
private final SempPatchCommandManager sempPatchCommandManager;
private final SempGetCommandManager sempGetCommandManager;
private final TerraformLogProcessingService terraformLoggingService;
private final EnvironmentUtil environmentUtil;

public CommandManager(TerraformManager terraformManager,
CommandMapper commandMapper,
Expand All @@ -77,7 +80,8 @@ public CommandManager(TerraformManager terraformManager,
final SempDeleteCommandManager sempDeleteCommandManager,
TerraformLogProcessingService terraformLoggingService,
SempPatchCommandManager sempPatchCommandManager,
SempGetCommandManager sempGetCommandManager) {
SempGetCommandManager sempGetCommandManager,
EnvironmentUtil environmentUtil) {
this.terraformManager = terraformManager;
this.commandMapper = commandMapper;
this.commandPublisher = commandPublisher;
Expand All @@ -90,6 +94,7 @@ public CommandManager(TerraformManager terraformManager,
this.terraformLoggingService = terraformLoggingService;
this.sempPatchCommandManager = sempPatchCommandManager;
this.sempGetCommandManager = sempGetCommandManager;
this.environmentUtil = environmentUtil;
}

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

@SuppressWarnings("PMD")
private void configPush(CommandRequest request) {

if (environmentUtil.isCustomCACertPresent()) {
log.info("Custom CA certificates present. Using combined truststore with default and custom CA certificates for configPush operation.");
}
List<Path> executionLogFilesToClean = new ArrayList<>();
boolean attachErrorToTerraformCommand = false;
try {
Expand All @@ -136,6 +145,7 @@ private void configPush(CommandRequest request) {
log.info("Skipping TLS verification for config push to serviceId {}.", request.getServiceId());
}


for (CommandBundle bundle : request.getCommandBundles()) {
boolean exitEarlyOnFailedCommand = bundle.getExitOnFailure();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.solace.maas.ep.common.messages.ScanStatusMessage;
import com.solace.maas.ep.common.model.ScanType;
import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties;
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
import com.solace.maas.ep.event.management.agent.plugin.constants.RouteConstants;
import com.solace.maas.ep.event.management.agent.plugin.constants.ScanStatus;
import com.solace.maas.ep.event.management.agent.plugin.manager.loader.PluginLoader;
Expand Down Expand Up @@ -46,19 +47,25 @@
// This is an optional dependency since it is not available in standalone mode.
// If the bean is not present, the publisher will not be used.
private final Optional<ScanStatusPublisher> scanStatusPublisherOpt;
private final EnvironmentUtil environmentUtil;

@Autowired
public ScanManager(MessagingServiceDelegateServiceImpl messagingServiceDelegateService,
ScanService scanService,
EventPortalProperties eventPortalProperties,
Optional<ScanStatusPublisher> scanStatusPublisher) {
Optional<ScanStatusPublisher> scanStatusPublisher,
EnvironmentUtil environmentUtil) {
this.messagingServiceDelegateService = messagingServiceDelegateService;
this.scanService = scanService;
this.scanStatusPublisherOpt = scanStatusPublisher;
runtimeAgentId = eventPortalProperties.getRuntimeAgentId();
this.environmentUtil = environmentUtil;
}

public String scan(ScanRequestBO scanRequestBO) {
if (environmentUtil.isCustomCACertPresent()) {

Check failure on line 66 in service/application/src/main/java/com/solace/maas/ep/event/management/agent/scanManager/ScanManager.java

View workflow job for this annotation

GitHub Actions / Unit Tests

com.solace.maas.ep.event.management.agent.scanManager.ScanManagerTest ► testScanManager

Failed test found in: service/application/target/surefire-reports/TEST-com.solace.maas.ep.event.management.agent.scanManager.ScanManagerTest.xml Error: java.lang.NullPointerException: Cannot invoke "com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil.isCustomCACertPresent()" because "<local3>.environmentUtil" is null
Raw output
java.lang.NullPointerException: Cannot invoke "com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil.isCustomCACertPresent()" because "<local3>.environmentUtil" is null
	at com.solace.maas.ep.event.management.agent.scanManager.ScanManager.scan(ScanManager.java:66)
	at com.solace.maas.ep.event.management.agent.scanManager.ScanManagerTest.testScanManager(ScanManagerTest.java:193)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
log.info("Custom CA certificates present. Using combined truststore with default and custom CA certificates for scan operation.");
}
Validate.notBlank(scanRequestBO.getOrgId(), " Organization ID cannot be null or empty");
String messagingServiceId = scanRequestBO.getMessagingServiceId();
String scanId = scanRequestBO.getScanId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService;
import com.solace.maas.ep.event.management.agent.plugin.terraform.manager.TerraformLogProcessingService;
import com.solace.maas.ep.event.management.agent.plugin.terraform.manager.TerraformManager;
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
import com.solace.maas.ep.event.management.agent.plugin.vmr.VmrProcessor;
import com.solace.maas.ep.event.management.agent.processor.CommandLogStreamingProcessor;
import com.solace.maas.ep.event.management.agent.publisher.CommandLogsPublisher;
Expand Down Expand Up @@ -70,8 +71,15 @@ public SolaceConfiguration solaceConfiguration() {

@Bean
@Primary
public VMRProperties vmrProperties(EventPortalPluginProperties eventPortalPluginProperties) {
return new VMRProperties(eventPortalPluginProperties);
public EnvironmentUtil environmentUtil() {
return mock(EnvironmentUtil.class);
}

@Bean
@Primary
public VMRProperties vmrProperties(EventPortalPluginProperties eventPortalPluginProperties,
EnvironmentUtil environmentUtil) {
return new VMRProperties(eventPortalPluginProperties, environmentUtil);
}

@Bean
Expand Down Expand Up @@ -177,7 +185,8 @@ public CommandManager getCommandManager(TerraformManager terraformManager,
SempDeleteCommandManager sempDeleteCommandManager,
TerraformLogProcessingService terraformLogProcessingService,
SempPatchCommandManager sempPatchCommandManager,
SempGetCommandManager sempGetCommandManager) {
SempGetCommandManager sempGetCommandManager,
EnvironmentUtil environmentUtil) {
return new CommandManager(
terraformManager,
commandMapper,
Expand All @@ -189,7 +198,8 @@ public CommandManager getCommandManager(TerraformManager terraformManager,
sempDeleteCommandManager,
terraformLogProcessingService,
sempPatchCommandManager,
sempGetCommandManager
sempGetCommandManager,
environmentUtil
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.solace.maas.ep.event.management.agent.webProxy;
package com.solace.maas.ep.event.management.agent.plugin.config;

import com.solace.maas.ep.event.management.agent.plugin.config.VMRProperties;
import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.EventPortalPluginProperties;
import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.GatewayProperties;
import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.GatewayMessagingProperties;
import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.GatewayProperties;
import com.solace.maas.ep.event.management.agent.plugin.messagingService.MessagingServiceConnectionProperties;
import com.solace.maas.ep.event.management.agent.plugin.messagingService.MessagingServiceUsersProperties;
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
import com.solace.messaging.config.SolaceProperties;
import lombok.SneakyThrows;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -37,6 +38,9 @@ class VMRPropertiesTests {
@Mock
private GatewayMessagingProperties gatewayMessagingProperties;

@Mock
private EnvironmentUtil environmentUtil;

// Class under test
private VMRProperties vmrProperties;

Expand All @@ -47,7 +51,8 @@ void setUp() {
// MockitoExtension handles mock initialization
when(eventPortalPluginProperties.getGateway()).thenReturn(gatewayProperties);
when(gatewayProperties.getMessaging()).thenReturn(gatewayMessagingProperties);
vmrProperties = new VMRProperties(eventPortalPluginProperties);

vmrProperties = new VMRProperties(eventPortalPluginProperties, environmentUtil);

// Backup system properties
systemPropertiesBackup = new Properties();
Expand Down Expand Up @@ -256,4 +261,38 @@ void testNoGatewayConnectionProperties() {
.hasCauseExactlyInstanceOf(NoSuchElementException.class)
.hasRootCauseMessage("Event Portal gateway connection properties not found.");
}

@Test
@SneakyThrows
void testConfigureDefaultTrustStoreWhenCustomCaCertsPresent() {
// Mock environmentUtil to return true (custom CA certs are configured)
when(environmentUtil.isCustomCACertPresent()).thenReturn(true);

MessagingServiceConnectionProperties connectionProps = createConnectionProperties(false, null, null, null, null, null);
when(gatewayMessagingProperties.getConnections()).thenReturn(Collections.singletonList(connectionProps));

Properties properties = vmrProperties.getVmrProperties();

// Verify that truststore path is set when custom CA certs are present
assertThat(properties.getProperty(SolaceProperties.TransportLayerSecurityProperties.TRUST_STORE_PATH))
.isNotNull()
.endsWith("cacerts");
}

@Test
@SneakyThrows
void testConfigureDefaultTrustStoreWhenCustomCaCertsNotPresent() {
// Mock environmentUtil to return false (custom CA certs NOT configured)
when(environmentUtil.isCustomCACertPresent()).thenReturn(false);

MessagingServiceConnectionProperties connectionProps = createConnectionProperties(false, null, null, null, null, null);
when(gatewayMessagingProperties.getConnections()).thenReturn(Collections.singletonList(connectionProps));

Properties properties = vmrProperties.getVmrProperties();

// Verify that truststore path is NOT set when custom CA certs are not present
assertThat(properties.getProperty(SolaceProperties.TransportLayerSecurityProperties.TRUST_STORE_PATH))
.isNull();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.solace.maas.ep.common.model.ScanType;
import com.solace.maas.ep.event.management.agent.TestConfig;
import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties;
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
import com.solace.maas.ep.event.management.agent.publisher.ScanStatusPublisher;
import com.solace.maas.ep.event.management.agent.service.MessagingServiceDelegateServiceImpl;
import com.solace.maas.ep.event.management.agent.service.ScanService;
Expand Down Expand Up @@ -38,6 +39,9 @@ class ScanManagerHandleErrorTest {
@Mock
private ScanStatusPublisher scanStatusPublisher;

@Mock
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use @MockitoBean in here as well?

private EnvironmentUtil environmentUtil;

@Test
void testScanManagerConnectedHandleError(){
when(eventPortalProperties.getOrganizationId()).thenReturn("orgId");
Expand All @@ -49,7 +53,8 @@ void testScanManagerConnectedHandleError(){
messagingServiceDelegateService,
scanService,
eventPortalProperties,
Optional.of(scanStatusPublisher)
Optional.of(scanStatusPublisher),
environmentUtil
);
scanManagerUnderTest.handleError(mockEx,createScanCommandMessage());
verify(scanStatusPublisher, times(1)).sendOverallScanStatus(any(),any());
Expand All @@ -66,7 +71,8 @@ void testScanManagerStandaloneHandleError(){
messagingServiceDelegateService,
scanService,
eventPortalProperties,
Optional.empty()
Optional.empty(),
environmentUtil
);
// should just do "nothing" and not throw an exception when scanStatusPublisher is not present
assertDoesNotThrow(() ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.solace.maas.ep.event.management.agent.plugin.common.util;

import org.springframework.stereotype.Component;

@Component
public class EnvironmentUtil {

/**
* Checks if custom CA certificates are present via the CUSTOM_CA_CERTS_PRESENT environment variable.
* Currently, Only Private CEMAs are capable of importing and using custom ca certs for operating ep runtime operations
* on brokers that may be setup with certs signed by custom ca
* @return true if CUSTOM_CA_CERTS_PRESENT is set to "1", false otherwise
*/
public boolean isCustomCACertPresent() {
String customCaCertsPresent = System.getenv("CUSTOM_CA_CERTS_PRESENT");
return "1".equals(customCaCertsPresent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.solace.maas.ep.event.management.agent.plugin.jacoco.ExcludeFromJacocoGeneratedReport;
import com.solace.maas.ep.event.management.agent.plugin.messagingService.MessagingServiceConnectionProperties;
import com.solace.maas.ep.event.management.agent.plugin.messagingService.MessagingServiceUsersProperties;
import com.solace.maas.ep.event.management.agent.plugin.common.util.EnvironmentUtil;
import com.solace.messaging.config.SolaceConstants;
import com.solace.messaging.config.SolaceProperties;
import com.solacesystems.solclientj.core.handle.SessionHandle;
Expand All @@ -16,8 +17,11 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;

import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
Expand All @@ -38,6 +42,7 @@ public class VMRProperties {
private static final String SOLACE_PROXY_PASSWORD = "solace.proxy.password";

private final EventPortalPluginProperties eventPortalPluginProperties;
private final EnvironmentUtil environmentUtil;

/**
* The host used to connect to the VMR
Expand Down Expand Up @@ -74,8 +79,9 @@ public class VMRProperties {
*/

@Autowired
public VMRProperties(EventPortalPluginProperties eventPortalPluginProperties) {
public VMRProperties(EventPortalPluginProperties eventPortalPluginProperties, EnvironmentUtil environmentUtil) {
this.eventPortalPluginProperties = eventPortalPluginProperties;
this.environmentUtil = environmentUtil;
}

public void parseVmrProperties() {
Expand Down Expand Up @@ -122,9 +128,44 @@ public Properties getVmrProperties() {
properties.setProperty(SolaceProperties.AuthenticationProperties.SCHEME_BASIC_PASSWORD, password);
properties.setProperty(SolaceProperties.ClientProperties.NAME, clientName);

//We will always use the default jks truststore for connecting to the EVMR
Copy link

Copilot AI Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states 'We will always use the default jks truststore' but the implementation only configures it when CUSTOM_CA_CERTS_PRESENT=1. Update the comment to accurately reflect the conditional behavior.

Suggested change
//We will always use the default jks truststore for connecting to the EVMR
// Explicitly configure the default JKS truststore for connecting to the EVMR only when custom CA certificates are present

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this comment 👍

configureDefaultTrustStore(properties);

return properties;
}

private void configureDefaultTrustStore(Properties properties) {
if (properties == null) {
log.warn("Properties object is null");
return;
}

if (!environmentUtil.isCustomCACertPresent()) {
log.debug("Custom CA certificates not present. Skipping explicit default truststore configuration.");
return;
}

setDefaultTrustStore(properties);
}

void setDefaultTrustStore(Properties properties) {
String javaHome = System.getProperty("java.home");
if (StringUtils.isBlank(javaHome)) {
log.warn("java.home system property is not set. Cannot configure default truststore for JCSMP.");
return;
}
Path defaultTrustStorePath = Paths.get(javaHome, "lib", "security", "cacerts");
File trustStoreFile = defaultTrustStorePath.toFile();

if (!trustStoreFile.exists() || !trustStoreFile.canRead()) {
log.warn("Default truststore not found or not readable at: {}. JCSMP connection may fail.", defaultTrustStorePath);
return;
}

log.debug("Custom CA certificates present. Explicitly configuring EVMR connection to use default truststore: {}", defaultTrustStorePath);
properties.setProperty(SolaceProperties.TransportLayerSecurityProperties.TRUST_STORE_PATH, defaultTrustStorePath.toString());
}

Comment on lines 151 to 168
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package private to help in testing

public List<String> getRTOSessionProperties() {
parseVmrProperties();

Expand Down
Loading