NAME
Net::AS2::PSGI - AS2 Protocol Plack application
VERSION
This documentation is for AS2 Protocol Version 1.0.
SYNOPSIS
### Create an AS2 PSGI Server
my $view_app = Net::AS2::PSGI->to_view_app();
my $server_app = Net::AS2::PSGI->to_server_app();
DESCRIPTION
This module defines an AS2 Protocol compliant Plack application.
The AS2 Protocol is specified by RFC 4130. This protocol defines a secure peer-to-peer data transfer with receipt using HTTP. The receipt is called a Message Disposition Notification (MDN) and is specified by RFC 3798.
The Public certificates between each partnership are exchanged independently. i.e. The AS2 protocol does not allow for the public certificate to be downloaded, they must be exchanged before any AS2 communication can occur.
Implementations of the AS2 Protocol extend the original RFC 4130 to allow for transfer over HTTPS and use of newer signing algorithms, e.g. the SHA-2 family.
The AS2 Protocol defines two modes, Synchronous and Asynchronous.
The supported AS2 Protocol version is 1.0. Version 1.1 (compression) is not supported.
- Synchronous
-
In this mode the data is POSTed from the sender to the receiver and the response is the MDN receipt.
- Asynchronous
-
In this mode the data is POSTed from the sender to the receiver but the response only confirms the data was sent.
The receiver on completion of receiving the data, POSTs the MDN receipt for the data back to the sender.
CONFIGURATION AND ENVIRONMENT
The server uses the following directories.
- certificate_dir
-
This directory contains Private and Public Certificate pairings and the Public Certificate for each defined Partnership.
For security, this directory and the files within it should not be world readable.
An alternative, is to either supply the key and certificate text strings directly in the Net::AS2 hash or supply an alternative directory per partnership, using the
CertificateDirectory
Net::AS2 hash key. - partnership_dir
-
This directory contains JSON files that each define a partnership between two AS2 Protocol Servers.
Subdirectories may be used, with the whole relative path being used to define the partnership name.
For security, this directory and the files within it should not be world readable.
The partnership file contains the key names defined in Net::AS2, along with the following additions:
- FileHandlerClass
-
A Perl class that can process the files being sent and received via the AS2 protocol. See Net::AS2::PSGI::FileHandler, default is "Net::AS2::PSGI::FileHandler".
- file_dir
-
This directory will contain either files received from a partnership transfer or an MDN after sending data to a partnership.
For security, this directory and the files within it should not be world readable.
The directory structure is as follows:
- partnership
-
The subdirectory structure is created and named after the partnership file (without the .json extension). For security, this directory structure is created with owner read/write only.
The files being transferred between this partnership are then stored under the following directories:
- SENDING
-
Files here are being sent to the partner, but no receipt has been received yet.
- SENT
-
Files here have been sent to the partner and a receipt has been received.
- RECEIVING
-
Files here are being received from the partner, but no receipt has been sent yet.
- RECEIVED
-
Files here have been received from the partner and a receipt has been sent.
SUBROUTINES
- init ( $config, $log )
-
Class Method for initialising the AS2 directory structures.
- view_psgi ()
-
Class Method returning a PSGI application for viewing partnerships.
This app is not part of the AS2 specification. It may be useful for checking end-to-end access between partners and confirming partnership configurations.
- app_psgi ()
-
Class Method returning a PSGI application for AS2.
- app ( request )
-
API Method implementing AS2.
API METHODS
All API methods receive a Plack request as their one and only argument.
- send ( request )
-
To send data to a partner, a POST request is created with a URL of the form /send/
partnership
The data is sent as the content of the POST request along with the following headers:
- MessageId
-
The AS2 Message ID.
The Message ID is validated to ensure it conforms to RFC 822.
In Asynchronous mode, the received MDN will include this value as the
Original Message ID
, thus tying the two independent POST requests (send and MDN receipt) together, to complete the transfer. - Content-Type
-
The Content-Type of the data being sent.
- Subject
-
Optional. The subject is an arbitrary brief one-line string. Default is "AS2 Message".
- Filename
-
Optional. Sets the Content-Disposition filename. Default is "payload".
- receive ( request )
-
To receive data from a partner, a POST request is received via a URL of the form /receive/
partnership
The data is received as the content of the POST request along with the following headers:
- Message-Id
-
The AS2 Message ID.
The Message ID is validated to ensure it conforms to RFC 2822.
- Content-Type
-
The Content-Type of the data being received.
- AS2-Version
-
The AS2 Protocol version, it should be in the form 1.x. Only 1.0 is supported.
See RFC 4130 for further details about the different version numbers.
- AS2-From
-
The partner's AS2 ID.
This value should match the PartnerId in the
partnership.json
file. - AS2-To
-
The receiver's (i.e. this application's) AS2 ID.
This value should match the MyId in the
partnership.json
file. - Disposition-Notification-Options
-
Optional This header is only defined if digital signatures are requested.
This header contains the requirements for the digital signature. An example is:
signed-receipt-protocol=required, pkcs7-signature; signed-receipt-micalg=required, sha256
- Receipt-Delivery-Option
-
Optional This header is only defined for Asynchronous mode.
This header defines a URL for the receiver to POST the MDN receipt to, once the data has been received.
- MDNsend ( request )
-
Sends an MDN message to a partner.
The POST request is created with a URL of the form /MDNsend/
partnership
along with the following headers:- MessageId
-
The AS2 Message ID.
The Message ID is validated to ensure it conforms to RFC 2822.
In the RECEIVING directory, the file containing the saved MDN state of the given Message ID is read and an MDN response is created from the content. The MDN response is POSTed to the partner.
If the POST fails, the POST response code and content is stored in a file called
Message-Id
.Timestamp: %F-%H-%M-%S
.mdn-failed in the RECEIVING directory and the POST response code is returned.Otherwise, the data file is moved from the RECEIVING directory to RECEIVED and the MDN state file is moved from the RECEIVING directory to RECEIVED and renamed to have a .sent extension. If the MDN message is not indicating success, the data filename is also renamed to have a .failed extension.
- MDNreceive ( request )
-
Receives an MDN receipt from a partner.
The POST request is received via a URL of the form /MDNreceive/
partnership
The received MDN is decoded.
If the receipt is for a successful transfer, the Original Message ID is extracted and the file in the SENDING directory is moved to the SENT directory and its contents replaced with the decoded MDN details.
Otherwise, the MDN details are stored in SENDING directory with a filename called UNKNOWN.MDN.
Message-Id
with a 200 HTTP response being returned.- Message-Id
-
The AS2 Message ID.
The Message ID is validated to ensure it conforms to RFC 2822.
- Content-Type
-
The Content-Type of the data being received.
- AS2-Version
-
The AS2 Protocol version, it should be in the form 1.x. Only 1.0 is supported.
See RFC 4130 for further details about the different version numbers.
- AS2-From
-
The partner's AS2 ID.
This value should match the PartnerId in the
partnership.json
file. - AS2-To
-
The receiver's (i.e. this application's) AS2 ID.
This value should match the MyId in the
partnership.json
file.
- view ( env )
-
View a given partnership configuration.
The request is received via a URL of the form /view/
partnership
The actual content of the cached private key or certificates are not displayed, replaced instead by "...".
EXAMPLES
This module has an /examples directory. It contains an example PSGI application, its base configuration file, a systemd service for starman and an nginx conf file with SSL configurations. There is also some basic configuration files to get you started with partnering up with an instance of https://github.com/phax/as2-server.
The module's /t testing directory, includes test cases that forks AS2 Plack::Test applications, and then tests transferring files between using AS2 synchronous and AS2 asynchronous transfer modes.
SEE ALSO
Net::AS2, Net::AS2::PSGI::FileHandler, Net::AS2::PSGI::StateHandler
RFC 4130, RFC 3798, RFC 822, RFC 2822
LICENSE AND COPYRIGHT
This software is copyright (c) 2019 by Catalyst IT, <ajm@cpan.org>
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
BUGS AND LIMITATIONS
- Content-Transfer-Encoding: binary and LF line-endings
-
During testing against an Oracle B2B implementation, an issue with Digital Signatures was found. The Oracle instance was sending data with LF line-endings using binary Content-Transfer-Encoding.
The Crypt::SMIME validation failed the signature check.
A similar scenario occurred when testing with RSSBus software. In that case, just sending the file with CRLF line-endings was successful. It was not possible to test whether the same workaround would work with Oracle B2B. Another possibility is to configure sending/receiving base64 Content-Transfer-Encoding requests.
The issue may lie in the OpenSSL canonicalisation code when handling binary Content-Transfer-Encoding data. It appears to incorrectly apply canonicalisation of binary specified data. (OpenSSL version 1.1.0g).
- AS2 1.1 compression
-
The AS2 Protocol Version 1.1 (compression) is not supported.
- Filesystem initiated interface
-
Unlike other AS2 software, this module does not provide a means to send file to partners simply by copying a file to a designated 'send' directory. That functionality could probably be created by combining AnyEvent, Twiggy and this PSGI interface.
DISCLAIMER OF WARRANTY
This module is not certificated by any AS2 body. This module creates a basic AS2 server.
When using this server, you must have reviewed and be responsible for all the actions and inactions caused by this server.
More legal jargon follows:
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
AUTHOR
Andrew Maguire ajm@cpan.org