Instructivo para instalar y configurar Let's Encrypt

Exploración de la solución en #5191 y despliegue en #5275.

Referencia: la documentación de Let's Encrypt

Introducción

Let's Encrypt es un una autoridad certificadora (CA) libre, abierta, para el beneficio publico. Es un servicio proporcionado por Internet Security Research Group (ISRG), en el que está involucrada la EFF. En esta guía veremos como podemos obtener un certificado SSL sin costo, sólo demostrando ser tener el dominio registrado y configurado en un servidor web.

Referencia rápida de renovación

El proceso de emisión de certificado

Let's Encrypt entrega certificados a los clientes del protocolo ACME. El cliente corre en general en el servidor en el que se pretende instalar un certificado, correspondiente a cierto o ciertos nombres de dominios. Se lo puede hacer correr en otro servidor, pero esto significará procesos de intercambio manual entre varios servidores.

En el proceso de solicitud por un cliente, primero se generan en el servidor en el que corre una clave privada (que no saldrá de ahí) y con ésta una solicitud de certificación para el o los dominios solicitados.

Para emitir el certificado, el servidor de let's encrypt primero verificará que uno es titular del dominio que solitica. Para ello, la autoridad certificadora entregará un "challange", que el cliente deberá publicar en web (puerto 80 o 443) en el dominio solicitados.

En varios casos, el cliente es también capaz de configurar el servidor web del cliente, en particular con el servidor apache.

Todo este proceso está automatizado, y puede ser invisible al usuario que corre el cliente.

Instalación

Referencia: la documentación de Let's Encrypt

Ahora hay paquetes para debian, por lo cual lo que sigue está un poco desactualizado.

Ahora el cliente se llama CertBot, y se instala como documentado acá

Antes descargábamos el cliente desde el repositorio Github.

cd /usr/local/src/
sudo git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt

Corremos el script de instalación de Letsencrypt

sudo -h ./letsencrypt-auto

La primera vez, descargará unas cuantas dependencias. (Aparentemente, arma un entorno virtual en pythonm, para no contaminar el sistema de base).

El proceso hará algunas preguntas, en particular solicitará un mail, al cual luego serán enviados los avisos de expiración de certificados.

Con una configuración simple de apache, esto puede ser suficiente para tener un certificado, y configurarlo en el servidor web.

Si estamos en servidor.csic.edu.uy, por ejemplo, el nuevo certificado sera guardado en /etc/letsencrypt/live/domain.comservidor.csic.edu.uy

Podemos verificar la configuración SSL en por ejemplo en: https://globalsign.ssllabs.com/

configuración de dominios reales

Generalmente tenemos un manejo más complejo de los dominios en nuestros servidores, y el cliente let's encrypt no siempre es capaz de autodetectarlos.

En ese caso, debemos correr el comando con los dominios necesarios en opción. El nombre canónico del servidor debe estar entre los dominios configurados, y conviene que sea el último de la lista.

Por ejemplo, en Carroll configuramos:

./letsencrypt-auto -d media.softwarelibre.edu.uy -d media.interior.edu.uy -d media.interior.udelar.edu.uy -d carroll.csic.edu.uy

El cliente solicita que le indiquemos en qué VirtualHost de configuración del Apache deberá procurar configurar cada dominio.

También puede solicitar otros parámetros, como saber si debe configurar una redirección del http al https, o si el servidor responde en los dos puertos.

Igual, siempre conviene verificar luego la configuración Apache del servidor.

Procesamiento de errores

Si obtenemos un error igual o similar a este:

/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util/ssl_.py:79: 
          InsecurePlatformWarning: A true SSLContext object is not available. 
          This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. 
          For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning

Debemos de actualizar algunas bibliotecas de Python mediante el siguiente comando

pip install pyopenssl ndg-httpsclient pyasn1

Usar Let's Encrypt con Zimbra

Este procedimiento aquí detallado fue aplicado en #5257. Nos basamos en este tutorial
Previamente en el servidor con zimbra se debe de tener clonado el repositorio de Let's Encrypt.

Es oportuno primero verificar la lista de dominios instalados en el servidor. (y no olvidar los smtp., impas., etc);

root@dirac:~# su - zimbra
zimbra@dirac:~$ zmprov gad
csic.edu.uy
cci.edu.uy
ei.udelar.edu.uy
correo.csic.edu.uy
udelar.net
ei.ur.edu.uy

Luego se detiene el servicio de jetty o nginx de zimbra:
su - zimbra
zmproxyctl stop
zmmailboxdctl stop

Obtenemos un certificado para todos los dominios del servidor. Así para Godel:
root@godel:~/letsencrypt# ./letsencrypt-auto certonly --standalone -d godel.csic.edu.uy -d correo.cup.edu.uy -d imaps.cup.edu.uy -d smtps.cup.edu.uy -d correo.cut.edu.uy -d correo.cepe.edu.uy -d correo.cerrolargo.udelar.edu.uy -d correo.cur.edu.uy -d correo.cure.edu.uy -d imaps.cure.edu.uy -d smtps.cure.edu.uy -d correo.cucel.edu.uy -d correo.interior.udelar.edu.uy -d correo.litoralnorte.udelar.edu.uy -d correo.noreste.udelar.edu.uy -d correo.posgrados.udelar.edu.uy  -d correo.tacuarembo.udelar.edu.uy -d correo.idiis.edu.uy

En Dirac instalamos certbot-aunto en /usr/local/bin/, como recomendado en la instalación oficial para otros unix Así para Dirac:
/usr/local/bin/certbot-auto certonly --standalone -d dirac.csic.edu.uy -d correo.csic.edu.uy -d imaps.csic.edu.uy -d smtps.csic.edu.uy -d correo.cci.edu.uy -d imaps.cci.edu.uy -d smtps.cci.edu.uy -d correo.ei.udelar.edu.uy -d imaps.ei.udelar.edu.uy -d smtps.ei.udelar.edu.uy -d correo.chea.udelar.edu.uy

La respuesta:
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/godel.csic.edu.uy/fullchain.pem. Your cert
   will expire on 2016-07-14. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Habría que ver cómo renovar los certificados: por alguna razón el renew no anda, y estamos creando cada vez un nuevo certificado, que está bajando en el directorio /etc/letsencrypt/live/<servidor>.csic.edu.uy-XXXX/, donde XXXX es un serial que se incrementa:
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/godel.csic.edu.uy-0002/fullchain.pem. Your
   cert will expire on 2017-03-27. To obtain a new or tweaked version
   of this certificate in the future, simply run letsencrypt-auto
   again. To non-interactively renew *all* of your certificates, run
   "letsencrypt-auto renew" 
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Vemos los certificados:
root@godel:/etc/letsencrypt/live/godel.csic.edu.uy-0002# ls -altr
total 8
lrwxrwxrwx 1 root root   44 abr 15 16:14 privkey.pem -> ../../archive/godel.csic.edu.uy/privkey1.pem
lrwxrwxrwx 1 root root   46 abr 15 16:14 fullchain.pem -> ../../archive/godel.csic.edu.uy/fullchain1.pem
lrwxrwxrwx 1 root root   42 abr 15 16:14 chain.pem -> ../../archive/godel.csic.edu.uy/chain1.pem
lrwxrwxrwx 1 root root   41 abr 15 16:14 cert.pem -> ../../archive/godel.csic.edu.uy/cert1.pem

Workarund chahcnho

Hay que bajar el certificado root IdenTrust para mezclarlo con chain.pem:

Let's Encrypt is almost perfect, but during the files the process built, they just add the chain.pem file without the root CA. You must to use the IdenTrust root Certificate and merge it after the chain.pem

Bajamos el indetrust desde acá
Luego se edita el chain.pem. Al final del contenido del mismo hay que agregarle el IdenTrust bajado.
Además hay que agregar BEGIN Y END certificate antes y despues de dicho IdenTrust.
Luego el chain.pem tiene que quedar así:

-----BEGIN CERTIFICATE-----
YOURCHAIN
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----

Verficiamos:
root@godel:/etc/letsencrypt/live/godel.csic.edu.uy-0002# nano chain.pem 
root@godel:/etc/letsencrypt/live/godel.csic.edu.uy-0002#  /opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem 
** Verifying cert.pem against privkey.pem
Certificate (cert.pem) and private key (privkey.pem) match.
Valid Certificate: cert.pem: OK

Hacemos el backup
cp -a /opt/zimbra/ssl/zimbra /opt/zimbra/ssl/zimbra.$(date "+%Y%m%d")

Copiamos la clave privada en el directorio de zimbra:
cp privkey.pem /opt/zimbra/ssl/zimbra/commercial/commercial.key

Luego deployamos los certificados SSL:
root@godel:/etc/letsencrypt/live/godel.csic.edu.uy-0002# /opt/zimbra/bin/zmcertmgr deploycrt comm cert.pem chain.pem 
** Verifying cert.pem against /opt/zimbra/ssl/zimbra/commercial/commercial.key
Certificate (cert.pem) and private key (/opt/zimbra/ssl/zimbra/commercial/commercial.key) match.
Valid Certificate: cert.pem: OK
** Copying cert.pem to /opt/zimbra/ssl/zimbra/commercial/commercial.crt
** Appending ca chain chain.pem to /opt/zimbra/ssl/zimbra/commercial/commercial.crt
** Importing certificate /opt/zimbra/ssl/zimbra/commercial/commercial_ca.crt to CACERTS as zcs-user-commercial_ca...done.
** NOTE: mailboxd must be restarted in order to use the imported certificate.
** Saving server config key zimbraSSLCertificate...done.
** Saving server config key zimbraSSLPrivateKey...done.
** Installing mta certificate and key...done.
** Installing slapd certificate and key...done.
** Installing proxy certificate and key...done.
** Creating pkcs12 file /opt/zimbra/ssl/zimbra/jetty.pkcs12...done.
** Creating keystore file /opt/zimbra/mailboxd/etc/keystore...done.
** Installing CA to /opt/zimbra/conf/ca...done.

Se reinician todos los servicios
su - zimbRa
zmcontrol restart

Finalmente entramos y funciona perfecto: https://correo.cup.edu.uy/

Configuración de Ngix

Ahora podemos solicitar un nuevo certificado SSL. Asumimos que se corre Nignx como web server. Para solicitar el certificado debemos de detener el servicio web temporalmente.

sudo service nginx stop
sudo -H ./letsencrypt-auto certonly --email hostmaster@domain.com -d domain.com
sudo service nginx start

El nuevo certificado sera guardado en /etc/letsencrypt/live/domain.com

Actualizamos la configuración de Nignx en el archivo de nuestro dominio

sudo vi /etc/nginx/conf.d/domain.com.conf

Agregamos el nuevo certificado

ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;

Probamos nuestro archivo de configuración Nignx

sudo nginx -t

y reiniciamos el servicio

sudo service nginx reload

Configuración de auto renovación de certificados

Creamos un nuevo bash script en la carpeta cron.monthly para que quede programado.

cd /etc/cron.monthly/
sudo vi letsencrypt-renew
sudo chmod +x letsencrypt-renew

Agregamos el siguiente código al script recién creado (letsencrypt-renewscript)

cd /usr/local/src/letsencrypt
sudo service nginx stop
sudo -H ./letsencrypt-auto renew
sudo service nginx start

Guardamos y corremos el script para verificar que funcione correctamente

sudo ./letsencrypt-renew

Listo!!