diff --git a/.gitignore b/.gitignore index 20ebc05bd..de468221c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ local.yml +assets/certs/certs +assets/certs/ca diff --git a/README.md b/README.md index e8eafadef..e8b57eaf4 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,41 @@ When you change them, use `bin/moodle-docker-compose down && bin/moodle-docker-c | `MOODLE_DOCKER_APP_RUNTIME` | no | 'ionic3' or 'ionic5' | not set | Set this to indicate the runtime being used in the Moodle app. In most cases, this can be ignored because the runtime is guessed automatically (except on Windows using the `.cmd` binary). In case you need to set it manually and you're not sure which one it is, versions 3.9.5 and later should be using Ionic 5. | | `MOODLE_DOCKER_APP_NODE_VERSION` | no | [node](https://hub.docker.com/_/node) image version tag | not set | Node version to run the app. In most cases, this can be ignored because the version is parsed from the project's `.nvmrc` file. This will only be used when the runtime is `ionic5` and the app is running from the local filesystem. | +## SSL certificates + +If you wish, you can generate a self-signed certificate repository and create your own certificates for your containers. + +Certificates should be placed into the `assets/certs/certs` directory, with the certificate authority placed into `assets/certs/ca`. + +If moodle-docker-compose detects the certificate for a local certificate authority at `asserts/certs/ca/ca.pem` then an additional SSL configuration will be included. + +To make this easier, a helper has been created for Linux and MacOS which will: + +- generate a new certificate authority if required +- generate certificates +- offer to install your new Certificate Authority + + +The helper can be used as follows: + +``` +./assets/certs/createcerts.sh hostname [alternative-hostname] +``` + +You will need to run a separate command for each host you wish to generate a certificate for, for example: + +``` +./asserts/certs/createcerts.sh webserver webserver.container.docker.internal +./asserts/certs/createcerts.sh exttests exttests.container.docker.internal +``` + +### Local hostnames + +If you wish to access your containers using their certificates, you will need to add either: + +- entries to your `/etc/hosts` or `%WinDir%\System32\Drivers\Etc\Hosts` file; or +- relevant DNS entries to your local DNS resolver (for example dnsmasqd). + ## Local customisations In some situations you may wish to add local customisations, such as including additional containers, or changing existing containers. diff --git a/assets/certs/443-default.conf b/assets/certs/443-default.conf new file mode 100644 index 000000000..f54cff145 --- /dev/null +++ b/assets/certs/443-default.conf @@ -0,0 +1,9 @@ + + ServerName webserver + DocumentRoot /var/www/html + ErrorLog /var/log/apache2/error.log + CustomLog /var/log/apache2/access.log combined + SSLEngine on + SSLCertificateFile "/etc/ssl/certs/moodle/webserver.crt" + SSLCertificateKeyFile "/etc/ssl/certs/moodle/webserver.key" + diff --git a/assets/certs/README.md b/assets/certs/README.md new file mode 100644 index 000000000..252585fd0 --- /dev/null +++ b/assets/certs/README.md @@ -0,0 +1,19 @@ +# IMPORTANT + +These are test Certificates and Keys only! + +Do NOT use them outside of a closed development environment. + +DO NOT commit them to the git repository. + +## Generating new certificates + +A helper script exists at the project root and takes a list of names for the certificate. + +For example: + +``` +./createcerts.sh webserver webserver.container.docker.internal +``` + +Each argument is used as a subject alternative name for the certificate. diff --git a/assets/certs/createcerts.sh b/assets/certs/createcerts.sh new file mode 100755 index 000000000..4516a7847 --- /dev/null +++ b/assets/certs/createcerts.sh @@ -0,0 +1,155 @@ +#!/bin/bash + +CERTDIR="`pwd`/assets/certs/" + +CACONF="${CERTDIR}/openssl.cnf" +CAKEY="${CERTDIR}/ca/ca.key" +CACERT="${CERTDIR}/ca/ca.pem" + +if [ -f "$CAKEY" ] && [ -f "${CACERT}" ]; then + echo "Using existing CA private key" + echo +else + # Generate the private key for the CA: + echo "Generating the key and certificate for the CA server" + mkdir -p "${CERTDIR}/ca" + mkdir -p "${CERTDIR}/certs" + + # Generate the key and certificate for the CA. + cat < "${CERTDIR}/ca/serial.txt" + echo + echo "You should add this certificate to your root certificate store." + + OS=`uname -s` + if [ "${OS}" = "Darwin" ] + then + echo "You can use the following command:" + echo "sudo security add-trusted-cert -d -r trustRoot -k '/Library/Keychains/System.keychain' ${CACERT}" + read -p "Do you want me to do that for you now? " yn + case $yn in + [Yy]* ) sudo security add-trusted-cert -d -r trustRoot -k '/Library/Keychains/System.keychain' "${CACERT}"; break;; + esac + fi + + if [ "${OS}" = "Linux" ] + then + echo "You can use the following command:" + echo "sudo cp ${CERTDIR}/ca/ca.pem usr/local/share/ca-certificates/moodle-docker-ca.crt && sudo update-ca-certificates" + read -p "Do you want me to do that for you now? " yn + case $yn in + [Yy]* ) sudo cp "${CERTDIR}/ca/ca.pem" usr/local/share/ca-certificates/moodle-docker-ca.crt && sudo update-ca-certificates; break;; + esac + + fi +fi + +if [ "$#" -lt 1 ] +then + echo "Usage: Must supply at least one hostname." + exit 1 +fi + +# The first hostname is canonical. +DOMAIN=$1 + +HOSTKEY="${CERTDIR}/certs/${DOMAIN}.key" +HOSTCSR="${CERTDIR}/certs/${DOMAIN}.csr" +HOSTCRT="${CERTDIR}/certs/${DOMAIN}.crt" +HOSTEXT="${CERTDIR}/certs/${DOMAIN}.ext" + +# Create a private key for the dev site: +echo +echo "Generating a private key for the $DOMAIN dev site" +echo +openssl genrsa -out "${HOSTKEY}" 2048 + +echo "Generating a CSR for $DOMAIN" +cat < "${HOSTEXT}" << EOF +[ req ] +default_bits = 2048 +default_keyfile = ${HOSTKEY} +distinguished_name = server_distinguished_name +req_extensions = server_req_extensions +string_mask = utf8only + +[ server_distinguished_name ] + +countryName = Country Name (2 letter code) +countryName_default = AU + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Western Australia + +localityName = Locality Name (eg, city) +localityName_default = Perth + +organizationName = Organization Name (eg, company) +organizationName_default = Moodle Pty Ltd + +organizationalUnitName = Organizational Unit (eg, division) +organizationalUnitName_default = Moodle LMS + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_default = ${DOMAIN} + +emailAddress = Email Address +emailAddress_default = moodle@example.com + +[ server_req_extensions ] +subjectKeyIdentifier = hash +basicConstraints = CA:FALSE +keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment +subjectAltName = @alternate_names +[ alternate_names ] +$DNS +EOF + +#Next run the command to create the certificate: using our CSR, the CA private key, the CA certificate, and the config file: +echo "Generating a certificate for $DOMAIN" +cat <