redcap-docker-compose
redcap-docker-compose copied to clipboard
Trouble with self-signed certificates and php
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
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.
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.
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
.