Проект юного DevOps Глава 2: Настройка центра сертификации и репозитория

от автора

В данной серии статей описан процесс создания первого pet-проекта для начинающего инженера в DevOps:

Глава 1: Введение и подготовка стенда

Глава 2: Настройка центра сертификации и репозитория

Глава 3: Настройка OpenVPN

Глава 4: Настройка мониторинга

Друзья, хочу ответить на комментарии об отсутствии в данной серии статей инструментов DevOps — Terraform, Ansible, Kubernetes, GitLab CI/CD и прочих инструментов. Полностью согласен с тем, что DevOps без вышеупомянутых инструментов существовать не может.

Данная серия статей является отправной точкой в изучении DevOps и уверен, что именно начинающим инженерам данный материал точно будет полезен. Здесь большой акцент сделан на написании скриптов. Цель данного pet-проекта — практическое ознакомление с Linux перед тем как двигаться дальше в DevOps — именно поэтому название «Проект юного DevOps». В планах написание следующей серии статей уже с углублением в DevOps и его инструменты.

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

Настройка центра сертификации (CA)

Easy-RSA — это набор скриптов для упрощения управления сертификатами в инфраструктуре открытых ключей (sudo apt-get update sudo apt-get install -y easy-rsa=3.0.8-1ubuntu1

Заметка

В других версиях Easy-RSA процесс и особенности настройки могут отличаться от описанных в данной статье.

Скопируем рабочую директорию Easy-RSA в домашнюю директорию нового пользователя и изменим права владения:

sudo cp -r /usr/share/easy-rsa /home/nikolay/ sudo chown -R nikolay:nikolay ~/easy-rsa/ sudo chmod -R 700 easy-rsa/

Настроим Easy-RSA, раскомментировав и изменив следующие строки в конфигурационном файле «~/easy-rsa/vars.example»:

sсt_var EASYRSA_REQ_COUNTRY     "RUS" set_var EASYRSA_REQ_PROVINCE    "Moscow" set_var EASYRSA_REQ_CITY        "Moscow City" set_var EASYRSA_REQ_ORG         "Justnikobird" set_var EASYRSA_REQ_EMAIL       "justnikobird@yandex.ru" set_var EASYRSA_REQ_OU          "LLC" set_var EASYRSA_ALGO            ec set_var EASYRSA_DIGEST          "sha512"

Применим конфигурацию и создадим инфраструктуру открытых ключей (Public Key Infrastructure):

cd ~/easy-rsa mv vars.example vars ./easyrsa init-pki
Результат выполнения команды
Note: using Easy-RSA configuration from: /home/nikolay/easy-rsa/vars  init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /home/nikolay/easy-rsa/pki

В результате программа создаст директорию «/home/nikolay/easy-rsa/pki», в которой будут храниться все создаваемые в дальнейшем ключи.

Теперь сгенерируем ключи удостоверяющего центра:

./easyrsa build-ca

Система запросит у нас ввести пароль для приватного ключа ca и имя нового ca:

Note: using Easy-RSA configuration from: /home/nikolay/easy-rsa/vars Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)  Enter New CA Key Passphrase: ******* Re-Enter New CA Key Passphrase: ******* read EC key writing EC key You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Common Name (eg: your user, host, or server name) [Easy-RSA CA]:  CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: /home/nikolay/easy-rsa/pki/ca.crt

В результате программа создаст два фала:

  • /home/nikolay/easy-rsa/pki/ca.crt — открытый ключ;

  • /home/nikolay/easy-rsa/pki/private/ca.key — закрытый ключ.

Открытый ключ можно сводобно передавать на другие vm, а закрытый необходимо хранить в строжайшем секрете.

Подробнее о том, что такое сертификаты и какую роль выполняет CA можно изучить в статье «Разбираем TLS по байтам. Кто такой этот HTTPS?»

Выпуск пары ключ-сертификат

Клиентский сертификат и сертификат сервера — это два различных типа сертификатов, используемых в контексте безопасности сети, особенно в протоколе SSL/TLS для шифрования данных.

Технически создание и подписание клиентского и серверного сертификатов схожи: оба включают открытый ключ, метаданные и подпись центра сертификации. Разница между ними сводится к прикрепленным метаданным и их проверке. Возможно использование клиентских сертификатов в роли серверных и наоборот, если отключены проверки подлинности и ограничений в библиотеке TLS. Сертификат сервера проверяется по DNS-имени в поле SAN, а сертификат клиента содержит проверенные атрибуты пользователя, устанавливаемые центром сертификации, и проверяется сервером на соответствие требованиям аутентификации.

Выпуск пары ключ-сертификат для сервера

Для выпуска и подписания новой пары ключ-сертификат для сервера с доменным именем «example.justnikobird.ru», необходимо выполнить следующие действия:

cd ~/easy-rsa ./easyrsa gen-req example.justnikobird.ru nopass ./easyrsa sign-req server example.justnikobird.ru

В результате мы получим два файла:

  • ~/easy-rsa/pki/issued/example.justnikobird.ru.crt — подписанный сертификат;

  • ~/easy-rsa/pki/private/example.justnikobird.ru.key — приватный ключ.

Выпуск пары ключ-сертификат для клиента

Для выпуска и подписания новой клиентской пары ключ-сертификат, необходимо выполнить следующие действия:

cd ~/easy-rsa ./easyrsa gen-req example nopass ./easyrsa sign-req client example

В результате мы получим два файла:

  • ~/easy-rsa/pki/issued/example.crt — подписанный сертификат

  • ~/easy-rsa/pki/private/example.key — приватный ключ

Центр сертификации успешно настроен, теперь соберем развернутую нами программу в deb-пакет, чтобы в дальнейшем процесс установки занял намного меньше времени.

Сборка deb-пакета Easy-RSA

Весь процесс сборки я описал в статье «Работа с DEB-пакетами».

Здесь я только помечу следующие данные для сборки:

Файлы, которые буем хранить в пакете:

/home/nikolay/easy-rsa
install
easy-rsa/ usr/share

control
Source: easy-rsa-lab Section: unknown Priority: optional Maintainer: Nikolay <justnikobird@yandex.ru> Build-Depends: debhelper-compat (= 13) Standards-Version: 4.6.0 Homepage: https://github.com/OpenVPN/easy-rsa #Vcs-Browser: https://salsa.debian.org/debian/just-easy-rsa #Vcs-Git: https://salsa.debian.org/debian/just-easy-rsa.git Rules-Requires-Root: no  Package: easy-rsa-lab Architecture: all Depends: easy-rsa Recommends: opensc Description: <insert up to 60 chars description>  <insert long description, indented with spaces>

Скриптов нет.

В результате мы собрали пакет «easy-rsa-lab_0.1-1_all.deb».

Далее нам необходимо создать репозиторий, куда мы загрузим наш новый пакет.

Приступим!


Настройка собственного репозитория

Репозитории — это архивы программ. Каждый репозиторий содержит список пакетов, в нём хранящихся, с указанием версий, зависимостей и прочей необходимой информации. В контексте данного лабораторного стенда в настроенном репозитории будут храниться все пакеты, которые мы соберем.

Aptly — это инструмент управления пакетами для Debian-подобных систем, таких как Ubuntu. Он позволяет создавать, обновлять и управлять локальными репозиториями пакетов, облегчая процесс установки и обновления программного обеспечения.

Настройка Aptly

Зайдем на vm «repo» и применим bash-скрипт «vm-start.sh».

Перед работой с Aptly, выполним установку пакета «bzip2»:

sudo apt-get install -y bzip2

Скачаем архив с Aptly версии 1.5.0 с официальной страницы разработчиков на GitHub в домашнюю директорию и распакуем его:

wget -P ~/ https://github.com/aptly-dev/aptly/releases/download/v1.5.0/aptly_1.5.0_linux_amd64.tar.gz tar xvf ~/aptly_1.5.0_linux_amd64.tar.gz
Заметка

В других версиях Aptly процесс и особенности настройки могут отличаться от описанных в данной статье.

Скопируем исполняемый файл программы в директорию «/usr/local/bin»:

sudo cp ~/aptly_1.5.0_linux_amd64/aptly /usr/local/bin/

Создадим конфигурационный файл «/etc/aptly.conf» от имени пользователя «root» и запишем в него следующие строки:

{   "rootDir": "/opt/aptly",   "downloadConcurrency": 4,   "downloadSpeedLimit": 0,   "architectures": ["all"],   "dependencyFollowSuggests": false,   "dependencyFollowRecommends": false,   "dependencyFollowAllVariants": false,   "dependencyFollowSource": false,   "dependencyVerboseResolve": false,   "gpgDisableSign": false,   "gpgDisableVerify": false,   "gpgProvider": "gpg",   "downloadSourcePackages": true,   "skipLegacyPool": true,   "ppaDistributorID": "ubuntu",   "ppaCodename": "",   "FileSystemPublishEndpoints": {     "lab": {       "rootDir": "/var/www/aptly",       "linkMethod": "symlink",       "verifyMethod": "md5"     }   },   "enableMetricsEndpoint": false }
Описание конфигурационного файла

rootDir: Определяет корневой каталог, в котором Aptly будет хранить свои данные.

downloadConcurrency: Задает количество одновременных загрузок при скачивании пакетов.

downloadSpeedLimit: Ограничивает скорость загрузки (в байтах в секунду). Установка в 0 отключает ограничение.

architectures: Определяет архитектуры, которые Aptly будет использовать (в данном случае, «all»).

dependencyFollowSuggests, dependencyFollowRecommends, dependencyFollowAllVariants, dependencyFollowSource: Управляют тем, следует ли Aptly автоматически добавлять пакеты, зависимые от других пакетов, указанных в полях Suggests, Recommends, Variants и Source.

dependencyVerboseResolve: Активирует запись подробных логов при разрешении зависимостей.

gpgDisableSign, gpgDisableVerify: Опции, позволяющие отключить подпись или верификацию GPG.

gpgProvider: Определяет провайдера GPG, который будет использоваться.

downloadSourcePackages: Определяет, следует ли загружать и хранить исходные пакеты.

skipLegacyPool: Пропускает использование старой файловой системы хранения для пула пакетов.

ppaDistributorID, ppaCodename: Информация о распределении (Distributor ID) и кодовом имени (Codename) для использования при работе с PPA (Personal Package Archive).

FileSystemPublishEndpoints: Определяет конечные точки публикации файловой системы для различных репозиториев. В нашем случае есть одна конечная точка с именем «lab», указывающая на «/var/www/aptly».

enableMetricsEndpoint: Включает или отключает метрический конечный пункт для мониторинга.

Создадим репозиторий с названием «lab»:

sudo aptly repo create -comment="lab repo" -component="main" -distribution="focal" lab

Перенесем пакет «easy-rsa-lab_0.1-1_all.deb» в домашнюю директорию vm «repo» и добавим его в репозиторий:

sudo aptly repo add lab ~/easy-rsa-lab_0.1-1_all.deb
Перенос пакета с помощью SCP (Windows)

В терминале машины, с которой выполняется администрирование всех vm, выполним перенос пакета с vm «ca» на vm «repo».

Скачаем пакет с vm «ca»:

scp -P 1870 nikolay@ca:/home/nikolay/deb/easy-rsa-lab_0.1-1_all.deb .

Загрузим пакет в домашнюю директорию vm «repo»:

scp -P 1870 easy-rsa-lab_0.1-1_all.deb nikolay@repo:/home/nikolay/

Для получения абсолютного пути файла из рабочей директории поможет команда «realpath»:

realpath easy-rsa-lab_0.1-1_all.deb

Вывод:

/home/nikolay/deb/easy-rsa-lab_0.1-1_all.deb

В работе нам могут быть полезны следующие команды:

  • Посмотреть список репозиториев:

sudo aptly repo list
  • Посмотреть список опубликованных репозиториев:

sudo aptly publish list
  • Подробная информация о репозитории на примере «lab»:

sudo aptly repo show -with-packages lab
  • Подробная информация о пакете на примере «easy-rsa-lab_0.1-1_all.deb»:

sudo aptly package show easy-rsa-lab_0.1-1_all
  • Удаление репозитория на примере «lab»:

sudo aptly repo drop lab

Снятие репозитория с публикации на примере «lab»:

sudo aptly publish drop focal filesystem:lab:lab 
  • Удаление пакета из репозитория на примере «easy-rsa-lab_0.1-1_all.deb»:

sudo aptly repo remove lab easy-rsa-lab_0.1-1_all

Публикация репозиториев

Для публикации нам потребуется gpg-ключ. Для начала установим набор утилит для генерации случайных чисел в ядре:

sudo apt-get install -y rng-tools

Запустим утилиту:

sudo rngd -r /dev/urandom

Создадим ключ:

sudo gpg --default-new-key-algo rsa4096 --gen-key --keyring pubring

Система запросит ввести имя и email.

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

Ключ создан, его можно увидеть с использованием следующей командой:

sudo gpg --list-keys

Теперь сделаем первую публикацию ранее созданного репозитория «lab»:

sudo aptly publish repo lab filesystem:lab:lab

Появится окно для ввода пароля закрытого gpg-ключа.

Для успешного выполнения команды нужно, чтобы в репозиторий был загружен хотя бы один пакет.

Обновление базы пакетов репозитория

В случае внесения изменений в основную базу пакетов, нам необходимо обновлять настройки публикации репозитория. Это приводит к обновлению метаданных и актуализации пакетов в каталогах «pool»:

sudo aptly publish update focal filesystem:lab:lab

После публикации, в каталоге «/var/www/aptly/lab» мы должны увидеть две директории:

ls /var/www/aptly/lab dists  pool

В директории «dists» хранятся метаданные для опубликованных дистрибутивов.

В директории «pool» хранятся загруженные пакеты (в нашем случае симлинки на файлы в основном каталоге «/opt/aptly»).

Перенесем в домашнюю директорию vm «repo» сертификат открытого ключа CA.

Для удобства работы с нашим репозиторием в дальнейшем, опубликуем открытый gpg-ключ и сертификат открытого ключа CA в директории «/var/www/aptly/lab» — это необходимы для подключения к репозиторию клиентов:

sudo gpg --export --armor | sudo tee /var/www/aptly/lab/labtest.asc > /dev/null sudo cp ~/ca.crt /var/www/aptly/lab/

Мы вернемся к данным файлам, когда будем настраивать подключение к репозиторию.

Настройка Nginx

Теперь нам необходимо предоставить доступ к нашему репозиторию через интернет, для этого нам понадобится Nginx Web Server.

Выполним установку Nginx:

sudo apt-get update sudo apt-get install -y nginx

Перенесем подписанные на CA ключи для vm «repo» в рабочую директорию Nginx:

sudo cp ~/repo.justnikobird.ru.crt /etc/nginx/ sudo cp ~/repo.justnikobird.ru.key /etc/nginx/

Подготовим хэш пароля для нового пользователя — скачаем необходимый пакет с инструментами и сгенерируем пароль «password» для пользователя «admin»:

sudo apt-get install -y apache2-utils htpasswd -nbB -C 10 admin "password"

В результате выполнения команды мы получим следующую строку, которую запишем в конфигурационный файл «/etc/nginx/conf.d/.htpasswd» для аутентификации на сервере.:

admin:$2y$10$iWOlBiff2IDDovW2wy2SauStp7ahuHpOULM2W7yQ6JpNcbDKeBPYS

Выполним настройку Nginx в конфигурационном файле «/etc/nginx/sites-available/default»:

server {         listen 1111 ssl default_server;         server_name repo.justnikobird.ru;         auth_basic              "Restricted Access!";         auth_basic_user_file    /etc/nginx/conf.d/.htpasswd;         ssl_certificate     repo.justnikobird.ru.crt;         ssl_certificate_key repo.justnikobird.ru.key;         ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;         ssl_ciphers         HIGH:!aNULL:!MD5;          root /var/www/aptly;          location / {                 autoindex on;         } }  # nginx prometheus exporter server {         listen 8080;          location /stub_status {                 stub_status;                 allow 127.0.0.1;                 deny all;         } }
Заметка

Настройка Nginx на порту 8080 понадобится для подключения системы мониторинга в дальнейшем.

Перезапустим Nginx и активируем автоматический запуск:

sudo systemctl restart nginx.service sudo systemctl enable nginx.service
Проверка исправности работы сервиса

Проверим статус сервиса Nginx:

sudo systemctl status nginx.service

Если сервис работает исправно, то он должен быть в статусе «active (running)»

● nginx.service - A high performance web server and a reverse proxy server      Loaded: loaded (/lib/systemd/system/nginx.service; disabled; vendor preset: enabled)      Active: active (running) since Tue 2024-01-30 18:37:36 MSK; 2 weeks 0 days ago        Docs: man:nginx(8)    Main PID: 5562 (nginx)       Tasks: 2 (limit: 1013)      Memory: 100.8M         CPU: 32.199s      CGroup: /system.slice/nginx.service              ├─5562 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"              └─5567 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""  Jan 30 18:37:36 2454768-justnikobird.twc1.net systemd[1]: nginx.service: Deactivated successfully. Jan 30 18:37:36 2454768-justnikobird.twc1.net systemd[1]: Stopped A high performance web server and a reverse proxy server. Jan 30 18:37:36 2454768-justnikobird.twc1.net systemd[1]: Starting A high performance web server and a reverse proxy server... Jan 30 18:37:36 2454768-justnikobird.twc1.net systemd[1]: Started A high performance web server and a reverse proxy server.

Если сервис в статусе «failed», то необходимо поверить его логи:

sudo journalctl -u nginx.service

Также необходимо проверить какие порты прослушивает запущенный сервис с помощью инструмента «netstat», который входит в пакет «net-tools»:

sudo apt-get install -y net-tools sudo netstat -lptun

В выводе видно, то сервис Nginx прослушивает порты «8080» и «1111»:

Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      54594/nginx: master tcp        0      0 0.0.0.0:1111            0.0.0.0:*               LISTEN      54594/nginx: master

Теперь необходимо проверить настройки iptables на наличие правил, разрешающих доступ к сервису:

sudo iptables -L -v -n | grep 1111  ...  Chain INPUT (policy DROP 531K packets, 27M bytes)  pkts bytes target     prot opt in     out     source               destination   969 56172 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:1111 /* repo_nginx */  ...  Chain OUTPUT (policy DROP 214 packets, 76866 bytes)  pkts bytes target     prot opt in     out     source               destination  631K 2580M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED

Правила присутствуют, доступ к сервису открыт.

Настройка iptables

sudo iptables -A INPUT -p tcp --dport 1111 -j ACCEPT -m comment --comment repo_nginx

Сохраним конфигурацию iptables с помощью инструмента iptables-persistent:

sudo apt-get install -y iptables-persistent sudo service netfilter-persistent save

Проверка работы репозитория

Проверим исправность работы репозитория, перейдя по ссылке «https://repo.justnikobird.ru:1111»:

Репозиторий успешно настроен.

Как подружить браузер с новой web-страницей?

Чтобы браузер не ругался на наш сертификат, необходимо загрузить файл сертификата с открытым ключом CA в библиотеку «Trusted Root Certificate Authorities» в настройках браузера.

Подключение к Repo

В системе, где планируем подключиться к репозиторию, создадим файл «/etc/apt/sources.list.d/own_repo.list» и запишем в него данные для подключения к repo:

echo "deb https://repo.justnikobird.ru:1111/lab focal main" | sudo tee -a /etc/apt/sources.list.d/own_repo.list > /dev/null

Настроим https аутентификацию в файле «/etc/apt/auth.conf» для пользователя «admin» с паролем «password»:

machine repo.justnikobird.ru:1111 login admin password password

Добавим правило в iptables и сохраним конфигурацию с помощью инструмента iptables-persistent:

sudo iptables -A OUTPUT -p tcp --dport 1111 -j ACCEPT -m comment --comment repo.justnikobird.ru sudo apt-get install -y iptables-persistent sudo service netfilter-persistent save

Импортируем в систему ключ, который опубликовали ранее:

wget --no-check-certificate -P ~/ https://admin:password@repo.justnikobird.ru:1111/lab/labtest.asc  sudo apt-key add ~/labtest.asc

Импортирует в систему сертификат от CA чтобы новый репозиторий считался доверенным:

wget --no-check-certificate -P ~/ https://admin:password@repo.justnikobird.ru:1111/lab/ca.crt sudo cp ~/ca.crt /usr/local/share/ca-certificates/ca.crt sudo update-ca-certificates

Обновим список пакетов:

sudo apt-get update

Проверим наличие пакета «easy-rsa-lab» в подключенном репозитории:

sudo apt search easy-rsa-lab

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

Sorting... Done Full Text Search... Done easy-rsa-lab/focal 0.1-1 all   <insert up to 60 chars description>

Репозиторий успешно подключен к системе!

Bash-скрипт для Repo

Настало время написать bash-скрипт, который сможет выполнить настройку Repo автоматически:

repo.sh

Версия на GitHub

#!/bin/bash  # проверим, запущен ли скрипт от пользователя root if [[ "${UID}" -ne 0 ]]; then   echo "You need to run this script as root!"   exit 1 fi  # функция, которая проверяет наличие пакета в системе и в случае его отсутствия выполняет установку command_check() {   if ! command -v "$1" &>/dev/null; then     echo -e "\n====================\n$2 could not be found!\nInstalling...\n====================\n"     apt-get install -y "$3"     echo -e "\nDONE\n"   fi }  # функция, которая запрашивает путь до файла и проверяет его валидность path_request() {   while true; do     read -r -e -p $'\n'"Please input full valid path to ${1}: " path     if [ -f "$path" ]; then       echo "$path"       break     fi   done } # функция, которая проверяет наличие правила в iptables и в случае отсутствия применяет его iptables_add() {   if ! iptables -C "$@" &>/dev/null; then     iptables -A "$@"   fi }  # установим все необходимые пакеты используя функцию command_check systemctl restart systemd-timesyncd.service apt-get update command_check wget "Wget" wget command_check iptables "Iptables" iptables command_check netfilter-persistent "Netfilter-persistent" iptables-persistent command_check rngd "Rng-tools" rng-tools command_check nginx "Nginx" nginx command_check htpasswd "Htpasswd" apache2-utils command_check basename "Basename" coreutils command_check bzip2 "Bzip2" bzip2  # настроим aptly echo -e "\n====================\nAptly Configuration...\n====================\n"  # проверим на наличие старых файлов aptly (полезно при переустановке) if [ -f /tmp/aptly_1.5.0_linux_amd64.tar.gz ] || [ -d /tmp/aptly_1.5.0_linux_amd64 ]; then   rm -rf /tmp/aptly_1.5.0_linux_amd64* fi  # скачаем исходники aptly с распакуем их if wget -P /tmp/ https://github.com/aptly-dev/aptly/releases/download/v1.5.0/aptly_1.5.0_linux_amd64.tar.gz; then   tar -xvf /tmp/aptly_1.5.0_linux_amd64.tar.gz -C /tmp/   mv -f /tmp/aptly_1.5.0_linux_amd64/aptly /usr/local/bin/ else   exit 1 fi rm -rf /opt/aptly rm -rf /var/www/aptly  # создадим конфигурационный файл aptly echo '{   "rootDir": "/opt/aptly",   "downloadConcurrency": 4,   "downloadSpeedLimit": 0,   "architectures": ["all","amd64"],   "dependencyFollowSuggests": false,   "dependencyFollowRecommends": false,   "dependencyFollowAllVariants": false,   "dependencyFollowSource": false,   "dependencyVerboseResolve": false,   "gpgDisableSign": false,   "gpgDisableVerify": false,   "gpgProvider": "gpg",   "downloadSourcePackages": true,   "skipLegacyPool": true,   "ppaDistributorID": "ubuntu",   "ppaCodename": "",   "FileSystemPublishEndpoints": {     "lab": {       "rootDir": "/var/www/aptly",       "linkMethod": "symlink",       "verifyMethod": "md5"     }   },   "enableMetricsEndpoint": false }' >/etc/aptly.conf  # создадим репозиторий lab if aptly repo create -comment="lab repo" -component="main" -distribution="focal" lab; then   # запросим путь до первого deb-пакета   package_path=$(path_request "first package (architecture is all or amd64)")   # загрузим пакет в новый репозиторий   if ! aptly repo add lab "$package_path"; then     exit 1   fi else   exit 1 fi echo -e "\n====================\nLab Repo Successfully Created\n====================\n"  # сгенерируем gpg-ключи echo -e "\n====================\nGPG Key Generating...\n====================\n" rngd -r /dev/urandom rngd_check=$? if [ $rngd_check -eq 0 ] || [ $rngd_check -eq 10 ]; then   gpg --default-new-key-algo rsa4096 --gen-key --keyring pubring   gen_key_check=$?   if [ $gen_key_check -eq 0 ] || [ $gen_key_check -eq 2 ]; then     gpg --list-keys   fi else   exit 1 fi echo -e "\nDONE\n"  # опубликуем репозиторий aptly publish repo lab filesystem:lab:lab  # экспортируем открытый gpg-ключ на web-страницу репозитория gpg --export --armor | tee /var/www/aptly/lab/labtest.asc >/dev/null  # экспортируем открытый ключ ca на web-страницу репозитория cp "$(path_request "ca certificate")" /var/www/aptly/lab/ca.crt  echo -e "\n====================\nLab Repo Successfully Published\n====================\n"  # настроим nginx echo -e "\n====================\nNginx Configuration...\n====================\n"  # запросим доменное имя репозитория read -r -p $'\n'"repo domain name (example repo.justnikobird.ru): " repo_name  # запросим путь до сертификата с помощью функции path_request и перенес файл в рабочую директорию nginx server_crt=$(path_request certificate) cp "$server_crt" /etc/nginx/ cert_file=$(basename "$server_crt")  # запросим путь до приватного ключа с помощью функции path_request и перенес файл в рабочую директорию nginx server_key=$(path_request key) cp "$server_key" /etc/nginx/ key_file=$(basename "$server_key")  # запросим логин и пароль для нового репозитория read -r -p $'\n\n'"login for ${repo_name}: " repo_login read -r -p "password for ${repo_name}: " -s repo_pass  # сгенерируем хэш пароля htpasswd -nbB -C 10 "$repo_login" "$repo_pass" >>/etc/nginx/conf.d/.htpasswd  # создадим конфигурационный файл nginx echo ' server {         listen 1111 ssl default_server;         server_name '"$repo_name"';         auth_basic              "Restricted Access!";         auth_basic_user_file    /etc/nginx/conf.d/.htpasswd;         ssl_certificate     '"$cert_file"';         ssl_certificate_key '"$key_file"';         ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;         ssl_ciphers         HIGH:!aNULL:!MD5;          root /var/www/aptly;          location / {                 autoindex on;         } }  # nginx prometheus exporter server {         listen 8080;          location /stub_status {                 stub_status;                 allow 127.0.0.1;                 deny all;         } }' >/etc/nginx/sites-available/default echo -e "\nDONE\n"  # настроим iptables echo -e "\n====================\nIptables configuration\n====================\n" iptables_add INPUT -p tcp --dport 1111 -j ACCEPT -m comment --comment repo_nginx echo -e "\n====================\nSaving iptables config...\n====================\n" service netfilter-persistent save echo -e "\nDONE\n"  # перезагрузим nginx-сервис systemctl restart nginx.service systemctl enable nginx.service  echo -e "\n====================\nRepo listening on port 1111\n====================\n" echo -e "\nOK\n" exit 0

Обновление bash-скрипта для vm

После успешной настройки Repo, добавим в скрипт первичной настройки vm процесс подключения к новому Repo и правило в iptables:

vm-start.sh

Версия на GitHub

#!/bin/bash  # активируем опцию, которая прерывает выполнение скрипта, если любая команда завершается с ненулевым статусом set -e  # проверим, запущен ли скрипт от пользователя root if [[ "${UID}" -ne 0 ]]; then   echo -e "You need to run this script as root!\nPlease apply 'sudo su root' and add your host-key to /root/.ssh/authorized_keys before run this script!"   exit 1 fi  # проверим, загружены ли открытые ssh-ключи у пользователя root if [ ! -f /root/.ssh/authorized_keys ]; then   echo -e "\n====================\nFile /root/.ssh/authorized_keys not found!\n====================\n"   exit 1 else   if [ ! -s /root/.ssh/authorized_keys ]; then     echo -e "\n====================\nFile /root/.ssh/authorized_keys is empty!\n====================\n"     exit 1   fi fi  # функция, которая проверяет наличие пакета в системе и в случае его отсутствия выполняет установку command_check() {   if ! command -v "$1" &>/dev/null; then     echo -e "\n====================\n$2 could not be found!\nInstalling...\n====================\n"     apt-get install -y "$3"     echo -e "\nDONE\n"   fi }  # функция, которая запрашивает имя нового пользователя и проверяет его на наличие в системе username_request() {   while true; do     read -r -p $'\n'"new username: " username     if id "$username" >/dev/null 2>&1; then       echo -e "\nUser $username exists!\n"     else       break     fi   done }  # функция, которая проверяет наличие правила в iptables и в случае отсутствия применяет его iptables_add() {   if ! iptables -C "$@" &>/dev/null; then     iptables -A "$@"   fi }  # функция, которая выполняет backup файла путем копирования его и модификации названия bkp() {   if [ -f "$1" ]; then     cp "$1" "$1".bkp   fi }  # функция, которая восстанавливает файл из backup restore_bkp() {   if [ -f "$1".bkp ]; then     if [ -f "$1" ]; then       rm "$1" && mv "$1".bkp "$1"     else       mv "$1".bkp "$1"     fi   else     echo -e "\nCan't find backup file!\n"   fi }  # настроим часовой пояс echo -e "\n====================\nSetting timezone\n====================" timedatectl set-timezone Europe/Moscow systemctl restart systemd-timesyncd.service timedatectl echo -e "\nDONE\n"  # установим все необходимые пакеты используя функцию command_check apt-get update command_check wget "Wget" wget command_check iptables "Iptables" iptables command_check netfilter-persistent "Netfilter-persistent" iptables-persistent command_check openssl "Openssl" openssl command_check update-ca-certificates "Ca-certificates" ca-certificates command_check tee "Tee" coreutils  # проверим наличие конфигурационного файла ssh if [ ! -f /etc/ssh/sshd_config ]; then   echo -e "\n====================\nFile /etc/ssh/sshd_config not found!\n====================\n"   exit 1 fi  # проверим наличие конфигурационного файла grub if [ ! -f /etc/default/grub ]; then   echo -e "\n====================\nFile /etc/default/grub not found!\n====================\n"   exit 1 fi  # создадим нового пользователя echo -e "\n====================\nNew user config\n===================="  while true; do   read -r -n 1 -p "Continue or Skip? (c|s) " cs   case $cs in   [Cc]*)     # запросим имя пользователя используя функцию username_request (функция создаст глобальную переменную "username")     username_request      # запросим пароль для нового пользователя     read -r -p "new password: " -s password      # создадим нового пользователя и перенесем ssh-ключи     useradd -p "$(openssl passwd -1 "$password")" "$username" -s /bin/bash -m -G sudo     cp -r /root/.ssh/ /home/"$username"/ && chown -R "$username":"$username" /home/"$username"/.ssh/     echo -e "\n\nDONE\n"      # выполним корректировку prompt statement     echo -e "\n====================\nEdit prompt statement for this user?\n===================="      while true; do       read -r -n 1 -p "Continue or Skip? (c|s) " cs       case $cs in       [Cc]*)         # запросим имя vm         read -r -p $'\n'"vm name: " vm_name          # выполним корректировку prompt statement         echo "PS1='\${debian_chroot:+(\$debian_chroot)}\\u@$vm_name:\\w\\\$ '" >>/home/"$username"/.bashrc          echo -e "\n\nDONE\n"         break         ;;       [Ss]*)         echo -e "\n"         break         ;;       *) echo -e "\nPlease answer C or S!\n" ;;       esac     done      break     ;;   [Ss]*)     echo -e "\n"     break     ;;   *) echo -e "\nPlease answer C or S!\n" ;;   esac done  # настроим ssh echo -e "\n====================\nEdit sshd_config file\n===================="  while true; do   read -r -n 1 -p "Continue or Skip? (c|s) " cs   case $cs in   [Cc]*)     sed -i 's/#\?\(Port\s*\).*$/\1 1870/' /etc/ssh/sshd_config     sed -i 's/#\?\(PermitRootLogin\s*\).*$/\1 no/' /etc/ssh/sshd_config     sed -i 's/#\?\(PubkeyAuthentication\s*\).*$/\1 yes/' /etc/ssh/sshd_config     sed -i 's/#\?\(PermitEmptyPasswords\s*\).*$/\1 no/' /etc/ssh/sshd_config     sed -i 's/#\?\(PasswordAuthentication\s*\).*$/\1 no/' /etc/ssh/sshd_config     echo -e "\n\n"     /etc/init.d/ssh restart     echo -e "\nDONE\n"     break     ;;    [Ss]*)     echo -e "\n"     break     ;;   *) echo -e "\nPlease answer C or S!\n" ;;   esac done  # выключим ipv6 echo -e "\n====================\nDisabling ipv6\n===================="  while true; do   read -r -n 1 -p "Continue or Skip? (c|s) " cs   case $cs in   [Cc]*)     echo -e "\n\n"     sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="/&ipv6.disable=1 /' /etc/default/grub     sed -i 's/^GRUB_CMDLINE_LINUX="/&ipv6.disable=1 /' /etc/default/grub     update-grub     echo -e "\nDONE\n"     break     ;;    [Ss]*)     echo -e "\n"     break     ;;   *) echo -e "\nPlease answer C or S!\n" ;;   esac done  # подключим репозиторий echo -e "\n====================\nRepo config\n===================="  while true; do   read -r -n 1 -p "Continue or Skip? (c|s) " cs   echo -e "\n"   case $cs in   [Cc]*)     # выполним backup файлов с помощью функции bkp     bkp /etc/apt/sources.list.d/own_repo.list     bkp /etc/apt/auth.conf      # запросим логин и пароль для подключения к репозиторию     read -r -p $'\n\n'"login for repo.justnikobird.ru: " repo_login     read -r -p "password for repo.justnikobird.ru: " -s repo_pass      # проверим файл /etc/apt/sources.list.d/own_repo.list на наличие записи о репозитории, и в случае ее отсутствия добавим     if ! grep -Fxq "deb https://repo.justnikobird.ru:1111/lab focal main" /etc/apt/sources.list.d/own_repo.list &>/dev/null; then       echo "deb https://repo.justnikobird.ru:1111/lab focal main" | tee -a /etc/apt/sources.list.d/own_repo.list >/dev/null     fi      # проверим файл /etc/apt/auth.conf на наличие записей о репозитории, и в случае их отсутствия добавим     if ! grep -Fxq "machine repo.justnikobird.ru:1111" /etc/apt/auth.conf &>/dev/null; then       echo -e "machine repo.justnikobird.ru:1111\nlogin $repo_login\npassword $repo_pass" | tee -a /etc/apt/auth.conf >/dev/null     else       # если в файле /etc/apt/auth.conf записи обнаружены, то попросим пользователя удалить их       echo -e "\n\nrepo.justnikobird.ru has been configured in /etc/apt/auth.conf!\nPlease manually clean configuration or skip this stage."       restore_bkp /etc/apt/sources.list.d/own_repo.list       restore_bkp /etc/apt/auth.conf       exit 1     fi      # скачаем и установим gpg-ключ от репозитория     if ! wget --no-check-certificate -P ~/ https://"$repo_login":"$repo_pass"@repo.justnikobird.ru:1111/lab/labtest.asc; then       restore_bkp /etc/apt/sources.list.d/own_repo.list       restore_bkp /etc/apt/auth.conf       exit 1     else       apt-key add ~/labtest.asc     fi      # скачаем и установим открытый ключ ca-сертификата от репозитория     if ! wget --no-check-certificate -P /usr/local/share/ca-certificates/ https://"$repo_login":"$repo_pass"@repo.justnikobird.ru:1111/lab/ca.crt; then       restore_bkp /etc/apt/sources.list.d/own_repo.list       restore_bkp /etc/apt/auth.conf       exit 1     else       update-ca-certificates     fi      # выполним синхронизацию списков пакетов в системе     if ! apt update; then       restore_bkp /etc/apt/sources.list.d/own_repo.list       restore_bkp /etc/apt/auth.conf       exit 1     fi     echo -e "\nDONE\n"     break     ;;    [Ss]*)     echo -e "\n"     break     ;;   *) echo -e "\nPlease answer C or S!\n" ;;   esac done  # настроим iptables echo -e "\n====================\nIptables config\n====================" while true; do   read -r -n 1 -p "Current ssh session may drop! To continue you have to relogin to this host via 1870 ssh-port and run this script again. Are you ready? (y|n) " yn   case $yn in   [Yy]*) #---DNS---     iptables_add OUTPUT -p tcp --dport 53 -j ACCEPT -m comment --comment dns     iptables_add OUTPUT -p udp --dport 53 -j ACCEPT -m comment --comment dns     #---NTP---     iptables_add OUTPUT -p udp --dport 123 -j ACCEPT -m comment --comment ntp     #---REPO---     iptables_add OUTPUT -p tcp --dport 1111 -j ACCEPT -m comment --comment repo.justnikobird.ru     #---ICMP---     iptables_add OUTPUT -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT     iptables_add INPUT -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT     #---loopback---     iptables_add OUTPUT -o lo -j ACCEPT     iptables_add INPUT -i lo -j ACCEPT     #---Input-SSH---     iptables_add INPUT -p tcp --dport 1870 -j ACCEPT -m comment --comment ssh     #---Output-HTTP---     iptables_add OUTPUT -p tcp -m multiport --dports 443,80 -j ACCEPT     #---ESTABLISHED---     iptables_add INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT     iptables_add OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT     #---INVALID---     iptables_add OUTPUT -m state --state INVALID -j DROP     iptables_add INPUT -m state --state INVALID -j DROP     #---Defaul-Drop---     iptables -P OUTPUT DROP     iptables -P INPUT DROP     iptables -P FORWARD DROP     # save iptables config     echo -e "\n====================\nSaving iptables config\n====================\n"     service netfilter-persistent save     echo -e "DONE\n"     break     ;;   [Nn]*)     echo -e "\n"     exit     ;;   *) echo -e "\nPlease answer Y or N!\n" ;;   esac done  echo -e "\nOK\n" exit 0

Bash-скрипт для Easy-RSA

Настало время написать bash-скрипт, который сможет выполнить настройку Easy-RSA автоматически:

easy-rsa.sh

Версия на GitHub

#!/bin/bash  # активируем опцию, которая прерывает выполнение скрипта, если любая команда завершается с ненулевым статусом set -e  # проверим, запущен ли скрипт от пользователя root if [[ "${UID}" -ne 0 ]]; then   echo "You need to run this script as root!"   exit 1 fi  # проверим подключен ли репозиторий if [[ ! $(grep -rhE ^deb /etc/apt/sources.list*) == *"deb https://repo.justnikobird.ru:1111/lab focal main"* ]]; then   echo -e "Lab repo not connected!\nPlease run vm_start.sh script!\n"   exit 1 fi  # запросим путь будущего расположения рабочей директории easy-rsa while true; do   read -r -e -p $'\n'"Path for easy-rsa location (format: /home/nikolay): " dest_dir   if [[ "$dest_dir" == */ ]]; then     echo -e "\nWrong path format!\n"   else     if [ ! -d "$dest_dir" ]; then       echo -e "\nDirectory $dest_dir doesn't exist!\n"     else       break     fi   fi done  # проверим установлена ли программа Easy-RSA if [ ! -d /usr/share/easy-rsa/ ]; then   echo -e "\n====================\nEasy-rsa could not be found\nInstalling...\n====================\n"   systemctl restart systemd-timesyncd.service   apt-get update   apt-get install -y easy-rsa-lab   echo -e "\nDONE\n" else   while true; do     read -r -n 1 -p $'\n'"Are you ready to reinstall easy-rsa? (y|n) " yn     case $yn in     [Yy]*)       apt-get purge -y easy-rsa       apt-get install -y easy-rsa-lab       echo -e "\nDONE\n"       break       ;;     [Nn]*) exit ;;     *) echo -e "\nPlease answer Y or N!\n" ;;     esac   done fi  # запросим username у администратора Easy-RSA и скопируем рабочую директорию Easy-RSA в рабочую директорию введенного пользователя while true; do   read -r -p $'\n'"Easy-rsa owner username: " username   if id "$username" >/dev/null 2>&1; then     cp -r /usr/share/easy-rsa "$dest_dir"/easy-rsa     chmod -R 700 "$dest_dir"/easy-rsa/     chown -R "$username":"$username" "$dest_dir"/easy-rsa/     break   else     echo -e "\nUser $username doesn't exists!\n"   fi done  # создадим пару CA-ключей while true; do   read -r -n 1 -p $'\n'"Are you ready to create pair of CA keys? (y|n) " yn   case $yn in   [Yy]*)     cd "$dest_dir"/easy-rsa     sudo -u "$username" ./easyrsa build-ca     echo -e "\nDONE\n"     break     ;;   [Nn]*) exit ;;   *) echo -e "\nPlease answer Y or N!\n" ;;   esac done  echo -e "\nOK\n" exit 0

Также если вам интересна работа с генераторами трафика, то предлагаю ознакомиться с моей статьей «Cisco TRex на практике».


ссылка на оригинал статьи https://habr.com/ru/articles/789056/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *