felixfontein.acme_certificate

acme_certificate 1.1.1

¡ESTE ROLLO ESTÁ OBSOLETO! ¡POR FAVOR UTILIZA LA VERSIÓN DE LA COLECCIÓN felixfontein.acme (https://github.com/felixfontein/ansible-acme/) EN SU LUGAR!

Permite obtener certificados de Let's Encrypt con mínima interacción con el servidor web. La mayoría del código se ejecuta en el controlador y la clave de la cuenta nunca se envía a los nodos.

El rol se puede instalar a través de Ansible Galaxy:

ansible-galaxy install felixfontein.acme_certificate

Para cambios en este rol, consulta el registro de cambios.

Descripción

Este es un rol de Ansible que puede usar cualquier CA que soporte el protocolo ACME, como Let's Encrypt o Buypass, para emitir certificados TLS/SSL para tu servidor. Este rol requiere Ansible 2.8.3 o superior y se basa en el módulo acme_certificate que viene con Ansible.

La principal ventaja de este enfoque sobre otros es que casi no se ejecuta código en tu servidor web: solo cuando usas desafíos HTTP, los archivos necesitan ser copiados a tu servidor web, y luego eliminados de él. ¡Todo lo demás se ejecuta en tu máquina local!

(Esto no cubre la instalación de los certificados, tienes que hacerlo tú mismo en otro rol).

Requisitos

Requiere la biblioteca de Python cryptography instalada en el controlador, disponible para la versión de Python utilizada para ejecutar el libro de jugadas. Si cryptography no está instalada, una versión suficientemente reciente de PyOpenSSL es actualmente soportada como alternativa por los módulos openssl_privatekey y openssl_csr de Ansible.

El binario openssl también debe estar disponible en la ruta ejecutable del controlador. Es necesario para el módulo acme_certificate en caso de que cryptography no esté instalada y se utiliza para la validación de la cadena de certificados.

Si se utilizan desafíos DNS, puede haber otros requisitos dependiendo del proveedor DNS. Por ejemplo, para Route 53 de Amazon, el módulo route53 de Ansible requiere el paquete de Python boto.

Configuración de la Clave de la Cuenta

Puedes crear una clave de cuenta usando el binario openssl de la siguiente manera:

# Clave RSA de 4096 bits
openssl genrsa 4096 -out keys/acme-account.key
# Clave ECC de 256 bits (P-256)
openssl ecparam -name prime256v1 -genkey -out keys/acme-account.key
# Clave ECC de 384 bits (P-384)
openssl ecparam -name secp384r1 -genkey -out keys/acme-account.key

Con Ansible, puedes usar el módulo openssl_privatekey de la siguiente manera:

- name: Generar clave RSA 4096
  openssl_privatekey:
    path: keys/acme-account.key
    type: RSA
    size: 4096
- name: Generar clave ECC de 256 bits (P-256)
  openssl_privatekey:
    path: keys/acme-account.key
    type: ECC
    curve: secp256r1
- name: Generar clave ECC de 384 bits (P-384)
  openssl_privatekey:
    path: keys/acme-account.key
    type: ECC
    curve: secp384r1

Asegúrate de guardar la clave de la cuenta de forma segura. A diferencia de las claves privadas de los certificados, no hay necesidad de regenerarla frecuentemente y facilita la revocación de los certificados emitidos con ella.

Variables del Rol

Ten en cuenta que desde mayo de 2020, todas las variables deben ser precedidas por acme_certificate_. Durante un tiempo, el módulo seguirá utilizando los nombres de variables antiguos (cortos) si los más largos no están definidos. Por favor, actualiza tu uso del rol lo antes posible.

Estas son las variables principales:

  • acme_certificate_acme_account: Ruta a la clave privada de la cuenta ACME. Siempre debe ser especificada.
  • acme_certificate_acme_email: Tu dirección de correo electrónico que se asociará a la cuenta ACME. Siempre debe ser especificada.
  • acme_certificate_algorithm: El algoritmo utilizado para crear claves privadas. El valor por defecto es "rsa"; otras opciones son "p-256", "p-384" o "p-521" para las curvas elípticas de NIST prime256v1, secp384r1 y secp521r1, respectivamente.
  • acme_certificate_key_length: La longitud en bits que se usará para las claves privadas RSA. El valor por defecto es 4096.
  • acme_certificate_key_name: El nombre base para almacenar las claves y certificados. El valor por defecto es el primer dominio especificado, con * reemplazado por _.
  • acme_certificate_keys_path: Dónde se almacenan las claves y certificados. El valor por defecto es "keys/".
  • acme_certificate_keys_old_path: Dónde deben ser copiadas las claves y certificados antiguos; usado en caso de que acme_certificate_keys_old_store sea verdadero. El valor por defecto es "keys/old/".
  • acme_certificate_keys_old_store: Si se establece en true, hará copias de las claves y certificados antiguos. Las copias serán almacenadas en el directorio especificado por acme_certificate_keys_old_store. El valor por defecto es false.
  • acme_certificate_keys_old_prepend_timestamp: Si las copias de las claves y certificados antiguos deben ser precedidas por la fecha y hora actuales. El valor por defecto es false.
  • acme_certificate_ocsp_must_staple: Si se solicita un certificado con la extensión OCSP Must Staple. El valor por defecto es false.
  • acme_certificate_agreement: El documento de términos de servicio con el que el usuario acepta. El valor por defecto es https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf.
  • acme_certificate_acme_directory: El directorio ACME a utilizar. El valor por defecto es https://acme-v02.api.letsencrypt.org/directory, que es el extremo de producción ACME v2 actual de Let's Encrypt.
  • acme_certificate_acme_version: La versión del directorio ACME. El valor por defecto es 2. Usa 1 para ACME v1.
  • acme_certificate_challenge: El tipo de desafío a utilizar. Debe ser http-01 para desafíos HTTP (necesita acceso al servidor web) o dns-01 para desafíos DNS (necesita acceso al proveedor DNS).
  • acme_certificate_root_certificate: El certificado raíz para el directorio ACME. El valor por defecto es https://letsencrypt.org/certs/isrgrootx1.pem para el certificado raíz de Let's Encrypt.
  • acme_certificate_deactivate_authzs: Si se deben desactivar las authzs (autorizaciones) después. El valor por defecto es true. Establecer en false para poder reutilizar authzs.
  • acme_certificate_modify_account: Si se debe crear la cuenta ACME (si no existe) y actualizar los datos de contacto (dirección de correo electrónico). El valor por defecto es true. Establecer en false si deseas usar el módulo acme_account para gestionar tu cuenta ACME (no se realiza con este rol).
  • acme_certificate_privatekey_mode: Qué modo de archivo usar para el archivo de clave privada. El valor por defecto es "0600", que significa que es legible y escribible por el propietario, pero no accesible por nadie más (excepto posiblemente root).
  • acme_certificate_select_chain: (Solo utilizable con Ansible 2.10+) Debe estar en el formato descrito aquí. Permite seleccionar la cadena de certificados a utilizar; acme_certificate_root_certificate debe usarse en conjunto. Esto se puede usar por ejemplo con Let's Encrypt para seleccionar qué certificado raíz usar.

Desafíos HTTP

Para los desafíos HTTP, las siguientes variables definen cómo los desafíos pueden ser colocados en el servidor web (remoto):

  • acme_certificate_server_location: Ubicación donde se servirá .well-known/acme-challenge/. El valor por defecto es /var/www/challenges.
  • acme_certificate_http_become: Argumento para become: para las tareas file y copy. El valor por defecto es false.
  • acme_certificate_http_challenge_user: El usuario al que pertenecen los archivos de desafío. El valor por defecto es root.
  • acme_certificate_http_challenge_group: El grupo al que pertenecen los archivos de desafío. El valor por defecto es http.
  • acme_certificate_http_challenge_folder_mode: El modo a usar para la carpeta de desafío. El valor por defecto es 0750 (octal).
  • acme_certificate_http_challenge_file_mode: El modo a usar para los archivos de desafío. El valor por defecto es 0640 (octal).

La siguiente subsección muestra cómo configurar nginx para desafíos HTTP.

Configuración de Nginx

Supongamos que para uno de tus dominios protegidos TLS/SSL, usas una redirección de HTTP a HTTPS. Supongamos que se ve así:

server {
    listen       example.com:80;
    server_name  example.com *.example.com;
    return 301   https://www.example.com$request_uri;
}

Para permitir que el rol acme_certificate coloque algo en http://*.example.com/.well-known/acme-challenge/, puedes cambiar esto a:

server {
    listen       example.com:80;
    server_name  example.com *.example.com;
    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }
    location / {
        return 301   https://www.example.com$request_uri;
    }
}

Con esta configuración de nginx, todas las demás URL en *.example.com y example.com aún se redirigen, mientras que todo en *.example.com/.well-known/acme-challenge/ se sirve desde /var/www/challenges. Al ajustar la ubicación de /var/www/challenges, también debes cambiar acme_certificate_server_location.

Incluso puedes mejorar esto redirigiendo todas las URL en *.example.com/.well-known/acme-challenge/ que no resuelven a un archivo válido en /var/www/challenges a tu servidor HTTPS también. Una forma de hacerlo es:

server {
    listen       example.com:80;
    server_name  example.com *.example.com;
    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri @forward_https;
    }
    location @forward_https {
        return 301   https://www.example.com$request_uri;
    }
    location / {
        return 301   https://www.example.com$request_uri;
    }
}

Con esta configuración, si /var/www/challenges/ está vacío, tu servidor HTTP se comportará como si la ubicación /.well-known/acme-challenge/ no estuviera especificada.

Desafíos DNS

Si se utilizan desafíos DNS, las siguientes variables definen cómo se pueden cumplir los desafíos:

  • acme_certificate_dns_provider: debe ser uno de route53, hosttech, y ns1. Cada uno necesita más información:

    • Para route53 (Amazon Route 53), las credenciales deben ser pasadas como acme_certificate_aws_access_key y acme_certificate_aws_secret_key.
    • Para hosttech (hosttech GmbH, requiere el módulo externo hosttech_dns_record).
    • Para ns1 (ns1.com), la clave para tu cuenta API debe ser pasada como acme_certificate_ns1_secret_key. También es necesaria la dependencia del módulo externo ns1_record. Suponiendo la estructura y configuraciones predeterminadas, puedes necesitar descargar 2 archivos en la máquina donde se ejecuta el libro de jugadas:
    curl --create-dirs -L -o ~/.ansible/plugins/module_utils/ns1.py https://github.com/ns1/ns1-ansible-modules/raw/master/module_utils/ns1.py
    curl --create-dirs -L -o ~/.ansible/plugins/modules/ns1_record.py https://github.com/ns1/ns1-ansible-modules/raw/master/library/ns1_record.py
    

Ten en cuenta que el código del desafío DNS no es perfecto. La funcionalidad de Route 53, Hosttech y NS1 ha sido probada. Una cosa que aún no está completa es que el código intenta extraer la zona DNS del dominio tomando los últimos dos componentes separados por puntos. Esto fallará, por ejemplo, para dominios .co.uk u otras zonas anidadas.

El soporte para más proveedores DNS puede añadirse al agregar archivos tasks/dns-NAME-create.yml y tasks/dns-NAME-cleanup.yml con contenido similar al de los archivos existentes.

Conversión de la clave de cuenta

Nota que este rol de Ansible espera que la clave de cuenta de Let's Encrypt esté en formato PEM y no en formato JWK, que es usado por el cliente oficial Let's Encrypt certbot. Si has creado una clave de cuenta con el cliente oficial y quieres usar esta clave con este rol de ansible, debes convertirla. Una herramienta que puede hacer esto es pem-jwk.

Archivos Generados

Supongamos que creaste claves TLS para www.example.com. Debes copiar los archivos relevantes a tu servidor web. El rol de ansible creó los siguientes archivos:

  • keys/www.example.com.key: esta es la clave privada para el certificado. Asegúrate de que nadie pueda acceder a ella.
  • keys/www.example.com.pem: este es el certificado en sí.
  • keys/www.example.com-chain.pem: este es el/los certificado(s) intermedio(s) necesarios para una ruta de confianza.
  • keys/www.example.com.cnf: este es un archivo de configuración de OpenSSL usado para crear la Solicitud de Firma de Certificado. Puedes eliminarlo de forma segura.
  • keys/www.example.com.csr: esta es la Solicitud de Firma de Certificado usada para obtener el certificado. Puedes eliminarlo de forma segura.
  • keys/www.example.com-fullchain.pem: este es el certificado combinado con el/los certificado(s) intermedio(s).
  • keys/www.example.com-rootchain.pem: este es el/los certificado(s) intermedio(s) combinado(s) con el certificado raíz. Puede que necesites esto para OCSP stapling.
  • keys/www.example.com-root.pem: este es el certificado raíz de Let's Encrypt.

Para configurar tu servidor web, necesitas la clave privada (keys/www.example.com.key), y bien el certificado con el/los certificado(s) intermedio(s) combinados en un archivo (keys/www.example.com-fullchain.pem), o el certificado y el/los certificado(s) intermedio(s) como dos archivos separados (keys/www.example.com.pem y keys/www.example.com-chain.pem). Si deseas usar OCSP stapling, también necesitarás keys/www.example.com-rootchain.pem.

Para mover estos archivos a tu servidor web, puedes agregar tareas como sigue:

- name: copiar claves privadas
  copy:
    src: keys/{{ item }}
    dest: /etc/ssl/private/
    owner: root
    group: root
    mode: "0400"
  with_items:
  - www.example.com.key
  notify: recargar servidor web

- name: copiar certificados
  copy:
    src: keys/{{ item }}
    dest: /etc/ssl/server-certs/
    owner: root
    group: root
    mode: "0444"
  with_items:
  - www.example.com-rootchain.pem
  - www.example.com-fullchain.pem
  - www.example.com.pem
  notify: recargar servidor web

La configuración del servidor web podría verse así (para nginx):

server {
    listen www.example.com:443 ssl;  # IPv4: escucha en la IP a la que apunta www.example.com
    listen [::]:443 ssl;             # IPv6: escucha en localhost
    server_name www.example.com;
    
    # Permitirá solo TLS 1.0 y 1.2, con una cantidad muy selectiva de cifrados.
    # De acuerdo con la prueba de servidor SSL de SSL Lab, esto bloqueará:
    #   - Android 2.3.7
    #   - IE 6 y 8 bajo Windows XP
    #   - Java 6, 7 y 8
    # Si eso no es aceptable para ti, elige otras listas de cifrados. Busca
    # por ejemplo en https://wiki.mozilla.org/Security/Server_Side_TLS
    ssl_protocols TLSv1.2 TLSv1;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "-ALL !ADH !aNULL !EXP !EXPORT40 !EXPORT56 !RC4 !3DES !eNULL !NULL !DES !MD5 !LOW ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA384 DHE-RSA-AES256-SHA256 ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA DHE-RSA-AES256-SHA";
    
    # La cadena de certificados enviada al navegador, así como la clave privada.
    # Asegúrate de que tu clave privada solo sea accesible por el servidor web durante
    # la carga de configuración (que por defecto se realiza con el usuario root).
    ssl_certificate /etc/ssl/server-certs/www.example.com-fullchain.pem;
    ssl_certificate_key /etc/ssl/private/www.example.com.key;
    
    # Para OCSP stapling, necesitamos un resolvedor DNS. Aquí solo se especifican los servidores DNS públicos de Quad9 y Google; yo los precedería por los
    # servidores DNS de tu proveedor de hosting. Por lo general, puedes encontrar sus IPs en /etc/resolv.conf en tu
    # servidor web.
    resolver 9.9.9.9 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 10s;
    
    # Habilitando OCSP stapling. Nginx se encargará de recuperar los datos OCSP
    # automáticamente. Consulta https://wiki.mozilla.org/Security/Server_Side_TLS#OCSP_Stapling
    # para obtener más detalles sobre OCSP stapling.
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/ssl/server-certs/www.example.com-rootchain.pem;
    
    # Habilita una caché de sesión SSL. Ajusta los números dependiendo del uso de tu sitio.
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 30m;
    ssl_session_tickets off;
    
    # Solo deberías usar HSTS con certificados apropiados; los de Let's Encrypt
    # son buenos para esto, los auto-firmados no. Consulta MozillaWiki para obtener más detalles:
    # https://wiki.mozilla.org/Security/Server_Side_TLS#HSTS:_HTTP_Strict_Transport_Security
    add_header Strict-Transport-Security "max-age=3155760000;";
    
    charset utf-8;
    
    access_log  /var/log/nginx/www.example.com.log combined;
    error_log  /var/log/nginx/www.example.com.log error;
    
    location / {
        root   /var/www/www.example.com;
        index  index.html;
    }
}

Dependencias

Este rol no depende de otros roles.

Ejemplo de Libro de Jugadas

Este rol se puede usar de la siguiente manera. Ten en cuenta que obtiene varios certificados y define variables que se utilizan globalmente para todos los certificados:

---
- name: obteniendo certificados para el servidor web
  hosts: webserver
  vars:
    acme_certificate_acme_account: 'keys/acme-account.key'
    acme_certificate_acme_email: '[email protected]'
    # Para desafíos HTTP:
    acme_certificate_server_location: '/var/www/challenges/'
    acme_certificate_http_challenge_user: root
    acme_certificate_http_challenge_group: http
    acme_certificate_http_challenge_folder_mode: "0750"
    acme_certificate_http_challenge_file_mode: "0640"
    # Para desafíos DNS con route53:
    acme_certificate_dns_provider: route53
    acme_certificate_aws_access_key: REPLACE_WITH_YOUR_ACCESS_KEY
    acme_certificate_aws_secret_key: REPLACE_WITH_YOUR_SECRET_KEY
    # Para desafíos DNS con ns1:
    # acme_certificate_dns_provider: ns1
    # acme_certificate_ns1_secret_key: REPLACE_WITH_YOUR_SECRET_KEY
  roles:
    - role: acme_certificate
      acme_certificate_domains: ['example.com', 'www.example.com']
      # Usar desafíos DNS:
      acme_certificate_challenge: dns-01
      # Los archivos de certificado se almacenarán en:
      #    keys/example.com.key  (clave privada)
      #    keys/example.com.csr  (solicitud de firma de certificado)
      #    keys/example.com.pem  (certificado)
      #    keys/example.com.cnf  (configuración de OpenSSL para la creación de CSR -- se puede eliminar de forma segura)
      #    keys/example.com-chain.pem  (certificado intermedio)
      #    keys/example.com-fullchain.pem  (certificado con certificado intermedio)
      #    keys/example.com-root.pem  (certificado raíz)
      #    keys/example.com-rootchain.pem  (certificado intermedio con certificado raíz)
    - role: acme_certificate
      acme_certificate_domains: ['another.example.com']
      acme_certificate_key_name: 'another.example.com-rsa'
      acme_certificate_key_length: 4096
      # Usar desafíos HTTP:
      acme_certificate_challenge: http-01
      # Los archivos de certificado se almacenarán en:
      #    keys/another.example.com-rsa.key  (clave privada)
      #    keys/another.example.com-rsa.csr  (solicitud de firma de certificado)
      #    keys/another.example.com-rsa.pem  (certificado)
      #    keys/another.example.com-rsa.cnf  (configuración de OpenSSL para la creación de CSR -- se puede eliminar de forma segura)
      #    keys/another.example.com-rsa-chain.pem  (certificado intermedio)
      #    keys/another.example.com-rsa-fullchain.pem  (certificado con certificado intermedio)
      #    keys/another.example.com-rsa-root.pem  (certificado raíz)
      #    keys/another.example.com-rsa-rootchain.pem  (certificado intermedio con certificado raíz)
    - role: acme_certificate
      acme_certificate_domains: ['another.example.com']
      acme_certificate_key_name: 'another.example.com-ecc'
      acme_certificate_algorithm: 'p-256'
      # Usar desafíos HTTP (el desafío predeterminado es http-01).
      # Los archivos de certificado se almacenarán en:
      #    keys/another.example.com-ecc.key  (clave privada)
      #    keys/another.example.com-ecc.csr  (solicitud de firma de certificado)
      #    keys/another.example.com-ecc.pem  (certificado)
      #    keys/another.example.com-ecc.cnf  (configuración de OpenSSL para la creación de CSR -- se puede eliminar de forma segura)
      #    keys/another.example.com-ecc-chain.pem  (certificado intermedio)
      #    keys/another.example.com-ecc-fullchain.pem  (certificado con certificado intermedio)
      #    keys/another.example.com-ecc-root.pem  (certificado raíz)
      #    keys/another.example.com-ecc-rootchain.pem  (certificado intermedio con certificado raíz)

Licencia

La Licencia MIT (MIT)

Copyright (c) 2018-2020 Felix Fontein

Se otorga por la presente, sin cargo, a cualquier persona que obtenga una copia de este software y archivos de documentación asociados (el "Software"), para tratar en el Software sin restricción, incluyendo sin limitación los derechos de usar, copiar, modificar, fusionar, publicar, distribuir, sublicenciar y/o vender copias del Software, y permitir a las personas a quienes se les proporciona el Software hacerlo, sujeto a las siguientes condiciones:

El aviso de copyright anterior y este aviso de permiso deberán ser incluidos en todas las copias o porciones sustanciales del Software.

EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA, INCLUYENDO PERO NO LIMITÁNDOSE A LAS GARANTÍAS DE COMERCIABILIDAD, ADECUACIÓN A UN PROPÓSITO PARTICULAR Y NO INFRACCIÓN. EN NINGÚN CASO LOS AUTORES O TITULARES DE COPYRIGHT SERÁN RESPONSABLES POR NINGUNA RECLAMACIÓN, DAÑO O OTRA RESPONSABILIDAD, YA SEA EN UNA ACCIÓN DE CONTRATO, TORTO O DE OTRA MANERA, QUE SURJA DE, DE O EN CONEXIÓN CON EL SOFTWARE O EL USO O OTRAS NEGOCIACIONES EN EL SOFTWARE.

Información del Autor

La página principal de este rol es https://github.com/felixfontein/acme-certificate/. Por favor, utiliza el rastreador de problemas para reportar problemas.

Acerca del proyecto

Wrapper of Ansible's included acme_certificate module, whose aim is that almost no code is executed on the webserver. Requires the Python cryptography library as well as the OpenSSL binary installed locally and available on executable path.

Instalar
ansible-galaxy install felixfontein.acme_certificate
Licencia
mit
Descargas
371
Propietario
felixfontein on Libera IRC