diff --git a/sync_letsencrypt_certs_from_storm.yml b/sync_letsencrypt_certs_from_storm.yml index 39b2f44..7bbb422 100644 --- a/sync_letsencrypt_certs_from_storm.yml +++ b/sync_letsencrypt_certs_from_storm.yml @@ -7,8 +7,8 @@ become: true vars: local_tmp_dir: "/tmp/ansible_certs" - # По умолчанию пустой список означает: обрабатываем ВСЕ найденные домены target_certs: [] + ansible_python_interpreter: /usr/bin/python3 tasks: - name: Динамический поиск папок доменов ansible.builtin.find: @@ -20,46 +20,50 @@ - name: Формирование списка доменов с учетом фильтрации ansible.builtin.set_fact: - dynamic_domains: >- - {% if target_certs | length > 0 %} - {{ found_live_dirs.files | map(attribute='path') | map('basename') | intersect(target_certs) | list }} - {% else %} - {{ found_live_dirs.files | map(attribute='path') | map('basename') | list }} - {% endif %} + dynamic_domains: "{{ (found_live_dirs.files | map(attribute='path') | map('basename') | list) if target_certs | length == 0 else (found_live_dirs.files | map(attribute='path') | map('basename') | intersect(target_certs) | list) }}" cacheable: true - name: Проверка, что список доменов для переноса не пуст ansible.builtin.meta: end_play when: dynamic_domains | length == 0 - comment: "Скрипт остановится, если переданных доменов нет на сервере-источнике" - name: Вывод списка доменов, выбранных для синхронизации ansible.builtin.debug: msg: "Будут синхронизированы следующие сертификаты: {{ dynamic_domains }}" - - name: Создание изолированной папки на вашем ПК + - name: МАКСИМАЛЬНАЯ БЕЗОПАСНОСТЬ - Создание изолированной папок на вашем ПК ansible.builtin.file: path: "{{ local_tmp_dir }}/{{ item }}" state: directory mode: '0700' delegate_to: localhost + become: false loop: [ 'archive', 'live', 'renewal' ] - - name: Скачивание папок archive на ваш ПК + # --- РЕШЕНИЕ ПРОБЛЕМЫ С ПАПКАМИ --- + - name: Поиск всех файлов внутри папок archive для выбранных доменов + ansible.builtin.find: + paths: "/etc/letsencrypt/archive/{{ item }}" + file_type: file + recurse: true + loop: "{{ dynamic_domains | list }}" + register: found_archive_files + + - name: Скачивание файлов archive на ваш ПК ansible.builtin.fetch: - src: "/etc/letsencrypt/archive/{{ item }}/" - dest: "{{ local_tmp_dir }}/archive/{{ item }}/" - flat: false - loop: "{{ dynamic_domains }}" + src: "{{ item.1.path }}" + dest: "{{ local_tmp_dir }}/archive/{{ inventory_hostname }}/{{ item.1.path | relpath('/') }}" + flat: true + loop: "{{ found_archive_files.results | subelements('files') }}" - name: Скачивание конфигураций обновления renewal на ваш ПК ansible.builtin.fetch: src: "/etc/letsencrypt/renewal/{{ item }}.conf" dest: "{{ local_tmp_dir }}/renewal/{{ item }}.conf" flat: true - loop: "{{ dynamic_domains }}" + loop: "{{ dynamic_domains | list }}" - - name: Скачивание папок live на ваш ПК + - name: Скачивание файлов из папок live на ваш ПК ansible.builtin.fetch: src: "/etc/letsencrypt/live/{{ item.0 }}/{{ item.1 }}.pem" dest: "{{ local_tmp_dir }}/live/{{ item.0 }}/{{ item.1 }}.pem" @@ -67,17 +71,17 @@ loop: "{{ dynamic_domains | product(['cert', 'chain', 'fullchain', 'privkey']) | list }}" # ============================================================================== -# ЭТАП 2: Раскатка сертификатов с вашего ПК и ПОЛНАЯ ЗАЧИСТКА ХВОСТОВ +# ЭТАП 2: Раскатка сертификатов СТРОГО на выбранные хосты # ============================================================================== - name: Раскатка SSL-сертификатов с ПК на целевые хосты и зачистка - hosts: mail_servers + hosts: "{{ target_certs if (target_certs | length > 0) else 'all:!storm.bit-it.ru' }}" become: true vars: local_tmp_dir: "/tmp/ansible_certs" source_host_inventory_name: "storm.bit-it.ru" - + ansible_python_interpreter: /usr/bin/python3 tasks: - - name: Основной блок выполнения раскатки + - name: Основной block раскатки block: - name: Сбор информации о запущенных сервисах на целевом хосте ansible.builtin.service_facts: @@ -93,56 +97,55 @@ - name: Копирование содержимого папки archive на целевой сервер ansible.builtin.copy: - src: "{{ local_tmp_dir }}/archive/{{ hostvars[source_host_inventory_name]['inventory_hostname'] }}/etc/letsencrypt/archive/{{ item }}/" - dest: "/etc/letsencrypt/archive/{{ item }}/" + src: "{{ local_tmp_dir }}/archive/{{ source_host_inventory_name }}/etc/letsencrypt/archive/{{ inventory_hostname }}/" + dest: "/etc/letsencrypt/archive/{{ inventory_hostname }}/" owner: root group: root mode: '0600' - loop: "{{ hostvars[source_host_inventory_name]['dynamic_domains'] }}" + when: inventory_hostname in hostvars[source_host_inventory_name]['dynamic_domains'] - name: Копирование конфигураций renewal на целевой сервер ansible.builtin.copy: - src: "{{ local_tmp_dir }}/renewal/{{ item }}.conf" - dest: "/etc/letsencrypt/renewal/{{ item }}.conf" + src: "{{ local_tmp_dir }}/renewal/{{ inventory_hostname }}.conf" + dest: "/etc/letsencrypt/renewal/{{ inventory_hostname }}.conf" owner: root group: root mode: '0644' - loop: "{{ hostvars[source_host_inventory_name]['dynamic_domains'] }}" + when: inventory_hostname in hostvars[source_host_inventory_name]['dynamic_domains'] - name: Создание папок доменов внутри директории live ansible.builtin.file: - path: "/etc/letsencrypt/live/{{ item }}" + path: "/etc/letsencrypt/live/{{ inventory_hostname }}" state: directory owner: root group: root mode: '0700' - loop: "{{ hostvars[source_host_inventory_name]['dynamic_domains'] }}" + when: inventory_hostname in hostvars[source_host_inventory_name]['dynamic_domains'] - name: Нативная сборка относительных символических ссылок в папке live ansible.builtin.file: - src: "../../archive/{{ item.0 }}/{{ item.1 }}1.pem" - dest: "/etc/letsencrypt/live/{{ item.0 }}/{{ item.1 }}.pem" + src: "../../archive/{{ inventory_hostname }}/{{ item }}1.pem" + dest: "/etc/letsencrypt/live/{{ inventory_hostname }}/{{ item }}.pem" state: link force: true - loop: "{{ hostvars[source_host_inventory_name]['dynamic_domains'] | product(['cert', 'chain', 'fullchain', 'privkey']) | list }}" + loop: [ 'cert', 'chain', 'fullchain', 'privkey' ] + when: inventory_hostname in hostvars[source_host_inventory_name]['dynamic_domains'] - name: Автоматический перезапуск активных веб- и почтовых служб ansible.builtin.systemd: name: "{{ item }}" state: restarted - loop: - - dovecot - - nginx - - apache2 - - httpd + loop: [ 'dovecot', 'nginx', 'apache2', 'httpd' ] when: - ansible_facts.services[item + '.service'] is defined - ansible_facts.services[item + '.service'].state == 'running' + - inventory_hostname in hostvars[source_host_inventory_name]['dynamic_domains'] always: - - name: Полное удаление секретных ключей с ПК администратора + - name: МАКСИМАЛЬНАЯ БЕЗОПАСНОСТЬ - Полное удаление секретных ключей с ПК администратора ansible.builtin.file: path: "{{ local_tmp_dir }}" state: absent delegate_to: localhost - run_once: true \ No newline at end of file + become: false + run_once: true