
Привет, Habr! Меня зовут Андрей, системный администратор в электрических сетях, со всеми вытекающими — сети, сервера, пользователи, программы. Как и у всех — какие то скрипты на python для сбора инфы с активки, ежедневного бэкапа конфигов, задач «а добавь вот этот IP в ACL на все устройства»
Везде использую свой модуль для работы с файлами конфигурации. Вы скажете OmegaConf Dynaconf, да и PYAML никто не отменял. Не торопитесь. Я попросил AI сравнить и воодушевился — а вдруг мой велосипед будет кому то полезен?
В начале было слово
Знакомство с python началось с книги Натальи Самойленко Python для сетевых инженеров
эксперименты ставил на своей сети, очень скоро осознал что для десятков устройств надо каждый раз готовить словарь device для ConnectHandler(**device), начал создавать такой в YAML файле. Формат этот мне больше всего понравился, принял для себя как «внутренний стандарт»
Это вылилось в создание своего модуля для работы с активкой, в котором в самом начале был класс StartOptions:
class StartOptions: def __init__(self, fi): from os import path import psutil if not path.dirname(fi): p = psutil.Process().exe() path_to_ini = path.abspath(path.join(path.dirname(p), fi)) else: path_to_ini = fi with open(path_to_ini, encoding="utf8") as f: d = yaml.safe_load(f) for key in d.keys(): setattr(self, key, d[key]) myini = StartOptions('cb.yml')
Создаем объект и устанавливаем ему атрибуты из keys() values() нашего конфига.
Погуглить имеющиеся решения на PYPi ума в тот момент и не хватило и хотелось что то свое написать.
пример конфига cb.yml:
language: ru localpath: /opt/mypython/ main_backup_server: ftp_root: /var/ftp/CISCO/ local_root: /var/ftp/CISCO/ name: loganalyzer password: gAAAAABn7NmePUXNP7Yxni9dKi2H_ZqeQmAgv3AmbrNADgY23XrBVKB_rgmohFK321I9fbB_2bCAz5ShTJN3QSMGlwz5jVUNnA==^M user: gAAAAABn7Nme9PyPeK5Tm406au9B5NaN8FtnP33MAYo3DYkOTRnJKw0lBOROaw2iuKhSgDudHWePvWQ74WJi7iELvFglcvcE4g==^M password: gAAAAABn7Nme6Kb4cI-sqsyApPFm2JsqLtp-2Hds7Jov8MY50XBx3s1VKOIXgA3FKjIa_FjpqkbdDsG6bWwzobwhw9SOrSwHOA==^M phone_mac: - 805e - 001a second_backup_server: ftp_root: / name: NOES-RPBSRV password: gAAAAABn7NmeOj75h2NeM8zzuySko3lVgEzEzTHkETALzcMv6s32XusxdRe9xseDFtJh0GPJpuuFEyeMmNq9h5vECRNgJicnsQ==^M user: gAAAAABn7NmeWRGa7UCv29ApgekzhYZdwXoN_PS_VJPjekvA72zzeQrJDv8GjsXKGHVT2_tfqJZHg0TgdoDaPhIvRSp7sJD-9w==^M templpath: /opt/mypython/TEMPLATES/^M user: gAAAAABn7NmekcfGhIjrwJRXL6v0QRm3SAz4dz-GSm16gu7dpBIyw5omo-A1d3-LjaNwPwTN6Vg-1jzW5_0aPeFbwe0p6TZtsQ=
Это реальный конфиг для скрипта бэкапа конфигураций всей активки. И пусть вас не удивляет не только main но и second backup server. Это цена опыта 🙂
Зашифрованные строки появились уже потом. Используя свой модуль написал скрипт который по fh some_ip или fh some_host_name показывает в какой порт какого коммутатора (и путь от меня до него по сети) включен хост и, если это пользовательский АРМ в домене, еще и имя пользователя этого компьютера и имя хоста. Он полезен не только мне, но в конфиге в открытом виде мои учетки на tacacs и в AD,
Можно, конечно, создать ограниченные учетки для поиска (для AD у нас такая есть), но у меня лично один конфиг и для «покажи мне» и для «добавь на 100 500 устройств новый ACL
Поэтому прикрутил cryptography.fernet с созданием, обновлением «секрета» по ключу запуска с сохранением… в тело самой программы. Не понравилось. Стал хранить в отдельном файле. Пару раз менял принцип поиска, где лежит этот файл с секретом.
А потом попросил AI сравнить мой модуль с другими, он показал на какие‑то плюсы и началось — а хочешь добавим парсер/декодер, а хочешь добавим подсказки при наборе вида
ac.main_backup_server language password templpath localpath phone_mac user main_backup_server second_backup_server
а хочешь еще и поддержку JSON? согласился, сам подумывал. Не устоял еще и от .env от TOML отказался, но добавить не проблема.
И вот что поучилось:
Python module astarconf
Безопасный, подключаемый загрузчик конфигураций для YAML, JSON, .env и Python словарей — с шифрованием на уровне полей, поддержкой CLI и гибридным доступом.
Особенности
🔐 Шифрование/дешифрование полей в YAML
🔌 Загрузка из .yaml, .json, .env или dict
✅ Доступ к атрибутам (config.key) и ключам (config[‘key’])
🧰 CLI-интерфейс для рабочих процессов шифрования.
Пример использования:
from astarconf import Astarconf conf = Astarconf("config.yaml") print(conf.database.user) print(conf["database"]["user"])
Ключ для шифрования/дешифрования может лежать в
-
переменной окружения ASTARCONF_SECRET
-
~/.astarconf/secret.key
-
/etc/astarconf/secret.key
-
в файле secret.key в любом каталоге в $PATH доступном пользователю от имени которого запускается скрипт
astarconf.py -g ~/.astarconf/secret.key # генерация секретного ключа astarconf.py -c config.yaml # шифрование полей (по умолчанию - user, passowrd) astarconf.py -c config.yaml token api_key # шифрование конкретных указанных полей astarconf.py -d config.yaml # дешифрование конфига (в тот же файл) astarconf.py -d config.yaml -o output.yaml # дешифрование конфига, запись в output файл astarconf.py -o output.yaml -f # перезапись output если существует
Модуль astarconf имеет несколько интересных особенностей, которые отличают его от omegaconf и dynaconf. Сравнение по ключевым аспектам:
1. Основные возможности:
|
Функционал |
|
|
|
|---|---|---|---|
|
Поддержка форматов |
YAML, JSON, |
YAML, JSON (через OmegaConf) |
YAML, JSON, TOML, |
|
Шифрование данных |
Да (Fernet) |
Нет |
Да (частично, через Vault) |
|
Доступ к данным |
Атрибуты ( |
Атрибуты + индексы + точки ( |
Атрибуты + индексы |
|
Динамическая загрузка |
Нет (можно добавлять новые атрибуты), |
Да (можно обновлять конфиг) |
Да (динамическое перечитывание) |
|
Валидация схемы |
Нет |
Да (через |
Да (через |
|
Переменные окружения |
Через |
Через интерполяцию ( |
Через |
|
Иерархическая конфигурация |
Да (через |
Да (вложенные структуры) |
Да (многоуровневые настройки) |
Плюсы моего модуля (astarconf):
✅ Встроенное шифрование
-
Позволяет шифровать чувствительные данные (например,
user,password) прямо в YAML/JSON. -
omegaconfиdynaconfне имеют встроенного шифрования (вdynaconfесть поддержка HashiCorp Vault, но это внешний сервис).
✅ Гибкий доступ к данным
-
Поддержка как
obj.key, так иobj["key"]. -
В
omegaconfтоже есть оба варианта, но вdynaconfпредпочтительнееobj.key.
✅ Простота использования
-
Ваш модуль легче освоить, так как он фокусируется на базовых задачах (загрузка + шифрование).
-
omegaconfсложнее из-за поддержкиpydanticи интерполяции.
Когда использовать astarconf?
-
Если нужно простое решение с шифрованием (например, для хранения паролей в конфиге).
-
Если не нужна сложная валидация или динамическое обновление.
Когда выбрать omegaconf или dynaconf?
-
Если нужна интеграция с
pydantic→omegaconf. -
Если нужна поддержка Vault или динамическое перечитывание конфига →
dynaconf. -
Если важна интерполяция переменных (например,
${env:DB_HOST}) →omegaconf.
Для моих быстрых задач мне вполне хватает astarconf
Например у меня есть словарь различных команд для разного оборудования, он гораздо больше примера
commands: "mac_addr_tbl_bymac": desc: 'show mac addres table and filter by mac' cisco_ios: 'show mac address-table | in {}' huawei_vrrp8: 'display mac-address | in {}' huawei_ce: 'display mac-address | in {}' eltex: 'show mac address-table | in {}' "mac_addr_tbl_byport": desc: 'show mac addres table on defined port' cisco_ios: 'show mac address-table interface {}' huawei_vrrp8: 'display mac-address {}' huawei_ce: 'display mac-address interface {}' eltex: 'show mac address-table | in {}'
а в конфиге программы fh (findHost) есть атрибут — путь до этого файла
dict_cmd_path: /some...path/commands.yml
а в коде использую например так
(в моем конфиге fh изначально отcутсвует атрибут commands):
import yaml from astar import Astarconf ac = Astarconf('/home/astar/mypython/fh.yml') commands = {} with open(ac.dict_cmd_path) as f: ac.commands = yaml.safe_load(f)['commands'] #и дальше объект представляющий всё наше оборудование myactivka #имеет функцию получения информации с устройства myactivka.getinfo(device, func, *args) # где func - абревиатуры команды из commands.yml типа mac_addr_tbl_byport port = 'Gi0/0/10' #и код не зависит от того что такое device - huawei, cisco, eltex router or switch command = ac.commands[func][dev['device_type']].format(port)
Если вам понравился такой подход к работе с конфигами
исходный код здесь: https://github.com/AstarAiki/astarconf
модуль на PYPi: https://pypi.org/project/astarconf/
установка: pip install astarconf
А больше всего хочется
Ваших отзывов и комментариев. Да, я изобрел велосипед, но по мне так удобный 🙂
И я им пользуюсь!
ссылка на оригинал статьи https://habr.com/ru/articles/903902/
Добавить комментарий