Путешествие по камням, или Как мы скрестили криптошлюзы S‑Terra с Ansible для автоматизации конфигурирования устройств

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Однажды моей команде довелось организовывать несложную кустовую схему шифрования для компании, у которой было более 2,5 тысяч офисов продаж и около ста региональных центров. Всё техническое описание решения легко излагалось в таблице Excel размером 2 800 строк на 25 столбцов, но где было взять столько эникейщиков, которые бы настроили оборудование без ошибок?

Если бы эта история была про оборудование, не поддерживающее автоматизацию ни в каком формате, именно так нам и пришлось бы поступить: развернуть некий стенд и найти десяток студентов для тестирования корректности настроек. Мы же имели дело с криптошлюзами S-Terra, и в нашем случае всё упиралось в знание Ubuntu и автоматизации по протоколу SSH. Автоматизировать нужно было два отдельных момента: загрузку конфигурации Cisco-like и инициализацию устройств. Для этого мы решили использовать систему управления конфигурациями Ansible.

В статье я расскажу, как мы пытались скрестить Ansible с криптошлюзами S-Terra, и что из этого вышло. Надеюсь, наш опыт будет полезным тем, кто возьмётся за подобный проект на базе решения S-Terra и будет искать способ ускорить конфигурирование оборудования и свести на нет человеческий фактор.

Как мы выбирали средство автоматизации

Одним из вариантов, которые мы рассматривали, было написать собственные скрипты на основе инструментов Netmiko или Paramiko с использованием модуля TextFSM. С одной стороны, это могла быть хорошая возможность отработать на практике знания, полученные при прочтении книги Наташи Самойленко «Python для сетевых инженеров». С другой, несколько лет назад я участвовал в подобной активности и помню, как намучился тогда с обработкой вывода, парсингом и подключением по SSH. Так что в итоге мы признали этот вариант решения слишком долгим и сложным, а к тому же и плохо масштабируемым.

Альтернативным вариантом было использовать бесплатное решение Ansible. В его пользу говорило наличие различных модулей под Cisco и Linux, а также огромная база знаний. Удобным было ещё и то, что в этом случае мы могли не вливать полный файл конфигурации, а отслеживать этапы: настройка интерфейсов, маршрутизации, Crypto, мониторинга и так далее. В итоге этот вариант и выбрали.

Поскольку у Ansible не было готовых модулей под продукты S-Terra, мы решили декомпозировать задачу: а именно разбить playbook на play Cisco-like и play Linux.

Как мы автоматизировали загрузку конфигурации

Шаг 1. Формирование конфигурации

Для начала мы попробовали отдельные task для выполнения отдельных конфигураций, а позже play для выполнения конфигураций в оболочке Cisco-like. Когда мы обкатали первую заливку конфигурации, то пришли к выводу, что наиболее удобно будет делать файлы переменных для каждого устройства в hostvars. Конечно, можно было вывести пароли, переменные мониторинга и серверов инфраструктуры в groupvars, но тогда мы потеряли бы гибкость, а заказчику во многом нужны были индивидуальные настройки. В итоге файл переменных для каждой точки стал выглядеть примерно так:

#
user_sudo: 'root'
password_sudo: 'ххххх'
user_cisco: 'cscons'
password_cisco: 'csp'
#========================
user_cisco_new: 'хххххх'
password_cisco_new: 'хххххххх'
UpLinkBase: 'ethX'
UpLink: 'ethX.100'
UpLinkCisco: 'GigabitEthernet0/X.700'
MGMTLink: 'ethX.300'
MGMTLinkCisco: 'GigabitEthernet0/X.701'
DownLink: 'ethY'
DownLink0: 'ethZ'
DownLinkCisco: 'GigabitEthernet0/Y'
DownLinkCiscoZ: 'GigabitEthernet0/Z'
InterfacesCisco:
#
  - name: 'GigabitEthernet0/Z'
    ip: '10.10.10.10'
    mask: 'XXX.XXX.XXX.XXX'
#
  - name: 'GigabitEthernet0/X.700'
    ip: '10.10.10.10'
    mask: 'XXX.XXX.XXX.XXX'
#
  - name: 'GigabitEthernet0/X.701'
    ip: '10.10.10.10'
    mask: 'XXX.XXX.XXX.XXX'
#
InterfacesCiscoMTU:
  - name: 'GigabitEthernet0/Z'
    MTU: '1600'
  - name: 'GigabitEthernet0/X'
    MTU: '1700'
  - name: 'GigabitEthernet0/X.700'
    MTU: '1700'
  - name: 'GigabitEthernet0/X.701'
    MTU: '1700'
#
#SNMP
SNMP_IP: 'XXX.XXX.XXX.XXX'
#Rsyslog
SyslogServerIP: 'XXX.XXX.XXX.XXX'
#NTP
NTP_server: 'XXX.XXX.XXX.XXX'
#
route:
  - prefix: 0.0.0.0
    mask: 0.0.0.0
    next_hop: 'XXX.XXX.XXX.XXX'
  - prefix: ZZZ.ZZZ.ZZZ.ZZZ
    mask: ZZZ.ZZZ.ZZZ.ZZZ
    next_hop: 'XXX.XXX.XXX.XXX'
#
ACLS:
  - name: 'ACL_XXXX_X'
    content:
    - ipsrc: 'XXX.XXX.XXX.XXX'
      wildmasksrc: 'XXX.XXX.XXX.XXX'
      ipdst: 'XXX.XXX.XXX.XXX'
      wildmaskdst: 'XXX.XXX.XXX.XXX'
#
MAPS:
  - number: '1'
    acl: 'ACL_XXXXX_X'
    peer: 'XXX.XXX.XXX.XXX'
#
CryptoInterfaces:
  - GigabitEthernet0/X.700	

Каждая role использовала свою группу переменных (MAPS, ACL, route и т.д.), которая представляла собой отдельный dict и/или list в формате json. Часть переменных, например, Interfaces, использовались на всём протяжении playbook.

Шаг 2. Подготовка конфигурационных файлов

В качестве основного проектного документа мы приняли файл с расширением .xlsx. Для того, чтобы не перебирать каждый раз ячейки таблицы и не тратить на это огромное количество времени, мы разбили скрипты на три части.

Первая часть выгружала нужную информацию из .xlsx в SQL. Это было необходимо для получения выгрузки данных из строк по определенным фильтрам. Про модуль pandas, который помог бы решить эту задачу более простым путём, на момент создания скрипта я не знал.

Вторая часть скриптов проверяла SQL на ошибки: отсутствие пересечений, корректность peer и другие. Всего у нас получилось семь функций проверки. Как говорится, не ошибается тот, кто ничего не делает, и тут это правило работало на 100%.

Третья часть включала в себя основной скрипт формирования конфигурации и скрипт для формирования изменений. Первый представлял собой группу функций, формирующих переменные для print(template.format(var1,….)), которые в свою очередь являются dict и/или list в формате json в конфигурации для Ansible. Второй мы сделали, так как со временем у нас появилась потребность парсинга (textFSM) файлов Cisco-like конфига уже установленных устройств S-Terra и формирования изменений (diff_conf).

Четыре булыжника, о которые мы споткнулись по пути

Вроде всё сделали красиво, но тут нас ждал первый булыжник — уровни вложенности переменных в Ansible. Оказалось, что при использовании модуля cisco.ios.ios_acls сделать перебор переменных аналогично [списку [списков]] не получится. Пролистав N страниц в интернете и протестировав несколько вариантов, мы пришли к использованию конструкции loop + subelements.

- name: acl_config
  cisco.ios.ios_acls:
    config:
    - afi: ipv4
      acls:
      - name: '{{item.0.name}}'
        acl_type: extended
        aces:
        - grant: permit
          protocol:
            ip
          source:
            address: '{{item.1.ipsrc}}'
            wildcard_bits: '{{item.1.wildmasksrc}}'
          destination:
            address: '{{item.1.ipdst}}'
            wildcard_bits: '{{item.1.wildmaskdst}}'
  loop: "{{ACLS|subelements('content')}}"

Я думаю, что боль использования модуля cisco.ios.ios_acls понимает любой сетевой инженер, который с ним работал. На мой взгляд, так неудобно сделать мог только человек, который никогда это не настраивал. Наши ощущения можно сравнить со случаем, когда решение по маршрутизации трафика в организации реализуется не на основе динамической маршрутизации, а на основе запуска файлов с расширением .bat, меняющих def route на host: администратор сделал, а на сетевом инженере сэкономили.

К сожалению, ход с конструкцией loop + subelements не решил проблему с использованием правил для /32 сетей, так как в Cisco-like их надо вводить как host, а как запустить when по внутреннему списку, я так и не придумал. Тогда я впервые вспомнил фразу из одной статьи «Ansible — это не язык программирования, это инструмент автоматизации». Пришлось потом это реализовывать отдельной role.

Второй булыжник был в том, что модули Ansible работали не совсем так, как нам хотелось бы это видеть. Модуль sudo так и не получилось запустить на Linux S-Terra, модули ACL и cisco.ios.ios_config не могли в цикле анализировать конфигурацию, удалять лишнее и дополнять недостающее (описанная выше ситуация с host). Так мы пришли к выводу, что всё нужно тестировать, причём очень внимательно и скрупулёзно.

Третий булыжник ждал нас в ситуации перехода с одной учётки на другую, когда настроили что-то под root в Linux и теперь то же самое надо сделать под cscons в Cisco-like, а для этого нужно поменять переменные внутри одного playbook. Тут, конечно, всё оказалось гораздо проще, спасибо статье, из которой я вообще очень много почерпнул для общего понимания работы системы. После второго прочтения я всё-таки понял, почему playbook, а не play. Где же здесь book? Ведь переменные используются в пределах одного play, и если их нужно переопросить для SSH-сессии, то есть снова забрать значения из vars, то необходимо сделать новый play. На самом деле до сих пор не понимаю, где и как настраиваются параметры SSH-сессии и почему нельзя было сделать в ansible.conf список параметров, аналогичный Netmiko, но это я просто чего-то не понимаю.

Четвертый булыжник был уже на этапе настройки. При заливке S-Terra с большим количеством MAP, задаваемых в используемом нами формате, Ansible лавинообразно начинал потреблять RAM. Как он умудрился 50-килобайтовый текстовый файлик конфига превратить в 1Гбайт RAM, я не знаю. Но это был очень неожиданный сюрприз. Пришлось выделять 8Гбайт памяти. Наверное, это тоже можно было как-то решить, но я не придумал, что именно надо вбить в Google для поиска решения проблемы.

Впрочем, на этом булыжники закончились и началось довольно приятное сосуществование: конфигурации получились понятными и читаемыми, а все названия стандартизованными. Всплывающие ошибки были достаточно читаемы и связаны с ошибками скрипта создания конфигураций. К тому же мы сэкономили кучу времени и нервов при загрузке custom-скриптов SNMP, ведь за этим бы последовало многочисленное копирование файлов, запуск большого количества скриптов, выполнение проверок и конфигурирование cron. В итоге мы подготовили к установке почти три тысячи устройств.

Как мы автоматизировали инициализацию устройств

Когда я слышу слово «инициализация», мне тут же вспоминается любимый лозунг безопасников «Инженер должен … страдать». Потому как на ПАК серии ниже 3 000 нужно руками вбивать случайную последовательность для генерации Гаммы. Поклонники популярного в начале 2000-ых способа обучения слепому набору текста «СОЛО на клавиатуре» были бы в восторге от такого решения.

Что мы сделали: на S-Terra G-7000 создали нужное количество gamma и загрузили их на SCP-сервер. Далее получили лицензии в текстовом формате от вендора S-Terra и написали скрипт на Python для управления криптошлюзами через COM-порт.

Тут мы столкнулись только с одной проблемой — статикой при переключении USB-COM конвертера. Из-за неё у нас появлялись дополнительные символы при вводе пароля учётки Administrator.

Что по итогам

В процессе запуска на объектах мы также сформировали группу plays и roles для сбора данных о состоянии устройств S-Terra, проверки прохождения пакетов по шифрованным каналам, доступности инфраструктуры заказчика, сбора lic параметров и S/N. Такое управление сетью оказалось довольно удобным.

Если изначально за день нам удавалось настроить два-четыре устройства, и при этом было достаточно много ошибок, то по итогам автоматизации мы ускорили настройку конфигурации криптошлюзов S-Terra серий G-100, G-1000 и G-2000 до 30 устройств в день, а серий G-3000 и G-7000 — до 15 устройств в день. В случае с последними основное ограничение было только в распаковывании больших коробок и настройке «Аккорда». 

Инфографика. Скорость настройки криптошлюзов S-Terra
Инфографика. Скорость настройки криптошлюзов S-Terra

Автор: Олег Рябикин, руководитель группы сетевой безопасности «Solar Интеграция» компании «Ростелеком-Солар»

Источник: https://habr.com/ru/company/solarsecurity/blog/655753/


Интересные статьи

Интересные статьи

Прим. перев.: в этом материале, опубликованном прошлой весной в блоге Dropbox, инженеры компании рассказывают о том, какие проблемы были у их монолита, жившего аж с 2007 года, что они предприняли для ...
Банкомат имеет ту форму, которую задаёт производитель. То есть обычно он похож на большой металлический шкаф, потому что так удобнее компоновать блоки. Когда вы не меняетесь из года в...
Источник квадранта — https://www.gartner.com/doc/reprints?id=1-1YZ85K9P&ct=200506&st=sb Данная статья даст ответы на определенные вопросы связанные с WMS-системами: «Что из себ...
Здравствуйте, уважаемые читатели. Из предыдущих четырех публикаций мы поняли, что современные карбюраторы весьма сложные устройства, и нам есть что еще обсудить в их конструкции. Сегод...
В одном из предыдущих постов мы поговорили о том, можно ли считать досмотр девайсов в аэропортах нарушением прав человека. Мнения разделились. Одни выступили за то, что законопослушному гражданин...