1. Introduction and Goals
1.1. Introduction
The Payment Service Directive 2 (PSD2) instructs banks to provide a fully productive Access-to-Account (XS2A) interface to Third Party Provider (TPPs) until September 2019. XS2A itself consists of banking services to initiate payments (PIS), request account data (AIS) and get the confirmation of the availability of funds (PIIS). In order to guarantee the compliance of this deadline due to adaptions and bugs, PSD2 claims the banks to provide a functional sandbox offering the XS2A services in a non-productive environment until March 2019.
1.1.1. Details about PSD2
PSD2 is aiming to open banks to TPPs in a harmonized and high secure manner. A reason for passing this directive is to innovate banking applications by introducing new non-banking players and make banking more attractive to the end consumer.
PSD2 itself is an EU directive describing requirements for banks on a very high level embedded in law paragraphs. The document contains links to Regulatory Technical Standards (RTS) prescribing technical descriptions like the Strong Customer Authentication (SCA). Those documents are very abstract and still close to the law which is a great challenge to interpret them correctly.
The Berlin-Group Initiative NextGenPSD2 joint forces to create an open specification of the XS2A to harmonize this interface. Amongst NextGenPSD2 a few other players like OpenBanking and STET are aiming to achieve the same goals.
1.1.2. PSD2 Accelerator Project
According to the law every European bank must provide a sandbox so that TPPs can begin integrating against it. The adorsys PSD2 Accelerator is a full implementation of this sandbox. It provides an XS2A API which is compliant to the Berlin Group XS2A spec (Version 1.3).
Besides the actual interface, PSD2 instructs banks to offer a technical documentation free of charge containing amongst others, information about supported payment products and payment services. That documentation is provided by us as well.
In order to access the XS2A services a TPP has to register at its National Competent Authority (NCA) and request an QWAC certificate from a Trust Service Provider (TSP). The PSD2 Accelerator allows TPPs to create test certificates by themselves so they can access the API. The certificates are valid QWAC certificates, signed by a custom PSD2 Accelerator CA.
The PSD2 Accelerator project bundles the described PSD2 components created at adorsys. The project is a self contained application which enables customers to provide a PSD2 compliant API for testing.
1.2. Requirements Overview
The PSD2 Accelerator has to fulfill the following requirements:
-
Get banks compliant to the law in March 2019
-
Be configurable to match the banks business features
-
Make the technical documentation of the XS2A interface accessible
-
Allow TPPs to test services based on test data
-
QWAC (certificate for authentication as specified in ETSI, eIDAS) can be issued by the TPP itself and used as in the real world
1.3. Quality Goals
Quality Goal | Scenario |
---|---|
PSD2 Compliance |
The PSD2 Accelerator must be PSD2 compliant. Neither ease of use nor cool technologies help the user if they fail the audit because of us. |
Fast Onboarding |
As a potential user of the PSD2 Accelerator you should be able to get the application running within minutes. We need to provide good documentation, sensible defaults and a simple setup. |
Simple Deployment |
The PSD2 Accelerator should be easy to deploy in enterprise contexts. This requires a simple architecture (e.g. not too many deployments, proven technology) and good documentation. |
1.4. Stakeholders
Name | Role | Contact | Expectation |
---|---|---|---|
Denys Golubiev |
Software Architect PSD2 |
|
|
Francis Pouatcha |
Software Architect PSD2, Sales |
|
|
Peer Schmid |
Portfolio Manager PSD2 |
|
|
Rene Pongratz |
Sales |
|
|
Stefan Hamm |
Sales |
|
1.5. Product Team
Name | Role | Contact |
---|---|---|
Andreas Winter |
Developer |
|
Annina Kiupel |
Product Owner |
|
Isabella Ionescu |
Developer |
|
Jana Tiimus |
Developer |
|
Nadja Krendel |
Agile Coach |
|
Roman Ataman |
Developer |
|
Sebastian Wild |
Developer |
|
Petro Rudenko |
Developer |
2. Architecture Constraints
3. System Scope and Context
3.1. Business Context

Neighbor | Description | ||
---|---|---|---|
👤 TPP Developer |
Registers at the PSD2 Accelerator in order to gain access to the test API and documentation |
||
👤 Bank Admin |
Configures the PSD2 Accelerator and manages TPPs |
||
👤 Bank Ops |
Deploys the PSD2 Accelerator. Needs proper documentation, access to logs, … Simple deployment is a central quality goal we design for, so the user is mentioned here. |
||
Bank CMS |
We assume that potential customers already have some sort of Content-Management-System in place we need to integrate with. So we must be able to provide content (e.g. documentation) in a format that’s easy to work with (e.g. favor plain text over PDF). The CMS could be an API management solution as well, depending on the customers infrastructure.
|
4. Solution Strategy
Note
|
This area is TODO! (rat) |
The PSD2 Accelerator bundles two top level components: the sandbox and the ssl-proxy. The sandbox contains the XS2A API, does the certificate handling and provides documentation in the developer portal. The ssl-proxy is responsible for doing SSL Client Authentication and is basically "just" infrastructure which does the SSL part and forwards the certificate as HTTP header. Most customers will provide their own implementation of it.
4.1. TPP Certificate Handling
Issuing a real certificate just for testing purposes would be a bit too much effort, which is why the PSD2 Accelerator acts as a TSP issuing Qualified Website Authentication Certificates (QWAC) valid only for the PSD2 Accelerator. A QWAC is defined in eIDAS and is implemented as a X.509 certificate.
For PSD2-purposes the certificate gets extended by the QcStatement containing appropriate values such as the role(s) of the PSP (see ETSI).
After embedding the QWAC in the actual XS2A request, the role and the signature get validated at a central reverse proxy before it gets finally passed to the interface where the banking logic happens. The technical documentation of the XS2A interface can be accessed here.
5. Building Block View
5.1. Whitebox Overall System

- Motivation
-
The application is designed as a modular monolith and uses Spring Boot 1.5. Every independent feature "xyz" maps to a top level package (
de.adorsys.psd2.sandbox.xyz
) (backend) or a top level folder (src/app/xyz
) (UI). The UI is implemented as an Angular app and bundled at build time in the backend JAR. The PSD2 Accelerator consists of the sandbox and the ssl-proxy. - Contained Building Blocks
Name | Responsibility |
---|---|
certificate-generator |
Create QWAC certificates to allow TPPs access to the XS2A API via SSL Client Authentication |
developer-portal |
 Provide documentation about the API (e.g. OpenAPI), supported use cases (XS2A), getting started and examples in one place. The content is static but embedded in the Angular app. |
ssl-proxy |
Infrastructure component which does SSL termination and SSL Client Authentication for XS2A. The ssl-proxy forwards the SSL Client certificate to XS2A. Since the ssl-proxy is part of the infrastructure, the actual implementation varies. Our own PSD2 Accelerator deployment uses our bundled NGINX (which also acts as reverse proxy). Customers may substitute it with their own hard- or software solution (HA-Proxy, F5, …). |
xs2a |
Provides the actual XS2A REST API |
config |
 Configure the PSD2 Accelerator and XS2A API (e.g. supported payment products). Just a YAML file right now. |
testdata |
 Manages static test data and allows some configuration. |
5.2. Level 2
5.2.1. White Box xs2a

Name | Responsibility |
---|---|
PIS |
Provide the Payment Initiation Service implementation for XS2A (implements interface from |
AIS |
Provide the Account Initiation Service implementation for XS2A (implements interface from |
PIIS |
Provide the Payment Issuer Instruments implementation for XS2A (implements interface from |
profile (library) |
Expose the XS2A configuration via REST API. The actual values come from the top level config module. Is provided by the Part of the adorsys PSD2 XS2A implementation. |
consent-management (library) |
Handle consents for us. Every payment or account information needs/creates a consent. Is
provided by the Part of the adorsys PSD2 XS2A implementation. |
xs2a-impl (library) |
Provide the XS2A business implementation (e.g. validation, handling of consents via Part of the adorsys PSD2 XS2A implementation. |
6. Runtime View
6.1. <Runtime Scenario 1>
-
<insert runtime diagram or textual description of the scenario>
-
<insert description of the notable aspects of the interactions between the building block instances depicted in this diagram.>
6.2. <Runtime Scenario 2>
6.3. …
6.4. <Runtime Scenario n>
7. Deployment View
7.1. adorsys Sample Setup
The PSD2 Accelerator consists of two deployments. The sandbox itself provides the XS2A API and a web application (and its API) for the developer portal. These two components are provided by a single fat JAR but served on different ports. XS2A is hosted on port :8080
and the developer portal is hosted on port :8081
(both configurable). XS2A needs access to a database to persist the Consent Management state. The configuration for the sandbox is completely externalized (see Configuration).
The ssl-proxy deployment is responsible for SSL Client Authentication required by XS2A. It forwards the certificate body to the sandbox in an HTTP header (tpp-qwac-certificate
). So SSL termination has to happen here, at least for the XS2A API part. The ssl-proxy only validates the SSL client certificate because certain parts of the API are accessible without authentication (e.g. the Swagger file and Swagger UI).
The sandbox acts as a Certificate Authority (CA) and provides SSL Client Certificates to the TPP developers. The ssl-proxy needs access to the sandbox CA certificate in order to verify the TPP SSL client certificates (see Configuration).
ssl_proxy listens on :8443
(actual reverse proxy) and :8090
(health check).
Warning
|
The supplied ssl-proxy is only meant to be used in development and must be substituted by an equivalent infrastructure component in prod (see Deploy on Your Own Infrastructure). |
In our own setup on OpenShift both components of the sandbox are available on different subdomains. The OpenShift loadbalancer terminates SSL for the developer portal and does SSL passthrough for the XS2A API so that the ssl-proxy can terminate SSL itself.
Note
|
In reality all (SSL) traffic get passed through the Load Balancer to the ssl-proxy. The ssl-proxy then does SSL termination for both endpoints but SSL client authentication only for the XS2A API. We need this so we can start the exact same setup as on OpenShift with docker-compose for local development. This is not a good idea for production. |
7.2. Release Artifacts
We use GitHub Releases to publish our release notes, the Sandbox JAR and its SHA1 checksum.
Docker Images are released to adorsys DockerHub account.
Artifact | Image Name |
---|---|
sandbox |
adorsys/psd2-sandbox:2.0.0-SNAPSHOT |
ssl-proxy |
adorsys/psd2-sandbox-ssl-proxy:2.0.0-SNAPSHOT |
$ docker run -it --rm -v $PWD:/target adorsys/psd2-sandbox:2.0.0-SNAPSHOT sh -c "cp /opt/app-root/src/*.jar /target"
To build your own Docker images get the JAR from our image or use Docker Multi Stage Builds:
FROM openjdk:8
COPY --from=adorsys/psd2-sandbox:2.0.0-SNAPSHOT /opt/app-root/src/sandbox-2.0.0-SNAPSHOT.jar .
CMD java -jar sandbox-2.0.0-SNAPSHOT.jar
7.3. Configuration
Configuration is done via Spring Boot Externalized Configuration and can be set via CLI arg, system property or environment variable. Since we intensively use Docker in our setup and environment variables are the idiomatic approach to configuration there, we stick to environment variables in the examples.
Note
|
Spring Boot automatically translates properties to environment variables. The environment variable SPRING_DATASOURCE_URL sets the property spring.datasource.url . Consult the Spring Boot documentation for more information.
|
7.3.1. Sandbox
Property | Description | Default |
---|---|---|
BANK_PROFILE_PATH |
File path to the customized Possible values could be This is the actual business configuration reflecting the PSD2 features your bank offers. You can find the relevant documentation for this file at the XS2A GitHub Project. For an example and the actual default values used in the sandbox see the Sample bank_profile.yml below. |
Points to the default |
SANDBOX_TESTDATA_TRANSACTIONS_PATH |
Path and filename of the custom transaction data |
Points to the default |
SANDBOX_TESTDATA_USD_ENABLED |
Enables/Disables the account with the currency US-Dollar of PSU-Successful. Possible values are: true or false |
true |
CERTIFICATE_FILTER |
Set to the format of the QWAC certificate in the |
tab |
SANDBOX_FEATURE_UI_ENABLED |
Enables/Disables the Sandbox UI. Possible values are: true or false |
true |
SPRING_DATASOURCE_PASSWORD |
DB password |
(not set) |
SPRING_DATASOURCE_URL |
JDBC URL |
(not set) |
SPRING_DATASOURCE_USERNAME |
DB username |
(not set) |
SPRING_JPA_PROPERTIES_HIBERNATE_DEFAULT_SCHEMA |
DB schema name (depends on used DB and configuration) |
(not set) |
SANDBOX_FEATURE_UI_CERTPAGE_ENABLED |
Enables/Disables the certificate page in the ui Possible values are: true or false |
true |
SANDBOX_UI_CONTACT_MAILTO |
Contact email address Format: mailto:YOUR@MAILADRESS.DE |
|
SANDBOX_UI_LOGO_URL |
URL to customized ui logo |
Points to the default psd2-accelerator logo embedded in the application |
SANDBOX_UI_CONTENT_URLS_DE_CERT |
URL to customized german markdown file for certificate page |
Points to the default german |
SANDBOX_UI_CONTENT_URLS_DE_FAQ |
URL to customized german markdown file for faq page |
Points to the default german |
SANDBOX_UI_CONTENT_URLS_DE_PORTAL |
URL to customized german markdown file for portal page |
Points to the default german |
SANDBOX_UI_CONTENT_URLS_EN_CERT |
URL to customized english markdown file for certificate page |
Points to the default english |
SANDBOX_UI_CONTENT_URLS_EN_FAQ |
URL to customized english markdown file for faq page |
Points to the default english |
SANDBOX_UI_CONTENT_URLS_EN_PORTAL |
URL to customized english markdown file for portal page |
Points to the default english |
LOGGING_CONFIG |
Location of the logback configuration |
classpath:logback.xml |
CONSOLE_LOG_PATTERN |
Sandbox log pattern (note: |
[%-5level][%d{HH:mm:ss.SSS}] - %logger: %message%n%xException |
Warning
|
It is required to enable CORS in the service which serves the customized markdown files for the UI. Otherwise the content can’t be loaded and stays empty. |
---
setting:
frequencyPerDay: 5
combinedServiceIndicator: false
scaApproaches:
- REDIRECT
tppSignatureRequired: false
bankOfferedConsentSupport: true
pisRedirectUrlToAspsp: http://localhost:8080/v1/online-banking/init/pis/{redirect-id}
pisPaymentCancellationRedirectUrlToAspsp: http://localhost:8080/v1/online-banking/cancel/pis/{redirect-id}
aisRedirectUrlToAspsp: http://localhost:8080/v1/online-banking/init/ais/{redirect-id}
multicurrencyAccountLevel: SUBACCOUNT
availableBookingStatuses:
- BOOKED
- PENDING
- BOTH
supportedAccountReferenceFields:
- IBAN
consentLifetime: 0
transactionLifetime: 0
allPsd2Support: true
transactionsWithoutBalancesSupported: true
signingBasketSupported: false
paymentCancellationAuthorizationMandated: true
piisConsentSupported: false
redirectUrlExpirationTimeMs: 600000
authorisationExpirationTimeMs: 86400000
notConfirmedConsentExpirationPeriodMs: 86400000
notConfirmedPaymentExpirationPeriodMs: 86400000
supportedPaymentTypeAndProductMatrix:
SINGLE:
- sepa-credit-transfers
PERIODIC:
- sepa-credit-transfers
paymentCancellationRedirectUrlExpirationTimeMs: 600000
availableAccountsConsentSupported: false
scaByOneTimeAvailableAccountsConsentRequired: true
psuInInitialRequestMandated: false
forceXs2aBaseUrl: false
xs2aBaseUrl: http://myhost.com/
scaRedirectFlow: REDIRECT
deltaListSupported: false
entryReferenceFromSupported: false
supportedTransactionApplicationTypes:
- application/json
startAuthorisationMode: auto
Customizing the Test Data
The IBANs of the different PSUs we provide are configurable. There is a default configuration in place which uses a made up routing number (DEXX76036568XXXXXXXXXX).
sandbox:
testdata:
psus:
"PSU-Successful":
- DE11760365688833114935 # GIRO
- DE13760365689669622432 # SAVINGS
- DE07760365680034562391 # EMPTY GIRO
- DE89760365681134661389 # NEGATIVE BALANCE GIRO
- DE71760365681257681381 # LOWER BALANCE GIRO
- DE56760365681650680255 # USD GIRO
"PSU-Rejected":
- DE06760365689827461249
"PSU-Cancellation-Rejected":
- DE68760365687914626923
"PSU-Blocked":
- DE13760365681209386222
"PSU-InternalLimit":
- DE91760365683491763002
"PSU-Pending":
- DE06760365680304199226
"PSU-ConsentExpired":
- DE12760365687895439876
"PSU-ConsentRevokedByPsu":
- DE89760365681729983660
Every PSU has one or more accounts. The account order does matter (e.g. the first IBAN of PSU-Successful is always picked for the giro account). You can override the configuration by placing an edited copy in $CWD/config/testdata.yml
next to the JAR.
Warning
|
Make sure that every IBAN you use is valid. We do not check externally set IBANs for correctness. If you use invalid IBANs, you might encounter problems when interacting with the XS2A API or with external systems. If a PSU has more than one IBAN, you need to supply all of them or the application won’t start. To help with configuration and debugging, the effective TestDataConfiguration is logged (INFO ) to the console at startup.
|
Besides the IBANs it is also possible to import transaction data using a CSV file (see [propertyTable]). The data will then replace the transactions of the giro account of the PSU_Successful
.
The format of the CSV file must match the following example:
bookingStatus|endToEndId|mandateId|creditorId|bookingDate|valueDate|currency|amount|creditorName|creditorIban|creditorAccountCurrency|ultimateCreditor|debtorName|debtorIban|debtorAccountCurrency|ultimateDebtor|remittanceInformationUnstructured|remittanceInformationStructured|purposeCode|bankTransactionCode|proprietaryBankTransactionCode
booked||||2018-08-12|2018-08-12|EUR|-52.93|Tankstelle Weyarn Munchener Strase 32//Weyarn/DE|DE98760365686066861064|EUR||Isabella Ionescu|DE13760365689669622432|EUR||2018-07-20T15:08 Debitk.3 2019-03|2018-07-20T15:08 Debitk.3 2019-03|OTHR|5|5
booked||||2018-08-01|2018-08-01|EUR|2500|Felix Borchert & Söhne GmbH|DE22760365683809366106|EUR||Isabella Ionescu|DE13760365689669622432|EUR||Gehalt August 2018|Gehalt August 2018|OTHR|5|5
booked||||2018-02-01|2018-02-01|EUR|-17.50|CLIMBING-SOLUTIONS GMBH//Stuttgart/DE|DE43760365682351770687|EUR||Isabella Ionescu|DE13760365689669622432|EUR||2018-10-08T11:05 Debitk.3 2029-03|2018-10-08T11:05 Debitk.3 2029-03|OTHR|5|5
booked||||2018-08-18|2018-08-18|EUR|-830|Hans Schlegl|DE33760365683971994750|EUR||Isabella Ionescu|DE13760365689669622432|EUR||Miete, Grünwälderstr. 49, 2.OG rechts|Miete, Grünwälderstr. 49, 2.OG rechts|OTHR|5|5
pending|||||2019-02-01|EUR|-67|Strom-Gesellschaft NĂĽrnberg|DE31760365686202206855|EUR||Isabella Ionescu|DE13760365689669622432|EUR||KTO 84633821 Abschlag 67,00 EUR faellig 01.08.18 Moritz-Str. 12|KTO 84633821 Abschlag 67,00 EUR faellig 01.08.18 Moritz-Str. 12|OTHR|5|5
The CSV must comply with the following restrictions:
-
The columns must be separated by
|
-
A header line is mandatory and must match the example
-
Dates must be in the ISO format (YYYY-MM-DD)
-
Payment amounts must use
.
instead of,
as floating point separator -
Empty lines will be skipped
See Configuration for more information about the Spring Boot configuration mechanism.
7.3.2. ssl-proxy
Property | Description | Default |
---|---|---|
API_INTERNAL_URL |
Internal URL where the XS2A API is reachable (set in docker-compose) |
|
API_EXTERNAL_URL |
External URL where the XS2A API is reachable (set in docker-compose) |
|
PORTAL_INTERNAL_URL |
Internal URL where the developer portal is reachable (set in docker-compose) |
|
PORTAL_EXTERNAL_URL |
External URL where the developer portal is reachable (set in docker-compose) |
|
File | Description | Default |
---|---|---|
/opt/app-root/etc/nginx.pem |
SSL Certificate |
self signed one from adorsys |
/opt/app-root/etc/nginx.key |
PK to SSL Certificate |
random PK for the self signed certificate |
/opt/app-root/etc/ca.crt |
PSD2 Accelerator CA Certificate |
default adorsys CA certificate |
Note
|
The PSD2 Accelerator CA certificate (ca.crt) is already embedded in the ssl-proxy. If you supply your own instance of this component you need to configure the proper SSL and CA certificates there. You can get the PSD2 Accelerator CA certificate by extracting it from the ssl-proxy image. See Deploy on Your Own Infrastructure for more details. |
7.4. Deploy on Your Own Infrastructure
The PSD2 Accelerator deployment is quite flexible. The only required component is the sandbox and its DB.
While we release Docker images only, the sandbox can be run on any machine providing a recent JDK 8 (see [Technology Requirements]). See Release Artifacts to find out how to get the JAR.
Warning
|
As of now we release Docker Images with a Spring Boot fat JAR with an embedded Tomcat only. We do not release the sandbox as a WAR (yet). |
The ssl-proxy can (and should) be substituted by existing infrastructure. There are many options which components can replace our ssl-proxy. Most likely it’s going to be some kind of load balancer in hardware (F5) or software (HAProxy, some API Gateway). It’s only purpose is SSL Client Authentication and forwarding the SSL Client Certificate (QWAC) in PEM format (single line or tab delimited, see Configuration) in an HTTP header named tpp-qwac-certificate
to the sandbox (see adorsys Sample Setup).
The connection between sandbox and any SSL-Proxy is made on the SSL-Proxy side with custom configuration. The only information that comes from the sandbox is the Sandbox CA Certificate (ca.crt). You will need to make this file accessible to your SSL-Proxy.
# copy ca.crt from the image to the current directory
$ docker run -it --rm -v $PWD:/target adorsys/psd2-sandbox-ssl-proxy:2.0.0-SNAPSHOT sh -c "cp /opt/app-root/etc/ca.crt /target"
See NGINX SSL Configuration for an actual sample of our NGINX configuration.
7.4.1. Technical Requirements / Sizing
-
the sandbox needs a recent JDK 8 (if you aren’t using the Docker Image)
-
HA setup is possible
-
all state is shared in the DB
-
zero downtime deployments are not guaranteed (see the note about DB migrations)
-
DB availability depends on your setup
-
supported databases (see Use Your Own Database):
-
PostgreSQL 9+
-
Oracle 11g+
-
MariaDB 10+
-
-
2-4 GiB RAM per sandbox deployment is a good starting point for prod (monitor this!)
-
ssl-proxy needs 128 - 512 MiB RAM (don’t use in prod!)
-
the DB schema needs enough disk space because consents are persisted here (grows over time) (monitor this!)
7.4.2. Logging
We use a modified Spring Boot logging configuration with logback and log everything to stdout.
-
FILE
appender is disabled -
additional
access-log
logger which logs TPP access -
default configuration parameters for the
CONSOLE
are supported
The default log level is INFO
. Set a different level with LOGGING_LEVEL_ROOT=WARN
(global) or with LOGGING_LEVEL_de.adorsys.psd2=WARN
(for everything below de.adorsys.psd2
; please note the casing).
To use a custom log configuration start the PSD2 Accelerator with -Dlogging.config=my-logging-config.xml
to use your file at $CWD/my-logging-config.xml
. See Configuration
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
<logger name="access-log" level="info" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>
Warning
|
If you use your own logback.xml we can’t guarantee that the default Spring Boot configuration properties still work. Please check the docs thoroughly. Have a look at the Spring Boot logging configuration, the Logback Documentation and our logback.xml to see whats possible.
|
7.4.3. Production Ready Features
Health Checks
There are health check endpoints for both deployments. They return 200 OK
when healthy.
Using the Actuator Features
We use Spring Boot Actuator for metrics, health checks and information about the deployment. Per default there are four endpoints enabled (active on both ports).
-
GET /management/health
returns{status: "UP"}
if we’re good -
GET /management/info
returns information about-
deployed version
-
git commit/tag from which it was build
-
bundled XS2A impl and spec version
-
-
GET /management/metrics
returns the default Spring Actuator Metrics
Note
|
The actuator endpoints are all public. We do not expect any sensitive information there. Please verify this. |
If you want to disable certain endpoints you can do so:
endpoints.metrics.enabled=false
endpoints.health.enabled=false
endpoints.info.enabled=false
Warning
|
(KNOWN BUG) You can’t disable the endpoints with CLI arguments. System properties and environment variables work fine, though. |
Disable all production ready features by not exposing /management/**
to the public.
7.4.4. Use Your Own Database
We bundle a recent PostgreSQL JDBC driver in the sandbox JAR. For other databases you need to supply the correct JDBC driver. We use Springs PropertiesLauncher to allow adding JARs to the classpath. The default CMD
in our Dockerfile adds the folder /opt/app-root/src/lib
per default. Put your JDBC driver there so it gets loaded on application start:
$ docker run -it --rm -v $PWD/ojdbc8.jar:/opt/app-root/src/lib adorsys/psd2-sandbox:2.0.0-SNAPSHOT
If you run the sandbox without Docker, you need to set loader.path
yourself:
$ ls lib
ojdbc8.jar
# adds all JARs in "./lib" to the classpath
$ java -jar -Dloader.path="lib" sandbox-2.0.0-SNAPSHOT.jar
Only databases listed in Technical Requirements / Sizing are supported. The Liquibase migration may fail with others.
Warning
|
Please make sure to set the right SPRING_JPA_PROPERTIES_HIBERNATE_DEFAULT_SCHEMA depending on your setup.
|
7.4.5. Database Migration
There are three options to do database migration.
Warning
|
|
Automatically with Liquibase
Set the configuration property liquibase.enabled=true
and migration will be run automatically with the configured connection details.
Manually with Liquibase
The sandbox-2.0.0-SNAPSHOT.jar
can be used as CLI application to do the migration with different credentials than the actual deployment.
$ java -jar sandbox-2.0.0-SNAPSHOT.jar migrate --spring.datasource.url=$JDBC_URL --spring.datasource.username=$USR --spring.datasource.password=$PASS
Manually with self-generated SQL schema
The CLI can echo the full schema instead of doing the actual migration, too. This command creates a file database-migration.sql
which contains the SQL that Liquibase would run to update the schema.
$ java -jar sandbox-2.0.0-SNAPSHOT.jar create-schema --spring.datasource.url=$JDBC_URL --spring.datasource.username=$USR --spring.datasource.password=$PASS
7.5. Reset Sandbox Data
In a sandbox environment it is good practice to reset the data periodically to the factory-defaults. To reset the data of the PSD2 Accelerator, the following steps are needed:
-
Stop the running PSD2 Accelerator process by terminating the jar or by stopping the docker container.
-
Delete the database data by redeploying your database instance. The procedure of resetting the database depends on your local deployment setup. Check the documentation of your preferred database for further information.
-
Restart the PSD2 Accelerator.
7.6. Build Pipeline
Note
|
This is no longer accurate. TODO: document build with Travis CI when done. |
We use GitLab CI for the pipeline. Build, release, testing, Code coverage, linting and compilation/deployment of this architecture documentation are automated. Every artifact we build is also kept for one week and can be downloaded in corresponding pipeline/job.
Every commit on master pushes images for sandbox and ssl-proxy to the adorsys OpenShift. An image change trigger then starts a new deployment. The arc42 documentation is also built on every commit and published with the GitHub Pages feature.
Each tag which follows the semver pattern with a leading v
like v1.0.0
results in a tagged release. Tags are pushed to DockerHub (see Release Artifacts). Releases are created locally with our infrastructure/build/release.sh
script.
7.7. Deployment Samples
7.7.1. docker-compose
This docker-compose setup will start the sandbox on port :8080
/:8081
and the ssl-proxy on port :8443
. The ssl-proxy knows how to serve the domains https://portal.psd2-accelerator.vcap.me and https://api.psd2-accelerator.vcap.me locally with a self signed SSL certificate.
version: "3.7"
services:
service:
build: service/sandbox-core
image: adorsys/psd2-sandbox
ports:
- "8080:8080"
- "8081:8081"
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db/consent
- SPRING_PROFILES_ACTIVE=dev
depends_on:
- db
db:
image: centos/postgresql-10-centos7
environment:
- POSTGRESQL_USER=cms
- POSTGRESQL_PASSWORD=cms
- POSTGRESQL_DATABASE=consent
ports:
- "5432:5432"
ssl-proxy:
build: ssl-proxy
image: adorsys/psd2-sandbox-ssl-proxy
environment:
- API_INTERNAL_URL=${API_INTERNAL_URL:-http://service:8080}
- API_EXTERNAL_URL=${API_EXTERNAL_URL:-api.psd2-accelerator.vcap.me}
- PORTAL_INTERNAL_URL=${PORTAL_INTERNAL_URL:-http://service:8081}
- PORTAL_EXTERNAL_URL=${PORTAL_EXTERNAL_URL:-portal.psd2-accelerator.vcap.me}
ports:
- "8443:8443"
depends_on:
- service
7.7.2. OpenShift Deployment Config
This is an excerpt of the adorsys OpenShift deployment on https://sandbox-api.dev.adorsys.de and https://sandbox-portal.dev.adorsys.de. The PostgreSQL deployment we use is not shown here.
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
annotations:
openshift.io/generated-by: OpenShiftWebConsole
labels:
app: psd2-sandbox
name: psd2-sandbox
namespace: psd2-sandbox-dev
spec:
replicas: 2
selector:
app: psd2-sandbox
deploymentconfig: psd2-sandbox
strategy:
activeDeadlineSeconds: 21600
resources: {}
rollingParams:
intervalSeconds: 1
maxSurge: 25%
maxUnavailable: 25%
timeoutSeconds: 600
updatePeriodSeconds: 1
type: Rolling
template:
metadata:
annotations:
openshift.io/generated-by: OpenShiftWebConsole
creationTimestamp: null
labels:
app: psd2-sandbox
deploymentconfig: psd2-sandbox
spec:
containers:
- env:
- name: SPRING_DATASOURCE_URL
value: 'jdbc:postgresql://db/consent'
- name: CERTIFICATE_FILTER
value: tab
- name: SPRING_PROFILES_ACTIVE
value: dev
- name: SANDBOX_FEATURE_UI_ENABLED
value: 'true'
- name: BANK_PROFILE_PATH
value: /data/bank_profile.yaml
image: "psd2-sandbox-dev/psd2-sandbox-ssl-proxy:latest"
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
httpGet:
path: /management/health
port: 8081
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: psd2-sandbox
ports:
- containerPort: 8080
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /management/health
port: 8081
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
memory: 768Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /data
name: volume-vvjnf
- env:
- name: API_INTERNAL_URL
value: 'http://localhost:8080'
- name: API_EXTERNAL_URL
value: sandbox-api.dev.adorsys.de
- name: PORTAL_INTERNAL_URL
value: 'http://localhost:8081'
- name: PORTAL_EXTERNAL_URL
value: sandbox-portal.dev.adorsys.de
image: "psd2-sandbox-dev/psd2-sandbox-ssl-proxy:latest"
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 8090
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: ssl-proxy
ports:
- containerPort: 8443
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 8090
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
memory: 128Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt/app-root/etc/nginx.pem
name: nginx-certs
readOnly: true
subPath: tls.crt
- mountPath: /opt/app-root/etc/nginx.key
name: nginx-certs
readOnly: true
subPath: tls.key
- mountPath: /data
name: volume-vvjnf
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: nginx-certs
secret:
defaultMode: 420
secretName: dev.adorsys.de
- configMap:
defaultMode: 420
name: bank-profile
name: volume-vvjnf
test: false
triggers:
- imageChangeParams:
automatic: true
containerNames:
- psd2-sandbox
from:
kind: ImageStreamTag
name: 'psd2-sandbox:latest'
namespace: psd2-sandbox-dev
type: ImageChange
- imageChangeParams:
automatic: true
containerNames:
- ssl-proxy
from:
kind: ImageStreamTag
name: 'psd2-sandbox-ssl-proxy:latest'
namespace: psd2-sandbox-dev
type: ImageChange
- type: ConfigChange
apiVersion: v1
kind: Service
metadata:
labels:
app: psd2-sandbox
name: psd2-sandbox
spec:
ports:
- name: 8443-tcp
port: 8443
protocol: TCP
targetPort: 8443
- name: 8080-tcp-api
port: 8080
protocol: TCP
targetPort: 8080
- name: 8081-tcp-portal
port: 8081
protocol: TCP
targetPort: 8081
selector:
deploymentconfig: psd2-sandbox
sessionAffinity: None
type: ClusterIP
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: psd2-sandbox
name: api
spec:
host: sandbox-api.dev.adorsys.de
port:
targetPort: 8443-tcp
tls:
insecureEdgeTerminationPolicy: Redirect
termination: passthrough
to:
kind: Service
name: psd2-sandbox
weight: 100
wildcardPolicy: None
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: psd2-sandbox
name: portal
spec:
host: sandbox-portal.dev.adorsys.de
port:
targetPort: 8443-tcp
tls:
insecureEdgeTerminationPolicy: Redirect
termination: passthrough
to:
kind: Service
name: psd2-sandbox
weight: 100
wildcardPolicy: None
7.7.3. NGINX SSL Configuration
# sandbox-xs2a-server.conf
server {
# The Sandbox HTTPS server, which proxies our requests
listen 8443 ssl;
server_name $API_EXTERNAL_URL;
ssl_protocols TLSv1.1 TLSv1.2;
# ssl certificate
ssl_certificate /opt/app-root/etc/nginx.pem;
ssl_certificate_key /opt/app-root/etc/nginx.key;
# client certificate
ssl_client_certificate /opt/app-root/etc/ca.crt;
# make verification optional, so XS2A validates the incoming certificates
ssl_verify_client optional;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header tpp-qwac-certificate $ssl_client_cert;
# Fix the "It appears that your reverse proxy set up is broken" error.
proxy_pass $API_INTERNAL_URL;
# web sockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect $API_INTERNAL_URL $API_EXTERNAL_URL;
}
}
# sandbox-portal-server.conf
server {
# The Sandbox HTTPS server, which proxies our requests
listen 8443 ssl;
server_name $PORTAL_EXTERNAL_URL;
ssl_protocols TLSv1.1 TLSv1.2;
# ssl certificate
ssl_certificate /opt/app-root/etc/nginx.pem;
ssl_certificate_key /opt/app-root/etc/nginx.key;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Fix the "It appears that your reverse proxy set up is broken" error.
proxy_pass $PORTAL_INTERNAL_URL;
# web sockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect $PORTAL_INTERNAL_URL $PORTAL_EXTERNAL_URL;
}
}
8. Cross-cutting Concepts
8.1. Definition of Done
-
Code is technically reviewed by the developer
-
Code is manually tested
-
Pipeline is running green
-
All existing tests are still working
-
Code Styling is followed
-
Branch is rebased and therefore ready to merge
-
-
Automatic test for new functionality is implemented (if applicable)
-
Documentation is updated (if applicable)
8.2. Supported Browsers
Google Chrome, Mozilla Firefox and Microsoft Edge will be officially supported. Regarding w3schools.com, these browsers are the most popular browsers of 2018. Those browser together have a market share of roughly 95%. Only the latest versions of the listed browsers are officially supported. Currently no support for mobile devices is planned.
8.3. Code Formatting
For this project we decided to use two different code stylings depending on frontend or backend development.
The frontend development is using tslint for code-quality rules (no-unused vars,…). For code styling and formatting of HTML, Typescript and CSS/SCSS we use Pretter. The appropriate config files are .prettierrc.json
and tslint.json
. To guarantee a clean code styling on the remote branch, we decided to add a pre-push-hook which checks the style for errors and if possible also fixes them automatically. Furthermore, we added a second check embedded in the ci pipeline which fails in case of unclean code.
The backend development (mostly Java code) is using the Google Code Style which can be found in the service
folder named google-checkstyle.xml
. After adding this file to the local IDE the automatic styling should apply to those rules. We decided to add a maven-checkstyle-plugin
which allows the code style check during the build process. The configuration for this plugin is based on the google-checkstyle.xml
which can also be found in the service
folder of this project. In case of unformatted code the ci pipeline will fail with an appropriate error message.
8.4. SSL Client Authentication
The Sandbox acts as a CA which issues SSL client certificates required to access the provided XS2A API. Every Sandbox deployment (e.g. every customer) initially needs to generate a new CA primary key and certificate. Those artifacts are then used to issue the TPP client certificate. SSL Client Authentication is only used for the XS2A API.
See also adorsys Sample Setup for more information about the SSL authentication setup.
9. Design Decisions
- Modular Monolith/Well Designed Monolith
-
We start with a monolithic approach to keep it simple. Unrelated Use-Cases are represented by top-level packages in the backend or Angular modules in the frontend. We don’t allow dependencies between unrelated features. These features are also transaction boundaries. We might enforce these rules at build time with tools like ArchUnit if we see that design problems are introduced despite our code-reviews and guidelines.
This approach allows us to scale out later if we need it, while keeping development and deployment as simple as possible.
See also:
- Stick to a Tech-Stack Commonly Found in Banks
-
We try to be conservative in our tech choice. To reduce friction we use technologies that our potential customers know and can handle.
Right now we use:
-
Java 8 / Spring Boot 1 (XS2A forces us to use these versions, too)
-
Angular 7
-
Postgres 10
-
Docker (optional)
-
- Deployment as a single JAR
-
To make local development and deployment easy, we try to bundle everything in the sandbox JAR:
-
profile is embedded instead of being deployed stand-alone
-
consent-management is embedded instead of being deployed stand-alone
-
the ui is a separate top-level Angular project but is embedded in the resulting JAR as static content
-
- Different Spring Contexts for XS2A and the Sandbox
-
Our JAR hosts two Spring Web Applications on different ports. The XS2A context is isolated from the Sandbox context. This allows us to:
-
import the original XS2A configuration without affecting the Sandbox
-
host both applications on different subdomains
-
use two different but simpler Spring Security configurations instead of a complicated one
-
- Monorepo
-
All our code lives in a single PSD2 Accelerator repository. Every project / artifact gets a top-level directory (service, ui, arc42, deployment configuration). This allows us to
-
reflect our architecture in the repo
-
build and version everything together and at once
-
get started quickly (easy discovery and build)
-
10. Quality Requirements
10.1. Quality Tree
10.2. Quality Scenarios
11. Risks and Technical Debts
12. Glossary
Term | Name | Description |
---|---|---|
<AISP> |
<Account Information Service Provider> |
TPP application that reads and processes payment information of the PSU, with the purpose of providing a richer set of banking data. Such an application might also be called a Personal Finance Manager (PFM). |
<ASPSP> |
<Account Servicing Payment Service Provider> |
Payment service provider providing and maintaining a payment account for a PSU. It is mostly referred to a bank. |
<CA> |
<Certificate Authority> |
Entity that is issuing certificates. In this context it is a synonym to a TSP. |
<CSR> |
<Certificate Signing Request> |
Message sent by a TPP to CA in order to request a digital identity. |
<eIDAS> |
<electronic Identification, Authentication and Trust Services> |
EU regulation that is addressing a secure communication for electronic transactions. eIDAS contains QWAC and QSealC. |
<NCA> |
<National Competent Authority> |
National organisations that have competences in banking supervision. In Germany the NCA is called BaFin. |
<PIISP> |
<Payment Instrument Issuer Service Provider> |
TPP that issues payment instrument to the user. A most commonly known payment instrument is the "Credit Card". |
<PISP> |
<Payment Initiation Service Provider> |
TPP application that initiates payments on behalf of the PSU |
<PSD2> |
<Payment Service Directive 2> |
European revised payment service directive. |
<PSP> |
<Payment Service Provider> |
End user with a bank account accessing banking services via appropriate applications. |
<PSU> |
<Payment Service User> |
Individual or organisation that owns a bank account and can consume payment services. The PSU is generally the owner of the payment account, or in case of organisation has a legitimate access to the payment account. |
<QWAC> |
<Qualified Website Authentication Certificate> |
Institution certified by the NCA issuing eIDAS Certificates to registered TPPs. |
<RTS> |
<Regulatory Technical Standards> |
Technical standards referenced by PSD2. |
<SSL> |
<Secure Sockets Layer> |
Standardised security protocol for communication. |
<SCA> |
<Strong Customer Authentication> |
PSD2 refers from SCA to Two-Factor Authentication of PSU |
<TPP> |
<Third Party Provider> |
In this context a TPP is a FinTech corporation that develops applications in scope of AISP, PISP or PIISP. |
<TSP> |
<Trusted Services Provider> |
Institution certified by the NCA issuing eIDAS Certificates to registered TPPs. |
<XS2A> |
<Access-to-Account> |
Interface provided by ASPSPs offering payment services to TPPs |
<LB> |
<Load Balancer> |
A infrastructure component which routes HTTP traffic to backend services and often does things like SSL termination. |
13. About the PSD2 Accelerator Architecture Documentation
13.1. How to Build
-
check if you have jq, plantuml and asiidoctor installed
$ make check
-
install if needed
$ brew install plantuml jq $ gem install asciidoctor
-
create architecture documentation
$ make arc42/psd2-accelerator-arc42.html
13.2. Tools Used for Diagrams
We use PlantUML for simple diagrams. This allow us to put the plain text
diagram sources under source control. PlantUML diagrams are put into the diagrams
folder and
are named *.puml
. At build time we generate PNGs from them and put them in the ignored folder
images/generated
.
More complex diagrams (like the diagram in SSL Client Authentication) are created with https://draw.io, which is now completely free and even offers a desktop app. draw.io diagrams are saved as XML, also put in the diagrams
folder and have the
extension *.drawio.xml
(convention for us). We manually export them to images/*.svg
.
About arc42
arc42, the Template for documentation of software and system architecture.
By Dr. Gernot Starke, Dr. Peter Hruschka and contributors.
Template Revision: 7.0 EN (based on asciidoc), January 2017
© We acknowledge that this document uses material from the arc 42 architecture template, http://www.arc42.de. Created by Dr. Peter Hruschka & Dr. Gernot Starke.