Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS will be completely phased out by mid-2025. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit 8463b7c4 authored by Sebastian-Ion TINCU's avatar Sebastian-Ion TINCU
Browse files

EDELIVERY-11317 User should be able to check connection with SMP when changing certificate.

Add domain validation integration with SML.
Add exists participant integration with SML.
parent d8ae9def
No related branches found
No related tags found
No related merge requests found
Pipeline #142353 failed
......@@ -19,6 +19,7 @@
package eu.europa.ec.edelivery.smp.conversion;
import ec.services.wsdl.bdmsl.data._1.ParticipantsType;
import ec.services.wsdl.bdmsl.data._1.SMPAdvancedServiceForParticipantType;
import eu.europa.ec.edelivery.smp.identifiers.Identifier;
import org.busdox.servicemetadata.locator._1.ServiceMetadataPublisherServiceForParticipantType;
......@@ -31,12 +32,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
public class SmlIdentifierConverter {
public static ServiceMetadataPublisherServiceForParticipantType toBusdoxParticipantId(Identifier participantId, String smpId) {
if (isBlank(smpId)) {
throw new IllegalStateException("SMP ID is null or empty");
}
if (participantId == null || isBlank(participantId.getValue())) {
throw new IllegalStateException("Participant Scheme or Id is null or empty");
}
validate(participantId, smpId);
ServiceMetadataPublisherServiceForParticipantType busdoxIdentifier = new ServiceMetadataPublisherServiceForParticipantType();
busdoxIdentifier.setServiceMetadataPublisherID(smpId);
......@@ -47,20 +43,36 @@ public class SmlIdentifierConverter {
return busdoxIdentifier;
}
public static ParticipantsType toParticipantsType(Identifier participantId, String smpId) {
validate(participantId, smpId);
ParticipantsType participantsType = new ParticipantsType();
org.busdox.transport.identifiers._1.ParticipantIdentifierType parId = new org.busdox.transport.identifiers._1.ParticipantIdentifierType();
parId.setScheme(participantId.getScheme());
parId.setValue(participantId.getValue());
participantsType.setParticipantIdentifier(parId);
participantsType.setServiceMetadataPublisherID(smpId);
return participantsType;
}
public static SMPAdvancedServiceForParticipantType toBDMSLAdvancedParticipantId(Identifier participantId, String smpId, String serviceMetadata) {
if (isBlank(smpId)) {
throw new IllegalStateException("SMP ID is null or empty");
}
if (participantId == null || isBlank(participantId.getValue())) {
throw new IllegalStateException("Participant Scheme or Id is null or empty");
}
validate(participantId, smpId);
SMPAdvancedServiceForParticipantType bdmslRequest = new SMPAdvancedServiceForParticipantType();
bdmslRequest.setServiceName(serviceMetadata);
ServiceMetadataPublisherServiceForParticipantType bdxlRequest = toBusdoxParticipantId(participantId, smpId);
bdmslRequest.setCreateParticipantIdentifier(bdxlRequest);
return bdmslRequest;
}
private static void validate(Identifier participantId, String smpId) {
if (isBlank(smpId)) {
throw new IllegalStateException("SMP ID is null or empty");
}
if (participantId == null || isBlank(participantId.getValue())) {
throw new IllegalStateException("Participant Scheme or Id is null or empty");
}
}
}
......@@ -75,7 +75,7 @@ public enum ErrorCode {
ILLEGAL_STATE_SMD_ON_MULTIPLE_SGD (500,"SMP:144",ErrorBusinessCode.TECHNICAL,"Found than one service group domain for metadata id [%s] and user id [%s]!"),
// SML integration
SML_INTEGRATION_EXCEPTION (500,"SMP:150",ErrorBusinessCode.TECHNICAL,"Could not create new DNS entry through SML! Error: %s "),
SML_INTEGRATION_EXCEPTION (500,"SMP:150",ErrorBusinessCode.TECHNICAL,"SML integration error! Error: %s "),
//
XML_SIGNING_EXCEPTION (500,"SMP:500",ErrorBusinessCode.TECHNICAL,"Error occurred while signing response!"),
JAXB_INITIALIZATION (500,"SMP:511",ErrorBusinessCode.TECHNICAL, "Could not create Unmarshaller for class [%s]!"),
......
......@@ -94,8 +94,8 @@ public class DomainService {
}
/**
* If domain is not yet registered and sml integration is on. Than it tries to register domain and all participants
* on that domain. If integration is off it return an configuration exception.
* If domain is not yet registered and SML integration is on, it tries to register a domain and all participants
* on that domain. If integration is off, it returns a configuration exception.
* <p>
* Method is not in transaction - but sub-methods are. if registering domain or particular serviceGroup succeed
* then the database flag (SML_REGISTERED) is turned on ( if method fails
......
......@@ -65,6 +65,22 @@ public class SMLIntegrationService {
@Autowired
private IdentifierService identifierService;
/**
* Checks whether the participant exists in SML or not.
*
* @param resource the resource entity
* @param domain the domain entity
* @return {@code true} if the participant exists in SML; otherwise, {@code false} (also when SML integration is disabled).
*/
public boolean participantExists(DBResource resource, DBDomain domain) {
if (!isSMLIntegrationEnabled()) {
throw new SMPRuntimeException(CONFIGURATION_ERROR, ERROR_MESSAGE_DNS_NOT_ENABLED);
}
Identifier normalizedParticipantId = identifierService
.normalizeParticipant(resource.getIdentifierScheme(), resource.getIdentifierValue());
return smlConnector.participantExists(normalizedParticipantId, domain);
}
/**
* Method in transaction update domain status and registers domain to SML.
......@@ -82,6 +98,19 @@ public class SMLIntegrationService {
smlConnector.registerDomain(domain);
}
/**
* Checks whether the domain is valid by trying to read it from SML.
*
* @param domain the domain entity to verify whether it's valid or not.
*
* @return {@code true} if the domain can be successfully read from SML; otherwise, {@code false} (also when SML integration is disabled).
*/
public boolean isDomainValid(DBDomain domain) {
if (!isSMLIntegrationEnabled()) {
throw new SMPRuntimeException(CONFIGURATION_ERROR, ERROR_MESSAGE_DNS_NOT_ENABLED);
}
return smlConnector.isDomainValid(domain);
}
/**
* Method in transaction update domain status and registers domain to SML.
......@@ -171,7 +200,7 @@ public class SMLIntegrationService {
return;
}
// unregister only registered participants
// unregister only registered participants
if (resource.isSmlRegistered()) {
// update value
resource.setSmlRegistered(false);
......
......@@ -35,6 +35,7 @@ import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import eu.europa.ec.edelivery.smp.services.SMLIntegrationService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Service;
......@@ -64,7 +65,7 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
private final ConversionService conversionService;
private final GroupDao groupDao;
private final GroupMemberDao groupMemberDao;
private final SMLIntegrationService smlIntegrationService;
public UIDomainService(ConversionService conversionService,
DomainDao domainDao,
......@@ -73,7 +74,7 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
ResourceDefDao resourceDefDao,
DomainResourceDefDao domainResourceDefDao,
GroupDao groupDao,
GroupMemberDao groupMemberDao) {
GroupMemberDao groupMemberDao, SMLIntegrationService smlIntegrationService) {
this.conversionService = conversionService;
this.domainDao = domainDao;
this.resourceDao = resourceDao;
......@@ -82,6 +83,7 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
this.domainMemberDao = domainMemberDao;
this.groupDao = groupDao;
this.groupMemberDao = groupMemberDao;
this.smlIntegrationService = smlIntegrationService;
}
@Override
......@@ -175,6 +177,12 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
domain.setSmlSmpId(StringUtils.trim(data.getSmlSmpId()));
domain.setSmlClientKeyAlias(data.getSmlClientKeyAlias());
domain.setSmlClientCertAuth(data.isSmlClientCertAuth());
// if registered, validate the updated domain to ensure its SML integration certificate is valid
if(domain.isSmlRegistered() && !smlIntegrationService.isDomainValid(domain)) {
String msg = "The SML-SMP certificate for domain [" + domain.getDomainCode() + "] is not valid!";
throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, msg);
}
}
@Transactional
......
......@@ -19,6 +19,8 @@
package eu.europa.ec.edelivery.smp.sml;
import ec.services.wsdl.bdmsl.data._1.ExistsParticipantResponseType;
import ec.services.wsdl.bdmsl.data._1.ParticipantsType;
import ec.services.wsdl.bdmsl.data._1.SMPAdvancedServiceForParticipantType;
import eu.europa.ec.bdmsl.ws.soap.*;
import eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum;
......@@ -61,8 +63,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import static eu.europa.ec.edelivery.smp.conversion.SmlIdentifierConverter.toBDMSLAdvancedParticipantId;
import static eu.europa.ec.edelivery.smp.conversion.SmlIdentifierConverter.toBusdoxParticipantId;
import static eu.europa.ec.edelivery.smp.conversion.SmlIdentifierConverter.*;
import static eu.europa.ec.edelivery.smp.exceptions.SMLErrorMessages.*;
/**
......@@ -97,16 +98,13 @@ public class SmlConnector implements ApplicationContextAware {
private ApplicationContext ctx;
public boolean registerInDns(Identifier normalizedParticipantId, DBDomain domain, String customNaptrService) {
if (!configurationService.isSMLIntegrationEnabled()) {
return false;
}
String normalizedParticipantString = identifierService.formatParticipant(normalizedParticipantId);
if (!domain.isSmlRegistered()) {
LOG.info("Participant {} is not registered to SML because domain {} is not registered!",
LOG.warn("Participant {} is not registered to SML because domain {} is not registered!",
normalizedParticipantString, domain.getDomainCode());
return false;
}
......@@ -131,11 +129,47 @@ public class SmlConnector implements ApplicationContextAware {
}
}
/**
* Checks whether the participant identified by the provided ID exists or not. In case the integration with SML is
* disabled, it returns {@code false}.
*
* @param normalizedParticipantId the participant ID
* @param domain the domain entity
* @return {@code true} if the participant exists; otherwise, {@code false} (also when SML integration is disabled).
*/
public boolean participantExists(Identifier normalizedParticipantId, DBDomain domain) {
if (!configurationService.isSMLIntegrationEnabled()) {
return false;
}
String normalizedParticipantString = identifierService.formatParticipant(normalizedParticipantId);
if (!domain.isSmlRegistered()) {
LOG.warn("Cannot check if Participant {} exists when domain {} is not registered!",
normalizedParticipantString, domain.getDomainCode());
return false;
}
LOG.debug("Checking if Participant: {} exists in domain: {}.", normalizedParticipantString, domain.getDomainCode());
try {
ParticipantsType smlRequest = toParticipantsType(normalizedParticipantId, domain.getSmlSmpId());
ExistsParticipantResponseType existsParticipantResponseType = getBDMSLWSClient(domain).existsParticipantIdentifier(smlRequest);
return existsParticipantResponseType.isExist();
} catch (BadRequestFault e) {
return processSMLErrorMessage(e, normalizedParticipantId);
} catch (NotFoundFault e) {
return processSMLErrorMessage(e, normalizedParticipantId);
} catch (Exception e) {
LOG.error(e.getClass().getName() + e.getMessage(), e);
throw new SMPRuntimeException(ErrorCode.SML_INTEGRATION_EXCEPTION, e, ExceptionUtils.getRootCauseMessage(e));
}
}
protected void createRegularDNSRecord(Identifier normalizedParticipantId, DBDomain domain) throws UnauthorizedFault, BadRequestFault, NotFoundFault, InternalErrorFault {
LOG.debug("Set regular DNS record for Participant: [{}] and domain: [{}].", normalizedParticipantId, domain.getDomainCode());
ServiceMetadataPublisherServiceForParticipantType smlRequest = toBusdoxParticipantId(normalizedParticipantId, domain.getSmlSmpId());
getParticipantWSClient(domain).create(smlRequest);
}
protected void createCustomServiceNaptrDNSRecord(Identifier normalizedParticipantId, DBDomain domain, String customNaptrService) throws UnauthorizedFault, BadRequestFault, NotFoundFault, InternalErrorFault {
LOG.debug("Set custom naptr service [{}] DNS record for Participant: [{}] and domain: [{}].", customNaptrService, normalizedParticipantId, domain.getDomainCode());
SMPAdvancedServiceForParticipantType smlRequest = toBDMSLAdvancedParticipantId(normalizedParticipantId, domain.getSmlSmpId(), customNaptrService);
......@@ -182,19 +216,13 @@ public class SmlConnector implements ApplicationContextAware {
* @return
*/
public boolean registerDomain(DBDomain domain) {
if (!configurationService.isSMLIntegrationEnabled()) {
return false;
}
String smpLogicalAddress = configurationService.getSMLIntegrationSMPLogicalAddress();
String smpPhysicalAddress = configurationService.getSMLIntegrationSMPPhysicalAddress();
LOG.info("Registering new Domain to SML: (smpCode {} smp-smp-id {}) ", domain.getDomainCode(), domain.getSmlSmpId());
String smlSmpId = domain.getSmlSmpId();
LOG.info("Registering new Domain to SML: (smpCode {} smp-smp-id {}) ", domain.getDomainCode(), smlSmpId);
try {
ServiceMetadataPublisherServiceType smlSmpRequest = new ServiceMetadataPublisherServiceType();
smlSmpRequest.setPublisherEndpoint(new PublisherEndpointType());
smlSmpRequest.getPublisherEndpoint().setLogicalAddress(smpLogicalAddress);
smlSmpRequest.getPublisherEndpoint().setPhysicalAddress(smpPhysicalAddress);
smlSmpRequest.setServiceMetadataPublisherID(domain.getSmlSmpId());
ServiceMetadataPublisherServiceType smlSmpRequest = getServiceMetadataPublisherServiceType(smlSmpId);
getSMPManagerWSClient(domain).create(smlSmpRequest);
} catch (BadRequestFault e) {
processSMLErrorMessage(e, domain);
......@@ -206,6 +234,46 @@ public class SmlConnector implements ApplicationContextAware {
return true;
}
/**
* Checks whether a domain is valid or not. In case the integration with SML is disabled, it returns {@code false}.
*
* @param domain the domain entity
* @return {@code true} if the domain exists and is valid; otherwise, {@code false} (also when SML integration is disabled).
*/
public boolean isDomainValid(DBDomain domain) {
if (!configurationService.isSMLIntegrationEnabled()) {
return false;
}
String smlSmpId = domain.getSmlSmpId();
LOG.info("Validating Domain to SML: (smpCode {} smp-smp-id {}) ", domain.getDomainCode(), smlSmpId);
try {
ServiceMetadataPublisherServiceType smlSmpRequest = getServiceMetadataPublisherServiceType(smlSmpId);
getSMPManagerWSClient(domain).read(smlSmpRequest);
} catch (BadRequestFault e) {
processSMLErrorMessage(e, domain);
} catch (NotFoundFault e) {
processSMLErrorMessage(e, domain);
} catch (Exception e) {
LOG.error(e.getClass().getName() + e.getMessage(), e);
throw new SMPRuntimeException(ErrorCode.SML_INTEGRATION_EXCEPTION, e, ExceptionUtils.getRootCauseMessage(e));
}
// if not error is thrown - the domain exists and is valid
return true;
}
private ServiceMetadataPublisherServiceType getServiceMetadataPublisherServiceType(String smlSmpId) {
String smpLogicalAddress = configurationService.getSMLIntegrationSMPLogicalAddress();
String smpPhysicalAddress = configurationService.getSMLIntegrationSMPPhysicalAddress();
ServiceMetadataPublisherServiceType smlSmpRequest = new ServiceMetadataPublisherServiceType();
smlSmpRequest.setPublisherEndpoint(new PublisherEndpointType());
smlSmpRequest.getPublisherEndpoint().setLogicalAddress(smpLogicalAddress);
smlSmpRequest.getPublisherEndpoint().setPhysicalAddress(smpPhysicalAddress);
smlSmpRequest.setServiceMetadataPublisherID(smlSmpId);
return smlSmpRequest;
}
private void processSMLErrorMessage(BadRequestFault e, DBDomain domain) {
if (!isOkMessage(domain, e.getMessage())) {
LOG.error(e.getMessage(), e);
......@@ -303,13 +371,10 @@ public class SmlConnector implements ApplicationContextAware {
}
private IManageServiceMetadataWS getSMPManagerWSClient(DBDomain domain) {
IManageServiceMetadataWS iManageServiceMetadataWS = ctx.getBean(IManageServiceMetadataWS.class);
// configure value connection
configureClient(SERVICE_METADATA_CONTEXT, iManageServiceMetadataWS, domain);
return iManageServiceMetadataWS;
}
......@@ -330,9 +395,7 @@ public class SmlConnector implements ApplicationContextAware {
return alias;
}
public void configureClient(String serviceEndpoint, Object smlPort, DBDomain domain) {
String clientKeyAlias = getSmlClientKeyAliasForDomain(domain);
boolean clientCertAuthentication = domain.isSmlClientCertAuth();
Client client = ClientProxy.getClient(smlPort);
......@@ -383,7 +446,6 @@ public class SmlConnector implements ApplicationContextAware {
}
public void configureClientAuthentication(HTTPConduit httpConduit, Map<String, Object> requestContext, CertificateRO certificateRO, boolean clientCertAuthentication, boolean useTLS) {
LOG.info("Connect to SML (smlClientAuthentication: [{}] use Client-CertHeader: [{}])", certificateRO, clientCertAuthentication);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment