dhach.acme_letsencrypt
acme-letsencrypt
Resumen
Este es un rol puro de Ansible para lograr lo siguiente:
- Crear claves privadas ECC o RSA
- Generar solicitudes de firma de certificados (para múltiples dominios)
- Enviar la solicitud a Let's Encrypt o a otro proveedor ACME de tu elección
- Instalar todos los archivos en una ubicación determinista
Escribí este rol para poder obtener certificados de Let's Encrypt sin depender de herramientas de terceros (como certbot, acme-tiny, acme.sh, etc.) y tener más control sobre lo que está sucediendo.
Actualmente, solo se admite el tipo de desafío HTTP.
Dado que este es solo un rol de Ansible, no maneja la renovación automática del certificado. Para lograr esto, puedes ejecutar este rol periódicamente desde tu pipeline de CI/CD o hacer que funcione en modo Pull de Ansible con un crontab.
Versión de Ansible
Este rol, comenzando con la versión 2.0.0, solo está garantizado para ser compatible con Ansible >=2.10.
Si necesitas compatibilidad con <2.10 (es decir, "pre-collections"), usa cualquier versión con una etiqueta 1.x.x.
Requisitos
En el host objetivo:
- openssl
Ejemplos de playbooks
Usando una clave ECC secp384r1 para un certificado SAN (múltiples dominios).
- name: "Obtener certificados para webserver01"
hosts: webserver01
become: true
roles:
- dhach.acme_letsencrypt
vars:
le_base_directory: /etc/letsencrypt
le_certificates:
- name: ecc.example.com
domains:
- secp.example.com
- ecc.example.com
key:
curve: secp384r1
Ahora usa una clave secp256r1, cámbiala forzosamente y luego emite la solicitud contra el servidor de validación de producción de Let's Encrypt:
- name: "Obtener certificados para webserver02"
hosts: webserver02
become: true
roles:
- dhach.acme_letsencrypt
vars:
le_acme_directory: https://acme-v02.api.letsencrypt.org/directory
le_certificates:
- name: another-domain.example.com
domains:
- another-domain-abc.example.com
- another-domain-def.example.com
- another-domain-ghi.example.com
- another-domain-jkl.example.com
- another-domain-mno.example.com
ssl:
type: ECC
curve: secp256r1
renew: true
O usa claves RSA para obtener un certificado para cada dominio:
- name: "Obtener certificados para webserver03"
hosts: webserver03
become: true
roles:
- dhach.acme_letsencrypt
vars:
le_certificates:
- name: example.com
domains:
- foo.example.com
key:
type: RSA
size: 4096
- name: more.example.com
domains:
- bar.example.com
key:
type: RSA
size: 4096
Dónde encontrar los archivos
Todas las claves generadas, solicitudes de certificado y certificados subsiguientes se pueden encontrar bajo el valor de {{ le_base_directory }}/{{ le_certificates['name'] }}
.
Por ejemplo, si especificas un name
de 'example.com', y le_base_directory
está configurado a '/etc/letsencrypt/', el resultado sería:
/etc/letsencrypt/example.com/
├── domain.csr
├── domain.key
├── domain.pem
├── fullchain.pem
└── intermediate.pem
Cómo configurar tu servidor web
Los servidores ACME requieren que respondas a un desafío colocando un archivo con un nombre y contenido específico en una ruta predefinida que tu servidor web sirve a través de HTTP.
Tu servidor web debe servir la ubicación /.well-known/acme-challenge con el contenido del siguiente directorio: {{ le_base_directory }}/.well-known/acme-challenge/
.
Ejemplos si usas el valor predeterminado para le_base_directory
:
Nginx:
location /.well-known/acme-challenge {
alias /etc/letsencrypt/.well-known/acme-challenge/;
}
Apache:
Alias /.well-known/acme-challenge/ "/etc/letsencrypt/.well-known/acme-challenge/"
<Directory "/etc/letsencrypt/.well-known/acme-challenge/">
AllowOverride None
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
Require method GET POST OPTIONS
</Directory>
Variables y valores predeterminados del rol
Todas las variables definidas se enumeran a continuación, con sus respectivas variables predeterminadas.
Solicitudes de certificado
Puedes controlar para qué dominios debe solicitarse el certificado. También tienes la opción de especificar detalles sobre la generación de claves. Las opciones varían ligeramente entre claves RSA y ECC.
Todas las solicitudes de certificado se construyen como solicitudes SAN (SubjectAltName).
ECC:
le_certificates:
- name: example.com # esencialmente un identificador interno y dónde guardar el archivo
domains: # una lista de dominios para los que deseas que se emita el certificado
- foo.example.com
- bar.example.com
key: # detalles para la clave privada, si se va a generar una
type: ECC # (obligatorio) Tipos soportados: ECC, RSA
curve: secp384r1 # (opcional | predeterminado: secp384r1) Curva para clave ECC (sin efecto en claves RSA).
renew: false # (opcional | predeterminado: false) Si se debe recrear la clave forzosamente. Siempre mantendrá una copia de seguridad.
RSA:
le_certificates:
- name: example.com # esencialmente un identificador interno y dónde guardar el archivo
domains: # una lista de dominios para los que deseas que se emita el certificado
- foo.example.com
- bar.example.com
key: # detalles para la clave privada, si se va a generar una
type: RSA # (obligatorio) Tipos soportados: ECC, RSA
size: 4096 # (opcional | predeterminado: 4096) Longitud de la clave RSA (sin efecto en claves ECC)
renew: false # (opcional | predeterminado: false) Si se debe recrear la clave forzosamente. Siempre mantendrá una copia de seguridad.
Directorios y permisos
le_base_directory
: El directorio base donde poner todos los archivos generados (predeterminado: /etc/letsencrypt)
le_files_owner
: Quién debe ser el propietario de los archivos y carpetas generados (predeterminado: root)
le_files_group
: A qué grupo deben pertenecer los archivos y carpeta generados (predeterminado: root)
Clave de cuenta de Let's Encrypt
le_account_key_path
: Dónde poner (o encontrar) la clave de cuenta de Let's Encrypt (predeterminado: "{{ le_base_directory }}/account.key")
le_account_key_type
: Qué tipo de clave (RSA, ECC) usar para la clave de cuenta (predeterminado: RSA)
le_account_key_size
: El tamaño de la clave. Solo para claves RSA. (predeterminado: 4096)
le_account_key_curve
: Qué curva usar. Solo para claves ECC, no tiene efecto para claves RSA. (predeterminado: secp384r1)
le_account_key_regenerate
: Si se debe regenerar una clave existente o no. Mantendrá una copia de seguridad. (predeterminado: false)
Desafortunadamente, Let's Encrypt no admite fácilmente claves de cuenta ECC. Es mejor dejarlo en RSA 4096.
Versión y directorio de Let's Encrypt / ACME
le_acme_version
: Versión de ACME a usar. Puede ser necesario si eliges usar otro emisor que no sea Let's Encrypt (predeterminado: 2)
le_acme_directory
: La URL del directorio ACME para solicitar certificados. Por razones de seguridad, el valor predeterminado se establece en Let's Encrypt Staging (predeterminado: https://acme-staging-v02.api.letsencrypt.org/directory)
El directorio de producción de Let's Encrypt es: https://acme-v02.api.letsencrypt.org/directory.
le_renew_if_invalid_after
: Intentar renovar los certificados si son válidos por menos de esta cantidad de días (predeterminado: 30)
le_force_renew
: intentar forzar la renovación de los certificados (predeterminado: false)
le_csr_only
: Si solo deseas generar claves privadas y CSRs, establece esto como verdadero. Puede ser útil para la depuración. (predeterminado: false)
Contribuir y problemas
Todas las contribuciones son bienvenidas. No dudes en abrir problemas o crear solicitudes de extracción.
Con gusto revisaré cualquier problema planteado y siempre intentaré mejorar el rol.
Pruebas
Todas las pruebas se realizan con Molecule.
Un pipeline de CI se realiza con GitHub Actions y utiliza una estrategia de matriz, que prueba en Ubuntu, Debian y CentOS.
Para comenzar con pruebas locales, configura un entorno Python local, instala todas las dependencias y ejecuta las pruebas. Esto requiere que Docker esté instalado en tu máquina (o usando Docker-Machine):
python3 -m venv venv
source venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r test-requirements.txt
molecule test
Dado que este rol requiere esencialmente emitir solicitudes contra un servidor ACME y, por lo tanto, necesitaría tener control sobre un dominio para el cual establecer dinámicamente un registro DNS, las pruebas se limitan a comprobar si las claves y CSRs se crean y están presentes, y si contienen el contenido esperado.
Probar el rol completo con toda su funcionalidad se realiza contra el servidor de staging de Let's Encrypt en una máquina real conectada a Internet, pero manualmente.
Licencia
Licencia Pública General GNU v3.0
Requests certificates from Let's Encrypt (or another ACME server)
ansible-galaxy install dhach.acme_letsencrypt