Как стать автором
Поиск
Написать публикацию
Обновить

Пишем панельный менеджер для сертификатов на linux shell

Время на прочтение6 мин
Количество просмотров5.2K

Привет Хабр!

Многие разработчики недооценивают shell скрипты, пытаясь сравнивать их с другими скриптовыми языками. Но ведь linux shell - в первую очередь оболочка операционной системы, сделанная системными инженерами для системных инженеров. И если для других языков нужно знать библиотеки, то для shell - огромное количество консольных утилит. А также понимание основных принципов работы архитектуры Линукс заметно повысит ваши навыки работы с shell скриптами.

О сертификатах

С момента популяризации https, работа с сертификатами теперь есть практически в каждом проекте.


Сертификаты, которые любой может сгенерировать сам;

Сертификаты которые выдает местный СА в компании, доверие к которому есть только внутри компании;

Бесплатный публичный let's encrypt,

Платные сертификаты от крупных центров авторизации (Digicert, iDenTrust и др), с дополнительными услугами, типа проверки компании или государственной аккредитацией

Сертификаты для tls/ssl, сертификаты для авторизации, сертификаты для подписи - даже в пределах одного небольшого проекта с десятком микросервисов и несколькими тестовыми окружениями - сертификатов набирается уйма.

При работе с множеством сертификатов, их удобно хранить не отдельными файлами, а складывать в хранилища (keystore). Самые популярные keystore форматы на сегодня - JKS (java keystore, который считается legacy с выходом 9-й джавы) и PKCS12. Последний вышел уже около 20 лет назад, и несмотря на некоторую критику, является одним из самых надежных, открытых и популярных форматов, который в скором будущем должен уже полностью вытеснить JKS.

Я много работал в проектах, где основным языком разработки был java, поэтому при работе с keystore основной инструмент для меня это консольная утилита keytool, которая поставляется с JDK. И для большинства популярных действий у меня конечно есть микро-шпаргалка:

Посмотреть список сертификатов:

keytool -list -v -keystore "файл.jks" -storepass "пароль"|grep -P '(Alias name:|Entry type:|Serial number:|Owner:|Valid from:)'

Скопировать сертификат из одного keystore в другой keystore:

keytool -importkeystore -srckeystore "откуда.jks" -srcstorepass "пароль" -destkeystore "куда.jks" -deststorepass "пароль" -srcalias "имя сертификата" [ -destalias "новое имя" ]

Импортировать сертификат в keystore из PEM файла:

keytool -import -file "откуда.pem" -keystore "куда.jks" -storepass "пароль" -noprompt -alias "имя_сертификата"

Экспортировать сертификат из keystore в файл:

keytool -exportcert -v -alias "alias" -keystore "keystore.jks" -storepass "storepassword" -rfc -file "exportedcert.cer"

Но однажды мне пришлось поработать в проекте, где сертификатов оказалось мягко говоря много. Плюс несколько сотен виртуалок и контейнеров, где все сертификаты обновлялись вручную. Перед тем как подойти к вопросу автоматизации, было необходимо все это разобрать и причесать. Но долгое время руки просто не доходили - с одной стороны были вещи более приоритетные а сертификаты в общем напрягали нечасто. С другой стороны, опыта разгребания такого объема у меня раньше не было, и навскидку казалось, что в лоб задача решается слишком уныло и кропотливо, браться за нее по своей инициативе не хотелось - задача чисто техническая, никакие менеджеры и представители бизнеса такое перед нашей командой не ставили. Но где-то в подсознании желание все это перебрать и привести в порядок крутилось. Изредка я почитывал статьи, просматривал certificate explorer и его аналоги, но все они были под графическую оболочку Windows, а политика безопасности не позволяла ставить в компании неодобренный софт на десктопы.

Возможно, я бы собрался силой воли, помучился бы недельку, сделал бы все стандартными однострочниками+notepad+excel, но тут внезапно у меня случился больничный отпуск, а когда температура меня попустила, а на работу еще можно было не выходить, я случайно вспомнил, что считаю себя спецом по bash.

И пусть я не хватаю лавры автора PIUPIU, но тем не менее встречайте:

Консольный двух-панельный keystore менеджер на Linux shell

Что умеет менеджер вкратце можно наглядно увидеть на скриншотах.

В одно-панельном режиме:

В двух-панельном режиме:

Для поклонников панельных менеджеров (NC, VC, MC, FAR и др), функциональные клавиши и навигация должны быть интуитивно понятны.

Весьма важным плюсом я считаю, что jks_mgr.sh - это просто шелл скрипт, одним файлом размером 20 килобайт (update: уже 30+ кб) (update2: уже 35+ кб).

Никаких обсфукаций, код максимально простой - проверить на отсутствие закладок может в принципе любой джуниор - то есть такой скрипт можно использовать в любом проекте, не нарушая никаких требований по безопасности, требований по лицензионности, лоялен к производительности, установка не нужна - лишь бы на целевой машине был доступен шелл, keytool, sed и grep.

Сперва я написал рабочий вариант на bash, но в какой-то момент подумал и переписал все башизмы в пользу POSIX совместимости. Код стал выглядеть более громоздко, зато скрипт проверенно работает в bash/ksh без проблем.
Если я что-то пропустил - напишите в комментариях, ну или форкайте на здоровье.

Некоторое сожаление: привычка работы с java keytool вынудила меня всю работу с хранилищами выполнять именно через keytool, который должен быть доступен в PATH (а может быть стоило разобраться и сделать все через openssl?).

Что было самое интересное во время разработки

Довольно много времени потратил на подстройка панелей под высоту/ширину экрана.

Так как экран у меня перерисовывается почти с каждым нажатием, то менять ширину экрана (например если сидеть через графический ssh клиент) можно на ходу - после первого же нажатия любой клавиши экран перерисуется и все адаптируется. Пару вечеров ушло на опции отображения/скрытия столбцов - нужно было высчитать и отладить подстройку для одно-панельного и двух-панельного режима, плюс заголовки и текст считается разными формулами. Вот кусочек для определения насколько надо обрезать Alias, если экран слишком узкий и затем пример вывода заголовка:

WindowWidth="$(tput cols)"
if [ -n "$RFILE" ]; then # two-panel
    used=24
    [ -n "$SHOW_TYPE" ] && used=$(( $used+34 ))
    localWidth=$(( ( $WindowWidth - $used ) / 2 - 1 ))
    if [ $localWidth -ne $aliasWidth ]; then
        aliasWidth=$localWidth
        [ $aliasWidth -lt 1 ] && aliasWidth=1
        clear
    fi
..................................
headerWidth=$(( $aliasWidth + 5 ))
[ -n "$SHOW_TYPE" ] && headerWidth=$(( $headerWidth + 17 ))
printf " store: ${blue}%-$(( $headerWidth ))s${rst}" "$LFILE"
printf "| store: ${blue}%-$(( $headerWidth -1 ))s${rst}\n" "$RFILE"

printf " %-10s" "Valid to"
[ -n "$SHOW_TYPE" ] && printf " %-16s" "Storetype"
printf " %-${aliasWidth}s |" "Alias"
printf " %-10s" "Valid to"
[ -n "$SHOW_TYPE" ] && printf " %-16s" "Storetype"
printf " %-${aliasWidth}s\n" "Alias"

Определение нажатия функциональных клавиш

Специальные клавиши представляют собой строку произвольной длины, поэтому просто считать символ или два через read было некорректно. Но после некоторых эксприментов и гугления, я обнаружил что команда read знает что такое миллисекунда. Сейчас процедура выглядит вот так:

# Special keypress could take variable amount of characters
keypress=""
read -rsN1 keytap
while [ -n "$keytap" ]; do
    keypress="${keypress}${keytap}"
    read -sN1 -t 0.01 keytap
done

Теперь можно сравнивать $keypress с комбинациями:
 F1_KEY=$'\e[11~'
 F3_KEY=$'\e[13~'
 F10_KEY=$'\e[21~'
 UP_KEY=$'\e[A'
 DOWN_KEY=$'\e[B'
 TAB_KEY=$'\t'
 DEL_KEY=$'\e[3~'

Я все еще не уверен, что мой вариант будет работать идеально везде - поэтому на всякий случай почти все хоткеи продублированы обычными буквами.

В упрощенном виде я подобную навигацию уже копирую в другие свои велосипеды - в некоторых случаях это гораздо удобнее, чем стандартный select благодаря наглядности и возможности делать хоткеи.

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

Я догадываюсь, что можно заметно ускорить навигацию - производительность в git-bash ужасна - мне быстрее скопировать keystore на ближайшую виртуалку, поковырять там менеджером и скопировать исправленный keystore назад. Но нужно будет переписывать много вычислений, делать независимую пагинацию для каждой панели, а на Linux все работает отлично, поэтому в текущем варианте скрипт меня устраивает и дойдут ли руки до переделки - не уверен.

В конце нужно написать какой-то умный итог и заключение… ну он простой:

Хочешь получить от практики удовольствие - придумай задачу, результат которой будет полезен для тебя.

Хочешь получить от практики двойное удовольствие - придумай задачу, результат которой будет полезен и для тебя и для кого-нибудь еще.

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

P.S. На фоне некоторых проблем с nginx, Wargaming и др., сразу хочу уточнить, что jks_mgr.sh был написан ИСКЛЮЧИТЕЛЬНО в нерабочее время на личном компьютере.

P.P.S. Совсем забыл: https://github.com/sfkulyk/jks-manager

Теги:
Хабы:
Всего голосов 14: ↑14 и ↓0+14
Комментарии5

Публикации

Ближайшие события