felixfontein.acme_certificate

acme_certificate 1.1.1

ЭТА РОЛЬ УСТАРЕЛА! ПОЖАЛУЙСТА, ИСПОЛЬЗУЙТЕ КОЛЛЕКЦИЮ ВМЕСТО НЕЙ!

Эта роль позволяет получать сертификаты от Let's Encrypt с минимальным взаимодействием с веб-сервером. Большая часть кода выполняется на контроллере, а ключ учетной записи никогда не отправляется на узлы.

Роль можно установить через Ansible Galaxy:

ansible-galaxy install felixfontein.acme_certificate

Изменения в этой роли можно просмотреть в журнале изменений.

Описание

Это роль Ansible, которая может использовать любой ЦС, поддерживающий протокол ACME, такой как Let's Encrypt или Buypass, для выпуска TLS/SSL сертификатов для вашего сервера. Эта роль требует Ansible 2.8.3 или новее и основана на модуле acme_certificate, который идет с Ansible.

Основное преимущество этого подхода в том, что почти никакой код не выполняется на вашем веб-сервере: только если вы используете HTTP-челленджи, файлы нужно копировать на ваш веб-сервер, а затем удалять с него. Все остальное выполняется на вашем локальном компьютере!

(Это не включает установку сертификатов, вам нужно сделать это самостоятельно в другой роли.)

Требования

Требуется библиотека Python cryptography установлена на контроллере, доступная для версии Python, используемой для выполнения плейбука. Если cryptography не установлена, достаточно новая версия PyOpenSSL в настоящее время поддерживается в качестве запасного варианта для модулей Ansible openssl_privatekey и openssl_csr.

Также должен быть доступен двоичный файл openssl в исполняемом пути на контроллере. Он нужен модулю acme_certificate в случае, если cryptography не установлена, и используется для проверки цепочки сертификатов.

Если используются DNS-челленджи, могут быть другие требования в зависимости от DNS-поставщика. Например, для Amazon Route 53, модуль Ansible route53 требует пакет Python boto.

Настройка ключа учетной записи

Вы можете создать ключ учетной записи с использованием двоичного файла openssl следующим образом:

# RSA 4096 битный ключ
openssl genrsa 4096 -out keys/acme-account.key
# ECC 256 битный ключ (P-256)
openssl ecparam -name prime256v1 -genkey -out keys/acme-account.key
# ECC 384 битный ключ (P-384)
openssl ecparam -name secp384r1 -genkey -out keys/acme-account.key

С помощью Ansible вы можете использовать модуль openssl_privatekey следующим образом:

- name: Генерация RSA 4096 ключа
  openssl_privatekey:
    path: keys/acme-account.key
    type: RSA
    size: 4096
- name: Генерация ECC 256 битного ключа (P-256)
  openssl_privatekey:
    path: keys/acme-account.key
    type: ECC
    curve: secp256r1
- name: Генерация ECC 384 битного ключа (P-384)
  openssl_privatekey:
    path: keys/acme-account.key
    type: ECC
    curve: secp384r1

Убедитесь, что вы надежно храните ключ учетной записи. В отличие от частных ключей сертификатов, нет необходимости часто его регенерировать, и это делает аннулирование сертификатов, выданных с его помощью, очень простым.

Переменные роли

Обратите внимание, что с мая 2020 года все переменные должны начинаться с acme_certificate_. В течение некоторого времени модуль все еще будет использовать старые (короткие) имена переменных, если более длинные не определены. Пожалуйста, обновите использование вашей роли как можно скорее.

Это основные переменные:

  • acme_certificate_acme_account: Путь к закрытому ключу ACME. Обязательно всегда указывать.
  • acme_certificate_acme_email: Ваш адрес электронной почты, который будет связан с учетной записью ACME. Обязательно всегда указывать.
  • acme_certificate_algorithm: Алгоритм, используемый для создания закрытых ключей. По умолчанию "rsa"; другие варианты — "p-256", "p-384" или "p-521" для эллиптических кривых NIST prime256v1, secp384r1 и secp521r1, соответственно.
  • acme_certificate_key_length: Длина ключа в битах для RSA закрытых ключей. По умолчанию 4096.
  • acme_certificate_key_name: Основное имя для хранения ключей и сертификатов. По умолчанию это первый указанный домен, где * заменяется на _.
  • acme_certificate_keys_path: Где хранятся ключи и сертификаты. Значение по умолчанию — "keys/".
  • acme_certificate_keys_old_path: Куда должны быть скопированы старые ключи и сертификаты; используется в случае, если acme_certificate_keys_old_store истинно. Значение по умолчанию — "keys/old/".
  • acme_certificate_keys_old_store: Если установлено в true, будут сделаны копии старых ключей и сертификатов. Копии будут храниться в директории, указанной в acme_certificate_keys_old_store. Значение по умолчанию — false.
  • acme_certificate_keys_old_prepend_timestamp: Следует ли добавлять текущую дату и время к копиям старых ключей и сертификатов. Значение по умолчанию — false.
  • acme_certificate_ocsp_must_staple: Требуется ли сертификат с расширением OCSP Must Staple. Значение по умолчанию — false.
  • acme_certificate_agreement: Документ условий обслуживания, с которым пользователь согласен. Значение по умолчанию — https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf.
  • acme_certificate_acme_directory: ACME каталог для использования. По умолчанию https://acme-v02.api.letsencrypt.org/directory, что является текущей производственной конечной точкой ACME v2 от Let's Encrypt.
  • acme_certificate_acme_version: Версия каталога ACME. Значение по умолчанию — 2. Используйте 1 для ACME v1.
  • acme_certificate_challenge: Тип челленджа, который нужно использовать. Должен быть http-01 для HTTP челленджей (необходим доступ к веб-серверу) или dns-01 для DNS челленджей (необходим доступ к DNS-поставщику).
  • acme_certificate_root_certificate: Корневой сертификат для каталога ACME. Значение по умолчанию — https://letsencrypt.org/certs/isrgrootx1.pem для корневого сертификата Let's Encrypt.
  • acme_certificate_deactivate_authzs: Следует ли деактивировать authz (авторизации) после этого. Значение по умолчанию — true. Установите в false, чтобы иметь возможность повторно использовать authz.
  • acme_certificate_modify_account: Следует ли создать учетную запись ACME (если она не существует) и обновить контактные данные (адрес электронной почты). Значение по умолчанию — true. Установите в false, если вы хотите использовать модуль acme_account для управления своей учетной записью ACME (это не делает эта роль).
  • acme_certificate_privatekey_mode: Какой режим файла использовать для файла закрытого ключа. Значение по умолчанию — "0600", что означает, что он доступен для чтения и записи только владельцу, но не доступен другим (за исключением, возможно, root).
  • acme_certificate_select_chain: (Доступно только для Ansible 2.10+) Должен быть в формате, описанном здесь. Позволяет выбрать используемую цепочку сертификатов; acme_certificate_root_certificate должен использоваться совместно. Например, это можно использовать с Let's Encrypt, чтобы выбрать, какой корневой сертификат использовать.

HTTP-челленджи

Для HTTP челленджей следующие переменные определяют, как челленджи могут быть размещены на (удаленном) веб-сервере:

  • acme_certificate_server_location: Локация, откуда будет обслуживаться .well-known/acme-challenge/. По умолчанию /var/www/challenges.
  • acme_certificate_http_become: Аргумент для become: для задач file и copy. Значение по умолчанию — false.
  • acme_certificate_http_challenge_user: Пользователь, которому принадлежат файлыChallenge. Значение по умолчанию — root.
  • acme_certificate_http_challenge_group: Группа, которой принадлежат файлыChallenge. Значение по умолчанию — http.
  • acme_certificate_http_challenge_folder_mode: Режим, который следует использовать для папки челленджей. Значение по умолчанию — 0750 (восьмеричный).
  • acme_certificate_http_challenge_file_mode: Режим, который следует использовать для файлов челленджей. Значение по умолчанию — 0640 (восьмеричный).

Следующий подраздел показывает, как настроить nginx для HTTP челленджей. Настройка других веб-серверов может быть выполнена аналогичным образом.

Настройка Nginx

Предположим, что для одного из ваших защищенных доменов TLS/SSL вы используете перенаправление HTTP на HTTPS. Предположим, что оно выглядит так:

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

Чтобы позволить роли acme_certificate разместить что-то на http://*.example.com/.well-known/acme-challenge/, вы можете изменить это на:

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;
    }
}

С этой конфигурацией nginx все остальные URL на *.example.com и example.com по-прежнему перенаправляются, в то время как все, что в *.example.com/.well-known/acme-challenge/, обслуживается из /var/www/challenges. При изменении расположения /var/www/challenges также необходимо изменить acme_certificate_server_location.

Вы даже можете улучшить это, перенаправляя все URL в *.example.com/.well-known/acme-challenge/, которые не соответствуют действительному файлу в /var/www/challenges, на ваш HTTPS-сервер. Один из способов сделать это:

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;
    }
}

С этой конфигурацией, если /var/www/challenges/ пуст, ваш HTTP сервер будет вести себя так, будто локация /.well-known/acme-challenge/ не указана.

DNS Челленджи

Если используются DNS челленджи, следующие переменные определяют, как могут быть выполнены челленджи:

  • acme_certificate_dns_provider: должен быть одним из route53, hosttech и ns1. Каждый из них требует дополнительной информации:

    • Для route53 (Amazon Route 53) учетные данные должны быть переданы как acme_certificate_aws_access_key и acme_certificate_aws_secret_key.
    • Для hosttech (hosttech GmbH требуется внешний hosttech_dns_record модуль).
    • Для ns1 (ns1.com) ключ вашей учетной записи API должен быть передан как acme_certificate_ns1_secret_key. Это также зависит от внешнего модуля ns1_record. Предполагая стандартную структуру каталогов и настройки, вам может понадобиться загрузить 2 файла на машину, где выполняется плейбук:
    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
    

Обратите внимание, что код DNS челленджей не идеален. Функциональность Route 53, Hosttech и NS1 была протестирована. Одна вещь, которая еще не завершена, заключается в том, что код пытается извлечь DNS-зону из домена, беря последние две компоненты, разделенные точками. Это приведет к сбою, например, для доменов .co.uk или других вложенных зон.

Поддержка большее количество DNS-поставщиков может быть добавлена путем добавления файлов tasks/dns-NAME-create.yml и tasks/dns-NAME-cleanup.yml с аналогичным содержимым, как в существующих файлах.

Конвертация ключа учетной записи

Обратите внимание, что эта роль Ansible ожидает, что ключ учетной записи Let's Encrypt будет в формате PEM, а не в формате JWK, который используется официальным клиентом Let's Encrypt certbot. Если вы создали ключ учетной записи с помощью официального клиента и хотите использовать этот ключ с этой ролью Ansible, вам нужно будет его конвертировать. Один из инструментов, который может это сделать — pem-jwk.

Сгенерированные файлы

Предположим, вы создали TLS-ключи для www.example.com. Вам нужно скопировать соответствующие файлы на ваш веб-сервер. Роль ansible создала следующие файлы:

  • keys/www.example.com.key: это закрытый ключ для сертификата. Убедитесь, что никто не может его получить.
  • keys/www.example.com.pem: это сам сертификат.
  • keys/www.example.com-chain.pem: это промежуточные сертификаты, необходимые для доверительной цепочки.
  • keys/www.example.com.cnf: это файл конфигурации OpenSSL, используемый для создания запроса на подпись сертификата (CSR). Его можно безопасно удалить.
  • keys/www.example.com.csr: это запрос на сертификат, используемый для получения сертификата. Его можно безопасно удалить.
  • keys/www.example.com-fullchain.pem: это сертификат, объединенный с промежуточными сертификатами.
  • keys/www.example.com-rootchain.pem: это промежуточные сертификаты, объединенные с корневым сертификатом. Вам, возможно, понадобится это для OCSP stapling.
  • keys/www.example.com-root.pem: это корневой сертификат Let's Encrypt.

Для настройки вашего веб-сервера вам нужен закрытый ключ (keys/www.example.com.key), и либо сертификат с объединенными промежуточными сертификатами в одном файле (keys/www.example.com-fullchain.pem), либо сертификат и промежуточные сертификаты как два отдельных файла (keys/www.example.com.pem и keys/www.example.com-chain.pem). Если вы хотите использовать OCSP stapling, вам также понадобится keys/www.example.com-rootchain.pem.

Чтобы перенести эти файлы на ваш веб-сервер, вы можете добавить такие задачи:

- name: копирование закрытых ключей
  copy:
    src: keys/{{ item }}
    dest: /etc/ssl/private/
    owner: root
    group: root
    mode: "0400"
  with_items:
  - www.example.com.key
  notify: перезагрузить веб-сервер

- name: копирование сертификатов
  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: перезагрузить веб-сервер

Конфигурация веб-сервера может выглядеть следующим образом (для nginx):

server {
    listen www.example.com:443 ssl;  # IPv4: слушать IP, на который указывает www.example.com
    listen [::]:443 ssl;             # IPv6: слушать localhost
    server_name www.example.com;
    
    # Разрешаю только TLS 1.0 и 1.2, с очень выборочными шифрами.
    # По данным SSL Lab's SSL server test это будет блокировать:
    #   - Android 2.3.7
    #   - IE 6 и 8 на Windows XP
    #   - Java 6, 7 и 8
    # Если это для вас неприемлемо, выберите другие списки шифров. Посмотрите например на
    # 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";
    
    # Цепочка сертификатов, отправляемая браузеру, а также закрытый ключ.
    # Убедитесь, что ваш закрытый ключ доступен только веб-серверу во время загрузки конфигурации
    # (что по умолчанию делает пользователь root).
    ssl_certificate /etc/ssl/server-certs/www.example.com-fullchain.pem;
    ssl_certificate_key /etc/ssl/private/www.example.com.key;
    
    # Для OCSP stapling нам нужен DNS резолвер. Здесь указаны только публичные Quad9 и
    # Google DNS серверы; я бы добавил их перед DNS серверами вашего хостера.
    # Обычно вы можете найти их IP-адреса в /etc/resolv.conf на вашем веб-сервере.
    resolver 9.9.9.9 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 10s;
    
    # Включение OCSP stapling. Nginx позаботится о получении OCSP данных
    # автоматически. См. [https://wiki.mozilla.org/Security/Server_Side_TLS#OCSP_Stapling]
    # для подробностей о OCSP stapling.
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/ssl/server-certs/www.example.com-rootchain.pem;
    
    # Включает кэш сессий SSL. Настройте числа в зависимости от использования вашего сайта.
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 30m;
    ssl_session_tickets off;
    
    # Вы должны использовать HSTS только с правильными сертификатами; сертификаты от Let's Encrypt
    # подходят для этого, самоподписанные не подходят. См. MozillaWiki для получения более подробной информации:
    # [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;
    }
}

Зависимости

Эта роль не зависит от других ролей.

Пример плейбука

Эту роль можно использовать следующим образом. Обратите внимание, что она получает несколько сертификатов и определяет переменные, используемые для всех сертификатов глобально:

---
- name: получение сертификатов для веб-сервера
  hosts: webserver
  vars:
    acme_certificate_acme_account: 'keys/acme-account.key'
    acme_certificate_acme_email: '[email protected]'
    # Для 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"
    # Для DNS челленджей с 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
    # Для DNS челленджей с 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']
      # Использовать DNS челленджи:
      acme_certificate_challenge: dns-01
    - role: acme_certificate
      acme_certificate_domains: ['another.example.com']
      acme_certificate_key_name: 'another.example.com-rsa'
      acme_certificate_key_length: 4096
      # Использовать HTTP челленджи:
      acme_certificate_challenge: http-01
    - role: acme_certificate
      acme_certificate_domains: ['another.example.com']
      acme_certificate_key_name: 'another.example.com-ecc'
      acme_certificate_algorithm: 'p-256'

Лицензия

Лицензия MIT (MIT)

Copyright (c) 2018-2020 Felix Fontein

Настоящим предоставляется разрешение, безвозмездно, любому лицу, получившему копию этого программного обеспечения и сопутствующих документационных файлов (далее – "Программное обеспечение"), распоряжаться Программным обеспечением без ограничений, включая, без ограничения, права использовать, копировать, модифицировать, объединять, публиковать, распространять, предоставлять сублицензии и/или продавать копии Программного обеспечения, а также разрешать лицам, которому Программное обеспечение предоставлено, делать это, при соблюдении следующих условий:

Вышеуказанное уведомление об авторских правах и настоящее разрешение должны быть включены во все копии или значительные части Программного обеспечения.

ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ "КАК ЕСТЬ", БЕЗ ГАРАНТИЙ КАКОГО-ЛИБО РОДА, ЯВНЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ КОММЕРЧЕСКОЙ ЦЕННОСТИ, ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ И НАРУШЕНИЯ. В НИКТОРОМ СЛУЧАЕ АВТОРЫ ИЛИ ДЕРЖАТЕЛИ АВТОРСКИХ ПРАВ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ЗА ЛЮБЫЕ ИСКИ, УБЫТКИ ИЛИ ДРУГИЕ ОБЯЗАННОСТИ, ПО КОТОРЫМ БУДЕТ ВЕДЕН ДИАЛОГ В УСЛОВИЯХ ДОГОВОРА, НАРУШЕНИЯ ИЛИ ИНЫМ ОБРАЗОМ, ВОЗНИКАЮЩИЕ ИЗ ИЛИ СВЯЗАННЫЕ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЗОВАНИЕМ ИЛИ ДРУГИМИ СДЕЛКИ В ПРОГРАММНОМ ОБЕСПЕЧЕНИИ.

Информация об авторе

Домашняя страница для этой роли — https://github.com/felixfontein/acme-certificate/. Пожалуйста, используйте трекер проблем для сообщения о проблемах.

О проекте

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.

Установить
ansible-galaxy install felixfontein.acme_certificate
Лицензия
mit
Загрузки
371
Владелец
felixfontein on Libera IRC