Автоматизация обновления сертификатов Zimbra с помощью GitLab CI

Для корректной работы почтового сервера Zimbra необходим SSL-сертификат, который можно получить с помощью Certbot от Let’s Encrypt. В сети существует множество статей и скриптов автоматизации обновления сертификатов и установки на сервер Zimbra. Однако важно учесть один нюанс: Certbot требует, чтобы сервер на котором выполняется запрос на получение и обновление сертификата, в данном случае сервер Zimbra, был напрямую доступен из интернета по 80 порту. Если в инфраструктуре перед сервером Zimbra располагается проксирующий сервер, попытка обновления сертификата через Certbot завершится ошибкой.

zimbra_infra

Проблему можно решить двумя способами. Первый вариант — временно перенаправить 80 порт на маршрутизаторе с проксирующего сервера на сервер Zimbra во время обновления сертификата. Второй вариант — обновлять сертификат непосредственно на проксирующем сервере и затем передавать его на сервер Zimbra. Именно второй способ и будет использоваться.

Конфигурация

  • Прокси сервер  Nginx;
  • Почтовый сервер  Zimbra 8.8.15_GA в односерверной конфигурации;
  • CI/CD  GitLab Community Edition v17.3.0.
Предполагается, что Gitlab Runner уже установлены на сервера. Инструкция по обновлению сервера GitLab доступна в документации. Также предполагается, что сертификаты на проксирующем сервере обновляются автоматически, например, с помощью задания в crontab.

Создание проекта

  1. Авторизуемся в GitLab и создаём новый проект;
  2. Добавляем GitLab Runners  Settings -> CI/CD -> Runners;
    • Прокси сервер  GitLab Runner в режиме shell с тегом proxy;
    • Почтовый сервер  GitLab Runner в режиме shell с тегом zimbra;
    • GitLab сервер  GitLab Runner в режиме docker с тегом build ;
  3. Создаём в проекте новый файл с именем: .gitlab-ci.ymlи вставляем следующий код:
				
					variables:
    CERT_PROXY_PATH: "/etc/letsencrypt/live/DOMAIN"
    
stages:
    - delivery
    - build
    - deploy

delivery-cert-job:
    stage: delivery
    tags: 
        - proxy
    script:
        - mkdir build
        - sudo cp ${CERT_PROXY_PATH}/cert.pem build/cert.pem
        - sudo cp ${CERT_PROXY_PATH}/privkey.pem build/privkey.pem
        - sudo cp ${CERT_PROXY_PATH}/fullchain.pem build/fullchain.pem
        - sudo chmod -R 777 build
    artifacts:
        paths:
            - build/
        expire_in: 1h

build-cert-job:
    stage: build
    image: curlimages/curl:latest
    tags:
        - build
    script:
        - curl -o AUTH-X3.pem https://letsencrypt.org/certs/letsencryptauthorityx3.pem.txt
        - curl -o ISRG-X1.pem https://letsencrypt.org/certs/isrgrootx1.pem.txt
        - cat AUTH-X3.pem >> build/fullchain.pem
        - cat ISRG-X1.pem >> build/fullchain.pem
    artifacts:
        paths:
            - build/fullchain.pem
        expire_in: 1h

deploy-zimbra-job:
    stage: deploy
    tags:
        - zimbra
    before_script:
        - sudo su - zimbra -c "zmproxyctl stop"
        - sudo su - zimbra -c "zmmailboxdctl stop"
    script:
        - sudo rm -rf /opt/zimbra/ssl/zimbra/commercial
        - sudo mkdir /opt/zimbra/ssl/zimbra/commercial
        - sudo cp build/* /opt/zimbra/ssl/zimbra/commercial/
        - sudo chmod -R 744 /opt/zimbra/ssl/zimbra/commercial
        - sudo chown -R zimbra:zimbra /opt/zimbra/ssl/zimbra/commercial
        - sudo su - zimbra -c "cd /opt/zimbra/ssl/zimbra/commercial && zmcertmgr verifycrt comm privkey.pem cert.pem fullchain.pem"
        - sudo mv /opt/zimbra/ssl/zimbra/commercial/privkey.pem /opt/zimbra/ssl/zimbra/commercial/commercial.key
        - sudo su - zimbra -c "cd /opt/zimbra/ssl/zimbra/commercial && zmcertmgr deploycrt comm cert.pem fullchain.pem"
    after_script:
        - sudo su - zimbra -c "zmcontrol restart"

				
			

Давайте подробнее рассмотрим, что происходит в этом шаге. Мы задаём значение переменной CERT_PROXY_PATH, которое указывает путь к каталогу с сертификатами:

				
					variables:
    CERT_PROXY_PATH: "/etc/letsencrypt/live/DOMAIN"
				
			

Здесь вместо DOMAIN необходимо указать имя каталога, содержащего сертификаты Let’s Encrypt.

Затем определяем этапы в пайплайне CI/CD:

  1. delivery — на этом этапе сертификаты забираются с прокси сервера и через артефакты передаются на следующие этапы;
  2. build — этап сборки, на котором в цепочку сертификатов добавляются корневые сертификаты Let’s Encrypt;
  3. deploy — этап развёртывания, на котором сертификаты устанавливаются на сервер Zimbra.
				
					stages:
    - delivery
    - build
    - deploy


				
			
Сохраняем файл, затем переходим во вкладку Build -> Pipelines и ожидаем завершения выполнения всех задач:
pipelines

Теперь необходимо настроить запуск пайплайна по расписанию.

  1. В проекте Build -> Pipeline schedules -> New schedule;
  2.  Настраиваем расписание:
    • Description — Run update cert;
    • Interval Pattern  00 00 14 * *, означает запускать задание 14 числа каждого месяца в 00 часов 00 минут;
    • Cron timezone  [UTC+3] Moscow;
    •  Select target branch or tag — main;
    • Variables — по-умолчанию;
    • Activated – включено.

Leave a Comment