This page is out of date and will NOT be maintained any further.
The notes for the phoss SMP server will be kept up-to-date as it is an evolving implementation.
CIPA SMP 3.0 was released, but it does NOT support the PEPPOL SMP specification. It only supports the OASIS SMP specification which is currently NOT used in PEPPOL.

This page explains how to setup an OpenPEPPOL CIPA SMP from scratch. SMP is the abbreviation for Service Metadata Publisher which is the decentralized directory service of OpenPEPPOL. SMPs are normally only operated by Service Providers and not by endpoints. An SMP contains information about the endpoints of receivers - the URLs where to send the main documents to. The information within the SMP is structured by participant ID, document type ID and process ID.

Note: this page will not be updated to later versions, as my phoss SMP is imho much better

Prerequisites

Before you can start you need to have the following information in place:

  1. As the very first step you need to sign the TIAs (Transport Infrastructure Agreements) with OpenPEPPOL AISBL
  2. Afterwards you need to apply for an SMP certificate at OpenPEPPOL. This certificate is required to run the SMP.
  3. You should have a look at the official SMP specifications. It is important to understand that the specifications only specify the reading access to an SMP but not the writing access. Nevertheless the implementation discussed here also contains the possibility to write new entries.
  4. You should be familiar with Java 1.6+
  5. Basic knowledge of a relational database (e.g. MySQL) is required
  6. Basic knowledge about Apache Tomcat (and optionally a web server) should be present

Technical resources

The SMP software to be used can be obtained from the CIPA e-Delivery project maintained by the European Commission and hosted on joinup. The sources reside in a publicly accessible git repository. The old Subversion repository is no longer available, because the Joinup relaunch removed this feature,

The technical SMP resources are divided into the following elements:

  • smp-webapp - The SMP server that offers the query service. This server exists in two versions: one that supports only reading and one that supports reading and writing.
  • smp-client-library - An SMP client library to be used to access any SMP server.
  • smp-client-console - An SMP console client for querying the SMP from the commandline.

All of the components are available as ready-to-use Eclipse projects. The easiest way to build the projects is therefore to import the projects into Eclipse.

Hint when using Eclipse: it is best to close the project in Eclipse when a commandline build is performed because otherwise Eclipse might want to refresh while the console build is in progress. After the build finished you may re-open the project in Eclipse and clean it there again, because the Eclipse compiler and the Oracle console compiler produce incompatible byte code for enum classes!

smp-webapp

This is the main SMP server application. It is provided as a Java web application that can be deployed in an application server like Apache Tomcat or Jetty. This section assumes that you are using the complete SMP with read and write API. The respective CIPA project is called cipa-smp-full-webapp. Version 2.2.3 can be found on Joinup.

The SMP service has been implemented as a REST interface with a database backend. It is possible to change the backend, but the following description is based on a database backend. A copy of the MySQL database initialization script can be found in the /src/etc/database_backups/ folder of the cipa-smp-server-library project. By default a user peppol_user with the password Test1234 is created!

The service can be deployed in two ways:

  • Compiling the project on the command line using mvn clean install. The result is a WAR file in the target folder and additionally an exploded version of the WAR file in the target/cipa-smp-full-webapp-x.y.z directory (where x.y.z denotes the version number).
  • Start the application src/test/java/at/peppol/smp/server/jetty/RunInJettySMP from within Eclipse. Than the application will be running on localhost port 80 and can be accessed with a browser or an SMP client.

Metro 2.2.1-1 must be installed on the application server for the service to work since it makes use of the SML management client.

Note that the SMP service MUST be deployed as the ROOT web application (at path "/") on the application server, since this is a prerequisite in the DNS lookup scheme. Furthermore it MUST be deployed on port 80 (standard http port) and may not use SSL to secure the transport.

Configuring the service

The service is configured using a single configuration file src/main/resources/config.properties. The following list describes all the possible configuration items:

  • dataManager.class: The data manager implementation to use. The data manager is for retrieving the data to use in the REST service. The default class is eu.europa.ec.cipa.smp.server.data.dbms.DBMSDataManager.
  • registrationHook.class: The type of registration hook to use. The hook is used for notifying the SML of the creation or deletion of business identifiers. For testing purposes you may use the class eu.europa.ec.cipa.smp.server.hook.DoNothingRegistrationHook which does not communicate with the SML. For production use the class eu.europa.ec.cipa.smp.server.hook.RegistrationServiceRegistrationHook must be used, as it communicates with the SML and adds, updates or deletes participant DNS entries.
  • regServiceRegistrationHook.id: The SMP ID to use when using the SML interface.
    Note: it must be the same ID that was used for the initial registration of the SMP to the SML.
    Note: is only required if class RegistrationServiceRegistrationHook is used.
  • regServiceRegistrationHook.regLocatorUrl: The URL of the SML manage business identifier service. For production purposes (SML) use https://sml.peppolcentral.org/manageparticipantidentifier. For the test-SML (SMK) use the URL https://smk.peppolcentral.org/manageparticipantidentifier.
    Note: is only required if class RegistrationServiceRegistrationHook is used.
    Note: this is the field that needs to be changed for the SML migration on June 9th 2015!
  • regServiceRegistrationHook.keystore.classpath: The classpath - relative to the project - where the Java key store (of type JKS) with the SMP certificate is located. An empty directory src/main/resources/keystore is present which could contain the key store. In this case the properties entry should start with keystore/.
    Note: The key store should contain exactly one certificate entry with an arbitrary name and the certificate must have the same password as the whole key store!
    Note: is only required if class RegistrationServiceRegistrationHook is used.
  • regServiceRegistrationHook.keystore.password: The password used to access the key store.
    Note: is only required if class RegistrationServiceRegistrationHook is used.
  • xmldsig.keystore.classpath: Has the same semantics as regServiceRegistrationHook.keystore.classpath and should therefore have the same value.
  • xmldsig.keystore.password: Has the same semantics as regServiceRegistrationHook.keystore.password and should therefore have the same value.
  • xmldsig.keystore.key.alias: The alias of the key within the key store. Is case sensitive and may not be empty.
  • xmldsig.keystore.key.password: The password of the certificate with the above specified alias. Should be the same as the password of the whole key store (see xmldsig.keystore.password).
  • jdbc.driver: The JDBC driver class to be used by JPA. For MySQL use com.mysql.jdbc.Driver
  • jdbc.url: The JDBC URL of the database to connect to. For a local MySQL database called "smp" the string would look like this: jdbc:mysql://localhost/smp?autoReconnect=true
    Note: the URL depends on the JDBC driver used!
  • jdbc.user: The database user to be used when connecting to the database.
  • jdbc.password: The password of the JDBC user to be used when connecting to the DB
  • target-database: The JPA target database type to be used. For MySQL this value should be MySQL
    Note: Please see the documentation of EclipseLink for other target database systems!
  • jdbc.read-connections.max: The maximum number of JDBC connections to be used for reading. Usually 10 should be suitable for most use cases.

Example of a development config.properties file using a local MySQL database called smp without an SML connector (for easy testing):

## DBMS handler
dataManager.class=eu.europa.ec.cipa.smp.server.data.dbms.DBMSDataManager

## Registration callback (SML client caller)
registrationHook.class=eu.europa.ec.cipa.smp.server.hook.DoNothingRegistrationHook

## XMLDSIG response signing:
xmldsig.keystore.classpath    = keystore/keystore.jks
xmldsig.keystore.password     = peppol
xmldsig.keystore.key.alias    = smp keypair
xmldsig.keystore.key.password = peppol

## JDBC configuration for DB
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/smp
jdbc.user = smp
jdbc.password = smp
target-database = MySQL
jdbc.read-connections.max = 10

Example of a production-like config.properties file using a local MySQL database called smp with the SML connector (for close to production):

## DBMS handler
dataManager.class=eu.europa.ec.cipa.smp.server.data.dbms.DBMSDataManager

## Registration callback (SML client caller)
registrationHook.class=eu.europa.ec.cipa.smp.server.hook.RegistrationServiceRegistrationHook

# SMP ID
regServiceRegistrationHook.id=TEST-SMP-ID1
# SML URL (incl. the service name)
regServiceRegistrationHook.regLocatorUrl=https://sml.peppolcentral.org/manageparticipantidentifier
regServiceRegistrationHook.keystore.classpath = keystore/keystore.jks
regServiceRegistrationHook.keystore.password  = peppol

## XMLDSIG response signing:
xmldsig.keystore.classpath    = keystore/keystore.jks
xmldsig.keystore.password     = peppol
xmldsig.keystore.key.alias    = smp keypair
xmldsig.keystore.key.password = peppol

## JDBC configuration for DB
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/smp
jdbc.user = smp
jdbc.password = smp
target-database = MySQL
jdbc.read-connections.max = 10

Note: since the default Java properties file handling is used to read the configuration file recall that trailing whitespaces of a property name and leading white spaces of a property value are automatically skipped. Trailing whitespaces of a property value are not skipped!

Public REST API

The service is implemented as a REST interface using the Jersey framework. See the SMP specification for details on the intention of the REST URL paths.

The implementation contains four main REST classes, one for each path for which one can make queries:

  • /{ServiceGroupId} is implemented in the eu.europa.ec.cipa.smp.server.services.readwrite.ServiceGroupInterface class.
  • /{ServiceGroupId}/services/{DocumentTypeId} is implemented in the eu.europa.ec.cipa.smp.server.services.readwrite.ServiceMetadataInterface class.
  • /list/{UserId} is implemented in the eu.europa.ec.cipa.smp.server.services.common.ListInterface class.
  • /complete/{ServiceGroupId} is implemented in the eu.europa.ec.cipa.smp.server.services.common.CompleteServiceGroupInterface class.

The list interface is not part of the SMP specification and is used for getting a list of registered service groups for a given user. The complete interface is also not part of the specification and is used for getting the service group as well as all the service metadata for that group in a single call. Further the PUT and DELETE operations have also been implemented for ServiceGroupInterface and ServiceMetadataInterface. These four interfaces make use of the eu.europa.ec.cipa.smp.server.data.IDataManager interface to access the SMP data. The implementation currently contains one implementation of this interface which has a database as the underlying data source. The database version of the interface is implemented in the class eu.europa.ec.cipa.smp.server.data.dbms.DBMSDataManager and makes use of JPA (EclipseLink) for the main database access.

Modifying REST API

Some REST APIs are used to modify data within the SMP. Those APIs are not standardized by the PEPPOL SMP specifications and therefore are described here. All modifying REST APIs are either using HTTP PUT or HTTP DELETE for creating/updating or for deleting elements. As the SMP itself running without transport security these modifying methods require an HTTP BasicAuth header.

Note: to send an HTTP Basic Auth header you must provide an HTTP header called Authorization with a value like created by the following pseudo code: "Basic " + Base64.encode (userName + ":" + password)

Please see chapter on security considerations how to handle BasicAuth proper and secure.

A Java EE Filter is used for reverting changes to the SML, if the change to the SMP fails. If a HTTP status code different from 200 (OK) is returned from the REST interface, then the corresponding change made to the SML is reverted. This functionality is implemented in the class eu.europa.ec.cipa.smp.server.hook.PostRegistrationFilter.

A Jersey Filter has been added for generating the XML-DSIG element which is part of the response from a GET on Service Metadata interface. This is implemented in the class eu.europa.ec.cipa.smp.server.util.SignatureFilter.

  • ServiceGroupInterface
    • PUT /{ServiceGroupId}
      Expected body: A ServiceGroupType object as specified by the SMP XSD
      Description: create a new service group
    • DELETE /{ServiceGroupId}
      Expected body: none
      Description: Delete the whole service group with the specified service group ID. Implicitly deletes all related elements as well
  • ServiceMetadataInterface
    • PUT /{ServiceGroupId}/services/{DocumentTypeId}
      Expected body: A ServiceMetadataType object as specified by the SMP XSD
      Description: Define the AP endpoint URL etc. for a certain participant and a certain document type
    • DELETE /{ServiceGroupId}/services/{DocumentTypeId}
      Expected body: none
      Description: Delete all participant information for the specified document type

Security considerations

As the SMP is publicly available on HTTP port 80 and does not require a client certificate or anything the like it especially the modifying actions (HTTP PUT and DELETE) must be handled with special care to avoid man in the middle attacks. Even though HTTP BasicAuth is used this is not really added security, as the username and password are only Base64 encoded - which is easily decodable - and are therefore vulnerable to Man in the Middle attacks.

The recommended scenario is to additionally configure the SMP to run on HTTPS (on any port other than 80), and do the modifying actions only via HTTPS. BasicAuth is required anyway but the data is not readable by third-parties because of the underlying transport security. This is something that is currently technically not available but should be used as a convention when running an SMP with this implementation. For a future release it may be of value when the modifying actions are presented with a separate path prefix (e.g. /secure) which can than easily be used to forward all HTTP request on /secure/* to HTTPS automatically.

Initialization

Now that your new SMP server is up and running, you should perform some setup tasks.

  • Change the default user peppol_user with the default password Test1234 to something more complex! This can be easily achieved by altering the content of the database table smp_user manually. After this change, simply provide the new credentials for writing operations.
  • The SMP must be registered at the SML. For this purpose an online tool is integrated in this page to perform this task.

smp-client-library

This is the default Java library to query any SMP server (that is compliant to the specifications) for participant information. The client library has the sole purpose to provide reusable functionality. It does not offer executable functionality itself.

The eu.europa.ec.cipa.smp.client.SMPServiceCaller is the main class when using the library. The class contains methods for reading, saving and deleting both service groups and service metadata, as well as listing the service groups of a given user. The writing methods of this class can only be used in conjunction with the CIPA SMP server as for different implementation the write access may have been implemented in a different way. Alternatively the class eu.europa.ec.cipa.smp.client.SMPServiceCallerReadonly can be used to access any SMP that complies to the SMP specifications. The library contains both static and non-static methods for performing all of these actions. The class is documented using JavaDoc.

The following is an example code of getting a service metadata object of a service group (participant) for a certain document type:

// ServiceGroup = participant identifier; GLN = 0088
final ParticipantIdentifierType aServiceGroupID = EPredefinedIdentifierIssuingAgency.GLN.createParticipantIdentifier ("5798000000001");
// Document type identifier from enumeration
final DocumentIdentifierType aDocumentTypeID = EPredefinedDocumentTypeIdentifier.INVOICE_T010_BIS4A_V20.getAsDocumentTypeIdentifier ();
// Main call to the SMP client with the correct SML to use
final SignedServiceMetadataType aMetadata = new SMPServiceCallerReadonly (aServiceGroupID, ESMP.PRODUCTION).getServiceRegistrationOrNull (aServiceGroupID, aDocumentTypeID);
if (aMetadata == null)
{
  // No such metadata
}
else
{
  // Evaluate metadata
}

smp-client-console

This is a Java application that uses the smp-client-library to allow for SMP querying from the commandline. It can be executed on its own and also serves as an example on how to use the SMP client API.

It provides the following command line parameter:

ParameterDescription
-c COMMANDThe command to execute. Must be one of the following (case insensitive):
  • addgroup - create a new service group
  • delgroup - delete a service group
  • add - create a new service registration
  • del - delete a service registration
  • list - list all registrations for the given user name
-h HOSTURL of the SMP host to work on
-u USERNAMEThe username for the SMP
-p PASSWORDThe password for the SMP
-b BUSINESSID The participant ID of the business to handle. Must be in the PEPPOL specific format, without the common prefix. For example 0088:123456 would be a valid identifier.
Only required for the following commands: addgroup, delgroup, add, del
-a APURL The URL of the AccessPoint to register.
Only required for the following commands: add
-e PEMFILE File containing the Base64 encoded, DER encoded AP certificate (public key only).
Only required for the following commands: add
-r PROCESSID Process ID to perform operation on.
Only required for the following commands: add
-d DOCUMENTTYPEID Document type ID to perform operation on.
Only required for the following commands: add, del
You must be logged in to post a comment!