Pull to refresh
150.67
Солар
Безопасность за нами

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

Reading time7 min
Views4.7K

Однажды моей команде довелось организовывать несложную кустовую схему шифрования для компании, у которой было более 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 Интеграция» компании «Ростелеком-Солар»

Tags:
Hubs:
Total votes 6: ↑6 and ↓0+6
Comments5

Articles

Information

Website
rt-solar.ru
Registered
Founded
2015
Employees
1,001–5,000 employees
Location
Россия