The DSS demo webapp trusts only the certificate authorities carried by the EU trusted lists. A signature from a private CA is therefore reported as untrusted — technically correct, but useless when you operate that CA yourself and want your own validation service to say so.
This folder builds a DSS image that trusts the certificates in trusted/ in addition to the
EU lists.
It does not make anything qualified. DSS keeps qualification and trust apart: the certificates here go into a second trusted source next to the trusted-list source, so a signature under our root validates as trusted, not qualified. Nothing about the EU trusted lists changes.
| Piece | Why |
|---|---|
trusted/*.crt |
The CA certificates to trust, PEM. Public material — committed on purpose, so the trust set is reviewable in git rather than hand-installed on a server. |
Dockerfile |
Builds a PKCS#12 trust store from those certificates with keytool, then copies it plus dss-custom.properties into ${CATALINA_HOME}/lib. |
dss-custom.properties |
Sets trusted.source.keystore.*. DSS loads classpath:dss-custom.properties on top of the WAR's dss.properties (ignoreResourceNotFound=true, later wins). |
Two details decide whether this works, and both are easy to get wrong:
trusted.source.keystore.filenameis a classpath resource, not a path. DSS resolves it withnew ClassPathResource(filename).getFile(). Keep it a bare file name.- Tomcat's
${catalina.home}/libis on the common classpath — the directory itself, not just its jars. That is why both files go there and why a bare name resolves.
curl -o dss/trusted/my-root-ca.crt https://example.org/root.pem # PEM, .crt extensionVerify the fingerprint against the one the CA publishes before committing it — the whole point of a trust store is that you decided what is in it:
openssl x509 -in dss/trusted/my-root-ca.crt -noout -fingerprint -sha256The file name becomes the keystore alias, so name it after the CA.
Certificates may live in subdirectories — the Dockerfile imports trusted/**/*.crt recursively.
trusted/ch/ holds the CA certificates of the granted trust services from the official
Swiss Trusted List (https://trustedlist.tsl-switzerland.ch/tsl-ch.xml) — Swisscom, SwissSign,
DigiCert/QuoVadis, the Swiss Government CAs, etc. They are extracted (not hand-picked) so Swiss ZertES
signatures validate as trusted here. As with any trust-store entry this is trusted, not qualified —
DSS qualification would require processing the TSL as a real trusted list, which we deliberately do not do
(the DSS core stays untouched).
Two helpers keep this current:
| Script | Purpose |
|---|---|
extract-swiss-tsl.py |
Parse a tsl-ch.xml and write every granted service certificate to trusted/ch/ (extract-swiss-tsl.py <tsl.xml> <out-dir>). |
refresh-swiss-tsl.sh |
Fetch the live TSL, re-extract, and rebuild + redeploy the DSS image only if the certificate set changed. |
refresh-swiss-tsl.sh runs weekly on the server via /etc/cron.d/mipdfvalidator-swiss-tsl
(17 3 * * 0), so the snapshot follows the Swiss TSL without touching the DSS base image.
docker build -t mipdfvalidator-dss:6.4-trust --build-arg DSS_BASE=dss-demo:6.4 ./dssDSS_BASE names the DSS demo bundle image you built yourself (the ROOT.war in a Tomcat/JDK image) — it is
not on a public registry. Then point the dss service at mipdfvalidator-dss:6.4-trust and restart it.
Validate a PDF signed by that CA and look at the signing certificate's chain: every certificate up to and
including the root must come back trusted: true. Startup logs the import (keytool -list runs at build
time, so a broken certificate fails the build rather than silently producing an empty store).