From e4090353f3890ce9aa327a900ca347f60c4caba3 Mon Sep 17 00:00:00 2001 From: Mirko Tietgen Date: Fri, 4 Dec 2015 01:11:17 +0100 Subject: [PATCH] Bug 15303 Letsencrypt option for Debian package installations New option koha-create --letsencrypt - installs the letsencrypt package if needed - creates - generates letsencrypt certificates for - sets up a https-only website for - redirects http to https for ! you need to enable jessie backports to install letsencrypt: add deb http://http.debian.net/debian jessie-backports main contrib non-free to your /etc/apt/sources.list ! this patch uses the letsencrypt staging server to create real certificates, apply thy "LE production server" patch Test plan: - build a debian package with patch applied - use apache mod_ssl sudo a2enmod ssl - make sure the machine is accessible on 80 (needed for letsencrypt) and 443 from the internet - install koha with your new package - Put your (existing) domain options in /etc/koha/koha-sites.conf - use koha-create with the new options: sudo koha-create --create-db --letsencrypt - if you do not have the letsencrypt package installed, you will be prompted to do that [ if there is no package available, a symlink to the git checkout will work: on your test server, get letsencrypt via git git clone https://github.com/letsencrypt/letsencrypt create a symlink from /usr/bin/letsencrypt to letsencrypt-auto sudo ln -s /path/to/letsencrypt/letsencrypt-auto /usr/bin/letsencrypt ] - wait until setup is finished, check that you got a working OPAC and staff client with certificates - check that http redirects to https Signed-off-by: Chris Cormack Signed-off-by: Jonathan Druart --- debian/control.in | 3 +- debian/docs/koha-create.xml | 8 +++ debian/scripts/koha-create | 75 +++++++++++++++++++++++++-- debian/scripts/koha-foreach | 2 + debian/scripts/koha-functions.sh | 11 ++++ debian/scripts/koha-list | 81 ++++++++++++++++++++++-------- debian/templates/apache-site-https.conf.in | 70 ++++++++++++++++++++++++++ install_misc/debian.packages | 1 + 8 files changed, 227 insertions(+), 24 deletions(-) create mode 100644 debian/templates/apache-site-https.conf.in diff --git a/debian/control.in b/debian/control.in index 44060c6..6609d7f 100644 --- a/debian/control.in +++ b/debian/control.in @@ -35,7 +35,8 @@ Depends: ${misc:Depends}, ${koha:Depends}, xmlstarlet, yaz Suggests: mysql-server | virtual-mysql-server, - memcached + memcached, +letsencrypt Homepage: http://koha-community.org/ Description: integrated (physical) library management system Koha is an Integrated Library Management system for real-world libraries diff --git a/debian/docs/koha-create.xml b/debian/docs/koha-create.xml index 92785ac..a485ba8 100644 --- a/debian/docs/koha-create.xml +++ b/debian/docs/koha-create.xml @@ -40,6 +40,7 @@ port directory + | instancename @@ -177,6 +178,13 @@ + + + Set up a https-only website with letsencrypt certificates + + + + , Print usage information. diff --git a/debian/scripts/koha-create b/debian/scripts/koha-create index 2a6c87d..159193b 100755 --- a/debian/scripts/koha-create +++ b/debian/scripts/koha-create @@ -71,6 +71,7 @@ Options: conjunction with --defaultsql and --populate-db. --upload-path dir Set a user defined upload_path. It defaults to /var/lib/koha//uploads + --letsencrypt Set up a https-only site with letsencrypt certificates --help,-h Show this help. Note: the instance name cannot be longer that 11 chars. @@ -194,6 +195,20 @@ EOM die fi + # Check that mod_ssl is installed and enabled. + if [ "$CLO_LETSENCRYPT" = "yes" ]; then + if ! /usr/sbin/apachectl -M 2> /dev/null | grep -q 'ssl_module'; then + cat 1>&2 </dev/null | grep -c "ok installed") -eq 0 ]; then + apt-cache show letsencrypt &>/dev/null + if [ $? -eq 0 ]; then + read -r -p "The letsencrypt package is not installed. Do it now? [y/N] " response + if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then + apt-get install -y letsencrypt + else + die "You have to install letsencrypt to use the --letsencrypt parameter." + fi + else + echo "No installation candidate available for package letsencrypt." + read -r -p "If you have a symlink from /usr/bin/letsencrypt to letsencrypt-auto, it should work. [y/N] " response + if [[ ! $response =~ ^([yY][eE][sS]|[yY])$ ]]; then + die "You have to install letsencrypt to use the --letsencrypt parameter." + fi + fi + fi +} + +letsencrypt_instance() +{ + # Get letsencrypt certificates + letsencrypt --agree-tos --renew-by-default --webroot --staging certonly \ + -w /usr/share/koha/opac/htdocs/ -d $opacdomain -w /usr/share/koha/intranet/htdocs/ -d $intradomain + # enable all ssl settings (apache won't start with these before certs are present) + sed -i "s:^\s*#\(\s*SSL.*\)$:\1:" "/etc/apache2/sites-available/$name.conf" + # change port from 80 to 443. (apache won't start if it is 443 without certs present) + sed -i "s:^\s*\( #https$:\1443>:" "/etc/apache2/sites-available/$name.conf" + # enable redirect from http to https on port 80 + sed -i "s:^\s*#\(.*\)#nohttps$:\1:" "/etc/apache2/sites-available/$name.conf" + # make koha-list --letsencrypt aware of this instance # could be done by checking apache conf instead + touch /var/lib/koha/$name/letsencrypt.enabled + # restart apache with working certs + service apache2 restart +} + # Set defaults and read config file, if it exists. DOMAIN="" OPACPORT="80" @@ -356,6 +409,8 @@ END_BIBLIOS_RETRIEVAL_INFO="" START_AUTHORITIES_RETRIEVAL_INFO="" END_AUTHORITIES_RETRIEVAL_INFO="" +APACHE_CONFIGFILE="" + if [ -e /etc/koha/koha-sites.conf ] then . /etc/koha/koha-sites.conf @@ -363,7 +418,7 @@ fi [ $# -ge 1 ] && [ $# -le 16 ] || ( usage ; die "Error: wrong parameters" ) -TEMP=`getopt -o chrpm:l:d:f:b:a: -l create-db,request-db,populate-db,use-db,use-memcached,enable-sru,sru-port:,help,marcflavor:,auth-idx:,biblio-idx:,zebralang:,defaultsql:,configfile:,passwdfile:,database:,adminuser:,memcached-servers:,memcached-prefix:,upload-path:, \ +TEMP=`getopt -o chrpm:l:d:f:b:a: -l create-db,request-db,populate-db,use-db,use-memcached,enable-sru,sru-port:,help,marcflavor:,auth-idx:,biblio-idx:,zebralang:,defaultsql:,configfile:,passwdfile:,database:,adminuser:,memcached-servers:,memcached-prefix:,upload-path:,letsencrypt, \ -n "$0" -- "$@"` # Note the quotes around `$TEMP': they are essential! @@ -379,7 +434,7 @@ CLO_AUTHORITIES_INDEXING_MODE="" CLO_MEMCACHED_SERVERS="" CLO_MEMCACHED_PREFIX="" CLO_UPLOAD_PATH="" - +CLO_LETSENCRYPT="" while true ; do case "$1" in @@ -421,6 +476,8 @@ while true ; do SRU_SERVER_PORT="$2" ; shift 2 ;; --upload-path) CLO_UPLOAD_PATH="$2" ; shift 2 ;; + --letsencrypt) + CLO_LETSENCRYPT="yes" ; shift ;; -h|--help) usage ; exit 0 ;; --) @@ -516,6 +573,8 @@ check_apache_config opacdomain="$OPACPREFIX$name$OPACSUFFIX$DOMAIN" intradomain="$INTRAPREFIX$name$INTRASUFFIX$DOMAIN" +# Check everything is ok with letsencrypt, die otherwise +check_letsencrypt if [ -f $PASSWDFILE ] && [ `cat $PASSWDFILE | grep "^$name:"` ] then @@ -600,8 +659,13 @@ FLUSH PRIVILEGES; eof fi #` + if [ "$CLO_LETSENCRYPT" = "yes" ]; then + APACHE_CONFIGFILE="apache-site-https.conf.in" + else + APACHE_CONFIGFILE="apache-site.conf.in" + fi # Generate and install Apache site-available file and log dir. - generate_config_file apache-site.conf.in \ + generate_config_file $APACHE_CONFIGFILE \ "/etc/apache2/sites-available/$name.conf" mkdir "/var/log/koha/$name" chown "$username:$username" "/var/log/koha/$name" @@ -710,6 +774,11 @@ then # Start Indexer daemon koha-indexer --start "$name" fi + + if [ "$CLO_LETSENCRYPT" = "yes" ]; then + # Get letsencrypt certificates + letsencrypt_instance + fi fi diff --git a/debian/scripts/koha-foreach b/debian/scripts/koha-foreach index 925d90b..7a3341d 100755 --- a/debian/scripts/koha-foreach +++ b/debian/scripts/koha-foreach @@ -30,6 +30,8 @@ do --nosip) listopts="$listopts --nosip";; --plack) listopts="$listopts --plack";; --noplack) listopts="$listopts --noplack";; + --letsencrypt) listopts="$listopts --letsencrypt" ;; +--noletsencrypt) listopts="$listopts --noletsencrypt" ;; *) break;; esac shift diff --git a/debian/scripts/koha-functions.sh b/debian/scripts/koha-functions.sh index 87a84a1..ef71a3a 100755 --- a/debian/scripts/koha-functions.sh +++ b/debian/scripts/koha-functions.sh @@ -84,6 +84,17 @@ is_email_enabled() fi } +is_letsencrypt_enabled() +{ + local instancename=$1 + + if [ -e /var/lib/koha/$instancename/letsencrypt.enabled ]; then + return 0 + else + return 1 + fi +} + is_sip_enabled() { local instancename=$1 diff --git a/debian/scripts/koha-list b/debian/scripts/koha-list index 73ce075..0dd72e1 100755 --- a/debian/scripts/koha-list +++ b/debian/scripts/koha-list @@ -36,24 +36,27 @@ show_instances() for instance in $( get_instances ); do case $show in "all") - if instance_filter_email $instance $show_email && \ - instance_filter_plack $instance $show_plack && \ - instance_filter_sip $instance $show_sip; then + if instance_filter_email $instance $show_email && \ + instance_filter_letsencrypt $instance $show_letsencrypt && \ + instance_filter_plack $instance $show_plack && \ + instance_filter_sip $instance $show_sip; then echo $instance fi ;; "enabled") if is_enabled $instance; then - if instance_filter_email $instance $show_email && \ - instance_filter_plack $instance $show_plack && \ - instance_filter_sip $instance $show_sip; then + if instance_filter_email $instance $show_email && \ + instance_filter_letsencrypt $instance $show_letsencrypt && \ + instance_filter_plack $instance $show_plack && \ + instance_filter_sip $instance $show_sip; then echo $instance fi fi ;; "disabled") if ! is_enabled $instance; then - if instance_filter_email $instance $show_email && \ - instance_filter_plack $instance $show_plack && \ - instance_filter_sip $instance $show_sip; then + if instance_filter_email $instance $show_email && \ + instance_filter_letsencrypt $instance $show_letsencrypt && \ + instance_filter_plack $instance $show_plack && \ + instance_filter_sip $instance $show_sip; then echo $instance fi fi ;; @@ -106,6 +109,28 @@ instance_filter_plack() return 1 } +instance_filter_letsencrypt() +{ + local instancename=$1 + local show_letsencrypt=$2; + + case $show_letsencrypt in + "all") + return 0 ;; + "enabled") + if is_letsencrypt_enabled $instancename; then + return 0 + fi ;; + "disabled") + if ! is_letsencrypt_enabled $instancename; then + return 0 + fi ;; + esac + + # Didn't match any criteria + return 1 +} + instance_filter_email() { local instancename=$1 @@ -150,6 +175,17 @@ set_show_email() fi } +set_show_letsencrypt() +{ + local letsencrypt_param=$1 + + if [ "$show_letsencrypt" = "all" ]; then + show_letsencrypt=$letsencrypt_param + else + die "Error: --letsencrypt and --noletsencrypt are mutually exclusive." + fi +} + set_show_plack() { local plack_param=$1 @@ -190,6 +226,8 @@ Options: --nosip Show instances with SIP disabled --plack Show instances with Plack enabled --noplack Show instances with Plack disabled + --letsencrypt Show instances with letsencrypt enabled + --noletsencrypt Show instances with letsencrypt disabled --help | -h Show this help The filtering options can be combined, and you probably want to do this @@ -201,23 +239,26 @@ show="all" show_email="all" show_sip="all" show_plack="all" +show_letsencrypt="all" -args=$(getopt -l help,enabled,disabled,email,noemail,sip,nosip,plack,noplack -o h -n $0 -- "$@") +args=$(getopt -l help,enabled,disabled,email,noemail,sip,nosip,plack,noplack,letsencrypt,noletsencrypt -o h -n $0 -- "$@") set -- $args while [ ! -z "$1" ] do case "$1" in - -h|--help) usage; exit;; - --email) set_show_email "enabled" ;; - --noemail) set_show_email "disabled" ;; - --sip) set_show_sip "enabled" ;; - --nosip) set_show_sip "disabled" ;; - --plack) set_show_plack "enabled" ;; - --noplack) set_show_plack "disabled" ;; - --enabled) set_show "enabled" ;; - --disabled) set_show "disabled" ;; - *) break;; + -h|--help) usage; exit;; + --email) set_show_email "enabled" ;; + --noemail) set_show_email "disabled" ;; + --sip) set_show_sip "enabled" ;; + --nosip) set_show_sip "disabled" ;; + --plack) set_show_plack "enabled" ;; + --noplack) set_show_plack "disabled" ;; + --letsencrypt) set_show_letsencrypt "enabled" ;; +--noletsencrypt) set_show_letsencrypt "disabled" ;; + --enabled) set_show "enabled" ;; + --disabled) set_show "disabled" ;; + *) break;; esac shift done diff --git a/debian/templates/apache-site-https.conf.in b/debian/templates/apache-site-https.conf.in new file mode 100644 index 0000000..44a4fc8 --- /dev/null +++ b/debian/templates/apache-site-https.conf.in @@ -0,0 +1,70 @@ +# Koha instance __KOHASITE__ Apache config. + +# redirect http to https +# #nohttps +# ServerName __OPACSERVER__ #nohttps +# ServerAlias __INTRASERVER__ #nohttps +# RewriteEngine On #nohttps +# RewriteCond %{HTTPS} !=on #nohttps +# RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] #nohttps +# #nohttps + +# OPAC + #https +# SSLEngine on +# SSLProtocol +TLSv1.2 +TLSv1.1 +TLSv1 +# SSLCompression off +# SSLHonorCipherOrder on +# SSLCipherSuite "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-SA- +# SSLCertificateKeyFile /etc/letsencrypt/live/__OPACSERVER__/privkey.pem +# SSLCertificateFile /etc/letsencrypt/live/__OPACSERVER__/cert.pem +# SSLCertificateChainFile /etc/letsencrypt/live/__OPACSERVER__/chain.pem + + = 2.4> + Define instance "__KOHASITE__" + + Include /etc/koha/apache-shared.conf +# Include /etc/koha/apache-shared-disable.conf +# Include /etc/koha/apache-shared-opac-plack.conf + Include /etc/koha/apache-shared-opac.conf + + ServerName __OPACSERVER__ + SetEnv KOHA_CONF "/etc/koha/sites/__KOHASITE__/koha-conf.xml" + SetEnv MEMCACHED_SERVERS "__MEMCACHED_SERVERS__" + SetEnv MEMCACHED_NAMESPACE "__MEMCACHED_NAMESPACE__" + AssignUserID __UNIXUSER__ __UNIXGROUP__ + + ErrorLog /var/log/koha/__KOHASITE__/opac-error.log +# TransferLog /var/log/koha/__KOHASITE__/opac-access.log +# RewriteLog /var/log/koha/__KOHASITE__/opac-rewrite.log + + +# Intranet + #https +# SSLEngine on +# SSLProtocol +TLSv1.2 +TLSv1.1 +TLSv1 +# SSLCompression off +# SSLHonorCipherOrder on +# SSLCipherSuite "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES +# SSLCertificateKeyFile /etc/letsencrypt/live/__OPACSERVER__/privkey.pem +# SSLCertificateFile /etc/letsencrypt/live/__OPACSERVER__/cert.pem +# SSLCertificateChainFile /etc/letsencrypt/live/__OPACSERVER__/chain.pem + + = 2.4> + Define instance "__KOHASITE__" + + Include /etc/koha/apache-shared.conf +# Include /etc/koha/apache-shared-disable.conf +# Include /etc/koha/apache-shared-intranet-plack.conf + Include /etc/koha/apache-shared-intranet.conf + + ServerName __INTRASERVER__ + SetEnv KOHA_CONF "/etc/koha/sites/__KOHASITE__/koha-conf.xml" + SetEnv MEMCACHED_SERVERS "__MEMCACHED_SERVERS__" + SetEnv MEMCACHED_NAMESPACE "__MEMCACHED_NAMESPACE__" + AssignUserID __UNIXUSER__ __UNIXGROUP__ + + ErrorLog /var/log/koha/__KOHASITE__/intranet-error.log +# TransferLog /var/log/koha/__KOHASITE__/intranet-access.log +# RewriteLog /var/log/koha/__KOHASITE__/intranet-rewrite.log + diff --git a/install_misc/debian.packages b/install_misc/debian.packages index f520898..7d0c747 100644 --- a/install_misc/debian.packages +++ b/install_misc/debian.packages @@ -8,6 +8,7 @@ idzebra-2.0 install idzebra-2.0-common install idzebra-2.0-doc install idzebra-2.0-utils install +letsencrypt install libalgorithm-checkdigits-perl install libanyevent-http-perl install libanyevent-perl install -- 2.7.0