OpenAS2 / OpenAs2App

OpenAS2 is a java-based implementation of the EDIINT AS2 standard. It is intended to be used as a server. It is extremely configurable and supports a wide variety of signing and encryption algorithms.
https://sourceforge.net/projects/openas2/
BSD 2-Clause "Simplified" License
177 stars 132 forks source link

Self signed SSL certs in Docker #354

Closed ThorTL67 closed 5 months ago

ThorTL67 commented 5 months ago

We're running an OpenAS2v3.9.0 server using Docker

Problem: Connecting to a Partner AS2 server using a self signed certificate caused the issue described in OpenAS2Howto.pdf:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Running the SSL cert checker within the docker container did not add the certificate to a keystore:

java -cp lib/openas2-server-3.9.0.jar CheckCertificate -s as2.example.net -c jssechaincerts
Adding KeyManager for possible HTTP AUTH...
Set SSLContext using protocol: TLSv1.3

                **** Starting SSL handshake...
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
...
Exception caught starting SSL handshake so trying to set up a local certificate store with trust chain....

Trying using Apache HTTP Client...
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
        at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
        at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
        at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(Unknown Source)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(Unknown Source)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(Unknown Source)
        at java.base/sun.security.ssl.SSLHandshake.consume(Unknown Source)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(Unknown Source)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(Unknown Source)
        at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source)
        at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)

Importing the certificates with a GUI app to the .jks keystore defined in config.xml and rebuilding resulted in the same error. Importing the certificates with a GUI app to cacerts in the root directory of the repo and rebuilding resulted in the same error.

I managed to get this working by Modifying the Dockerfile as so:

...

FROM openjdk:11-jre-slim 
ENV OPENAS2_BASE=/opt/openas2
ENV OPENAS2_HOME=/opt/openas2
ENV OPENAS2_TMPDIR=/opt/openas2/temp
COPY --from=builder /usr/src/openas2/Runtime/bin ${OPENAS2_BASE}/bin
COPY --from=builder /usr/src/openas2/Runtime/lib ${OPENAS2_BASE}/lib
COPY --from=builder /usr/src/openas2/Runtime/resources ${OPENAS2_BASE}/resources
COPY --from=builder /usr/src/openas2/Runtime/config_template ${OPENAS2_HOME}/config_template
RUN mkdir ${OPENAS2_BASE}/config
WORKDIR $OPENAS2_HOME
# Import self-signed certs
COPY ./self-signed-certs /opt/workdir/certs/
RUN mkdir -p /usr/share/man/man1 \
    && apt-get update \
    && apt-get install -y ca-certificates-java \
    && for CERT in $(ls /opt/workdir/certs/*.cer); do \
         keytool -importcert -file $CERT -alias $(basename $CERT) -cacerts -storepass changeit -noprompt; \
       done
ENTRYPOINT ${OPENAS2_BASE}/bin/start-container.sh

This now trusts the self signed certificate and I'm able to communicate with the Partner AS2 server.

Is this the correct way to import self signed certs using Docker, or is there a 'cleaner way'?

I'm happy to work on or open a PR should this be something useful for the repo.

igwtech commented 5 months ago

Dear Tobias,

In the context of OpenAS2, it is crucial to understand the handling of partner certificates, especially when dealing with Container Images and platforms like Docker Hub. Partner certificates are integral to the transactional and operational aspects of OpenAS2, and as such, they carry sensitive information. Including these certificates directly in the Container Image of OpenAS2 poses significant security risks. There is a potential for unintended disclosure of these sensitive certificates if the image is shared or distributed through public repositories such as Docker Hub.

Moreover, when dealing with containerized environments, particularly those that employ high availability (HA) setups like Kubernetes, the reconstruction of containers from images is a common practice. In such scenarios, if the partner certificates are embedded within the container image, there is a risk of losing these certificates during the runtime when containers are recreated or scaled.

To mitigate these risks and ensure a more secure and resilient handling of partner certificates, it is advisable to treat the certificate keystore as an externally exportable volume. This approach is akin to how the config.xml file is handled in OpenAS2. As demonstrated in the start-container.sh script, if the config.xml file is already designated as an external volume, the system utilizes it. Otherwise, it resorts to copying over the default configuration file. Adopting a similar strategy for the certificate keystore not only enhances security but also maintains the integrity and availability of the certificates during various container operations.

On Tue, Jan 30, 2024 at 6:23 AM Tobias Leyland @.***> wrote:

We're running an OpenAS2v3.9.0 server using Docker

Problem: Connecting to a Partner AS2 server using a self signed certificate caused the issue described in OpenAS2Howto.pdf:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Running the SSL cert checker within the docker container did not add the certificate to a keystore:

java -cp lib/openas2-server-3.9.0.jar CheckCertificate -s as2.example.net -c jssechaincerts Adding KeyManager for possible HTTP AUTH... Set SSLContext using protocol: TLSv1.3

            **** Starting SSL handshake...

javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source) ... Exception caught starting SSL handshake so trying to set up a local certificate store with trust chain....

Trying using Apache HTTP Client... javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source) at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source) at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source) at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(Unknown Source) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(Unknown Source) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(Unknown Source) at java.base/sun.security.ssl.SSLHandshake.consume(Unknown Source) at java.base/sun.security.ssl.HandshakeContext.dispatch(Unknown Source) at java.base/sun.security.ssl.HandshakeContext.dispatch(Unknown Source) at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source) at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source) at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source) at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)

Importing the certificates with a GUI app to the .jks keystore defined in config.xml and rebuilding resulted in the same error. Importing the certificates with a GUI app to cacerts in the root directory of the repo and rebuilding resulted in the same error.

I managed to get this working by Modifying the Dockerfile as so:

... FROM openjdk:11-jre-slim ENV OPENAS2_BASE=/opt/openas2ENV OPENAS2_HOME=/opt/openas2ENV OPENAS2_TMPDIR=/opt/openas2/tempCOPY --from=builder /usr/src/openas2/Runtime/bin ${OPENAS2_BASE}/binCOPY --from=builder /usr/src/openas2/Runtime/lib ${OPENAS2_BASE}/libCOPY --from=builder /usr/src/openas2/Runtime/resources ${OPENAS2_BASE}/resourcesCOPY --from=builder /usr/src/openas2/Runtime/config_template ${OPENAS2_HOME}/config_templateRUN mkdir ${OPENAS2_BASE}/configWORKDIR $OPENAS2_HOME# Import self-signed certsCOPY ./self-signed-certs /opt/workdir/certs/RUN mkdir -p /usr/share/man/man1 \ && apt-get update \ && apt-get install -y ca-certificates-java \ && for CERT in $(ls /opt/workdir/certs/*.cer); do \ keytool -importcert -file $CERT -alias $(basename $CERT) -cacerts -storepass changeit -noprompt; \ doneENTRYPOINT ${OPENAS2_BASE}/bin/start-container.sh

This now trusts the self signed certificate and I'm able to communicate with the Partner AS2 server.

Is this the correct way to import self signed certs using Docker, or is there a 'cleaner way'?

I'm happy to work on or open a PR should this be something useful for the repo.

— Reply to this email directly, view it on GitHub https://github.com/OpenAS2/OpenAs2App/issues/354, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA2QNDZNYIRWZB2KQHYJSHTYRDCYTAVCNFSM6AAAAABCQ7F5DOVHI2DSMVQWIX3LMV43ASLTON2WKOZSGEYDONBXGIYDGMY . You are receiving this because you are subscribed to this thread.Message ID: @.***>

-- Javier Munoz

CEO

Greicodex Software

+58 2127629120 <+58+2127629120> @.*** www.greicodex.com Av Francisco Solano, Centro Solano Plaza, Oficina PHA, Caracas, Venezuela