redcap-docker-compose icon indicating copy to clipboard operation
redcap-docker-compose copied to clipboard

Trouble with self-signed certificates and php

Open carneirofc opened this issue 3 years ago • 3 comments

I'm trying to setup redcap using self-signed ssl certificates, the program seems to work fine but I'm getting the following erros when uploading files, specifically during the browser based installation itself. I had to setup the application sort of manually .

PHP Warning:  file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:\nerror:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed in /var/www/html/REDCapInstaller.php on line 301, referer: https://10.0.38.43/install.php

I've tried to install the crt file into the container root certs:

ln -s $CERT_PATH /usr/local/share/ca-certificates/
update-ca-certificates

and also by configuring the openssl.cafile= parameter on the php.ini file. None of the approaches worked for me.

Is there anything I can do to accept self-signed certificates? Surely it is possible to edit the *.php files and pass additional arguments to the function, but it is not a real solution.

I'm using the following command to generate the certificate and the pk:

openssl req \
    -newkey \
    rsa:4096 \
    -nodes \
    -sha256 \
    -keyout certs/pem.key \
    -x509 \
    -days 358000 \
    -out certs/pem.crt

I am using the following apache config 000-default.conf

...
LoadModule socache_shmcb_module /usr/lib/apache2/modules/mod_socache_shmcb.so
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so

<IfModule ssl_module>

    SSLRandomSeed startup builtin
    SSLRandomSeed startup file:/dev/urandom 512
    SSLRandomSeed connect builtin
    SSLRandomSeed connect file:/dev/urandom 512

    Listen 443

    SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4:!3DES
    SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4:!3DES
    SSLHonorCipherOrder on

    SSLProtocol all -SSLv3
    SSLProxyProtocol all -SSLv3

    SSLPassPhraseDialog  builtin

    SSLSessionCache         shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
    SSLSessionCacheTimeout  300

    <VirtualHost *:443>

        SSLEngine on
        SSLCertificateFile "${SSL_CERT_FILE}"
        SSLCertificateKeyFile "${SSL_KEY_FILE}"

        ServerName ${SERVER_NAME}
        ServerAlias ${SERVER_ALIAS}

        ServerAdmin ${SERVER_ADMIN}
        DocumentRoot ${APACHE_DOCUMENT_ROOT}

        ErrorLog ${APACHE_ERROR_LOG}
        CustomLog ${APACHE_ACCESS_LOG} combined
        IncludeOptional /etc/apache2/sites-enabled/default.virtualhost

        <FilesMatch "\.(cgi|shtml|phtml|php)$">
            SSLOptions +StdEnvVars
        </FilesMatch>

        BrowserMatch "MSIE [2-5]" \
                 nokeepalive ssl-unclean-shutdown \
                 downgrade-1.0 force-response-1.0
    </VirtualHost>
</IfModule>

DISCLAIMER: Im totally unfamiliar with PHP

carneirofc avatar Jan 20 '22 11:01 carneirofc

I have a solution for a self-signed certificate but haven't had time to add it to this repo.

This is copied from a private repo's readme - but we should be able to do something similar here (some of the mount points, like secrets, do not apply to this repo. Let me know if you get anywhere):

SSL Setup for Local Dev

It is possible to run a local instance of this project and connect to the production database (or any other database) depending on your configuration in the docker-compose file.

As REDCap forces you to stay on https if the server url is set to be https, we need to run our localhost environment as https. To do this, first follow the directions to install a trusted cert authority locally and then generate ssl certs to be used for the local docker container.

Building local trusted SSL certs

This is based on https://dockerwebdev.com/tutorials/docker-php-development/

brew install mkcert nss
mkcert -install

Next, make a locally trusted development certificate

mkcert localhost 127.0.0.1 ::1 (or add any other names you want to call your local server)

Rename the generated files:

mv localhost+x.pem cert.pem
mv localhost+x-key.pem cert-key.pem

Copy the two signed files to your docker project folder for addition to apache containers. In this case, I place them in the /secrets/ folder. They will only work on the local machine where we added the trusted authority, so don't bother checking them into the git repo.

At this point, your local browser can connect to your locally running docker over https without warnings. However, if your docker container trys to call itself with https://localhost (from a CURL in the PHP code, for example) - the cert will not be trusted. To also add this as a trusted cert for the docker container, follow these steps:

Find the location of the root certificate used by mkcert. This is done with:

mkcert -CAROOT

Copy the value of this (rootCA.pem) to the /secrets folder as well and uncomment the line in the docker-compose. This will allow the docker server to also trust the ssl certs provided previously.

123andy avatar Feb 16 '22 18:02 123andy

Did you ever get this to work? I'd love to have better documentation in the official repo readme on this feature. I'm planning to re-install on a new laptop in a month or so -- perhaps at that time I can do it or confirm any suggestions you had.

123andy avatar Aug 26 '22 20:08 123andy

I was able to get this to work, but I did make a few changes.

I added the below to the .env:

SECRET_DIR=../secrets
SSL_CERT_FILE=cert.pem
SSL_KEY_FILE=cert-key.pem

...

SSL_PORT=443

I created a secrets dir, then followed the steps like in your comment to create the certs and placed them in the secrets dir.

In the docker-compose.yml I added - 127.0.0.1:${SSL_PORT}:443 under the web service's ports.

In rdc\docker-web\container-config\apache2 I added:

PassEnv SSL_KEY_FILE
PassEnv SSL_CERT_FILE

I'm relatively new to Docker and have to clean this out, but I also added the above to ENV to the Dockerfile in rdc\docker-web under the other environment variables. I'm sure it's probably unnecessary here or at least shouldn't be hard-coded

In rdc\redcap-overrides\web\apache2\sites-enabled> I added:

<IfModule mod_ssl.c>
    # Listen 443
    <VirtualHost *:443>
        SSLEngine on
        SSLCertificateFile "/var/secrets/${SSL_CERT_FILE}"
        SSLCertificateKeyFile "/var/secrets/${SSL_KEY_FILE}"

        ServerName ${SERVER_NAME}
        ServerAlias ${SERVER_ALIAS}

        ServerAdmin ${SERVER_ADMIN}
        DocumentRoot ${APACHE_DOCUMENT_ROOT}

        ErrorLog ${APACHE_ERROR_LOG}
        CustomLog ${APACHE_ACCESS_LOG} combined
        IncludeOptional /etc/apache2/sites-enabled/default.virtualhost
    </VirtualHost>
</IfModule>

And I added a new script to rdc\redcap-overrides\web\startup-scripts called 10-enable_ssl.sh:

#!/usr/bin/env bash

echo 'Enabling mod ssl'
a2enmod ssl

I'll test the env's above and see how I can avoid hard-coding it the second time. I also think it makes sense to turn SSL on with an environment variable set in the .env so you have the option to run the above script or not more simply.


I will note that when I run the installer, I use it in http and once installed, switch over to https.

1000daysofcode avatar Nov 30 '23 09:11 1000daysofcode