Русский
Русский
English
Статистика
Реклама

Keytool

Как влючить шифрование в JetBrains Projector

09.07.2020 14:06:35 | Автор: admin

Projector это способ запускать IntelliJ IDEA на удалённом сервере. Недавно я писал об этом статью, но умолчал о важной для любого параноика вещи шифровании данных на вебсокете.


Генерация и подкладывание ключей довольно муторный кусок работы. Тут придётся познакомиться с особенностями Docker и криптографии в Java. К сожалению, убежать от этого никуда нельзя, потому что это Java, и ребята из JetBrains совершенно не виноваты.


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


Герерация ключей


Вначале нам нужно сгенерировать набор ключей. Для этого нужно установить OpenJDK и использовать инструмент keytool.


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


mkdir ~/keystorecd ~/keystorecurl https://raw.githubusercontent.com/projectile-ide/projectile-keymaker/master/projectile-keymaker --output ./keymakerchmod 755 ./keymaker./projectile-keymaker projector idea true IP 192.168.1.1 mypassword

Впрочем, ничего не мешает сделать это самостоятельно. Главное, чтобы на выходе получились два важных файла: ca.crt и server.jks.


  • ca.crt это наш Certificate Authority, которым подписаны серверные ключи. Нужно будет заставить браузер доверять ему.
  • server.jks это сертификат конкретного сервера с запущенной IDEA.

Восход Солнца вручную


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


Вначале нам нужно сгенерить наш собственный Certificate Authority (CA), который мы дальше подпихнём во все браузеры.


keytool -genkeypair -v \  -alias ca \  -dname "CN=myCA, OU=Development, O=myCA, L=SPB, S=SPB, C=RU" \  -keystore ca.jks \  -keypass:env PW \  -storepass:env PW \  -keyalg RSA \  -keysize 4096 \  -ext KeyUsage:critical="keyCertSign" \  -ext BasicConstraints:critical="ca:true" \  -validity 9999

Небольшое отступление про пароли


Обратите внимание на вот эту строчку: -keypass:env PW. Это означает, что пароль мы вписываем не в консоли (иначе он затеряется в bash history), а берем из переменных окружения.


Можно написать export PW=mypassword и этого достаточно, но тогда он тоже потеряется в bash history. Куда логичней положить его в файл.


Например, вот так можно сгенерить случайный пароль и положить его в файл:


export PW=`pwgen -Bs 10 1`echo $PW > password

А вот так можно высосать его назад в переменную окружения:


export PW=`cat password`

Красиво, правда? Конечно, такой файл всё ещё можно украсть с жесткого диска сервера, но это совсем другая история. На протяжении этой статьи я выпью свои таблеточки и представлю, что хранить пароли в текстовом файле это нормально. Тем более, что нам нужен не файл, а только содержимое переменной окружения PW.


Возвращаемся назад к генерации ключей...


CA мы сгенерили, но в каком-то богомерзком формате JKS, который браузеры не поймут. Чтобы его можно было скормить браузеру, вначале нужно перегнать его в привычный crt:


keytool -export -v \  -alias ca \  -file ca.crt \  -keypass:env PW \  -storepass:env PW \  -keystore ca.jks \  -rfc

Настала пора сгенерировать ключ для нашего сервера (того, который будет показывать Идею):


keytool -genkeypair -v \  -alias server \  -dname "CN=myServer, OU=Development, O=myServer, L=SPB, S=SPB, C=RU" \  -keystore server.jks \  -keypass:env PW \  -storepass:env PW \  -keyalg RSA \  -keysize 2048 \  -validity 385

Сертификат есть, но пока не подписанный и поэтому в браузере работать не станет. Продолжая церемонию, создаём запрос на подпись:


keytool -certreq -v \  -alias server \  -keypass:env PW \  -storepass:env PW \  -keystore server.jks \  -file server.csr

Теперь сертификат сервера можно подписать тем CA, который мы создали в самом начале:


keytool -gencert -v \  -alias ca \  -keypass:env PW \  -storepass:env PW \  -keystore ca.jks \  -infile server.csr \  -outfile server.crt \  -ext KeyUsage:critical="digitalSignature,keyEncipherment" \  -ext EKU="serverAuth" \  -ext SAN="IP:192.168.1.1" \  -rfc

Заметьте, что SAN может быть в двух вариантах: либо "DNS:website.com", если у вас есть зарегистрированное доменное имя. Либо "IP:192.168.1.1", если домена нет. Если нет ни IP, ни домена, то остаётся только забиться в угол и плакать, без этой записи браузер вам не поверит.


Дальше, в обратную сторону, нужно заставить наш JKS доверять самоподписанному CA (иначе следующий шаг сломается):


keytool -import -v \  -alias ca \  -file ca.crt \  -keystore server.jks \  -storetype JKS \  -storepass:env PW << EOFyesEOF

Берем подписанный ранее сертификат и упаковываем внутрь JKS:


keytool -import -v \  -alias server \  -file server.crt \  -keystore server.jks \  -storetype JKS \  -storepass:env PW

Ну и наконец, результат своих мучений можно посмотреть прямо в консоли:


keytool -list -v \  -keystore server.jks \  -storepass:env PW

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


Прописываем файлы конфигурации


Для хранения настроек нужно сделать файл /home/olegchir/keystore/ssl.properties с таким содержимым:


STORE_TYPE=JKSFILE_PATH=/tmp/server.jksSTORE_PASSWORD=mypasswordKEY_PASSWORD=mypassword

Пароль, очевидно, нужно указывать точно такой же, который вы использовали при создании кейстора.


В этой статье я пишу полный путь до моего домашнего каталога (/home/olegchir) чтобы вам не казалось, что я где-то вас обманул и кусок текста пропустил. Критически относитесь к тому, что читаете, и вписывайте свои пути. Ну или можете поменять имя и фамилию на olegchir, хотя мне будет немного неуютно.


Почему /tmp/server.jks, а не /home/olegchir/keystore/server.jks? Потому что мы в таком виде, во временную папку, будем монтировать его внутрь докерного образа. Сейчас всё увидите.


Теперь нам нужно сказать Projector, чтобы он начал использовать эти файлы. Для этого нужно устанавить специальные переменные окружения с негуманоидными названиями в параметрах docker run, а файлы смонтировать внутрь образа.


Идём в скачанный заранее репозиторий, открываем файл run-container.sh и ищем строчку:


docker run --rm -p 8080:8080 -p 8887:8887 -it "$containerName" bash -c "nginx && ./run.sh"

Туда нужно добавить две переменные окружения:


  • ORG_JETBRAINS_PROJECTOR_SERVER_SSL_PROPERTIES_PATH указывает на файл с настройками;
  • ORG_JETBRAINS_PROJECTOR_SERVER_HANDSHAKE_TOKEN задает пароль, который нужно указывать в URL, чтобы успешно подключиться;
  • Оба файла (настройки и кейстор) монтируем в /tmp.

docker run --rm \    -v /home/olegchir/keystore/ssl.properties:/tmp/ssl.properties \    -v /home/olegchir/keystore/server.jks:/tmp/server.jks \    --env ORG_JETBRAINS_PROJECTOR_SERVER_SSL_PROPERTIES_PATH=/tmp/ssl.properties \    --env ORG_JETBRAINS_PROJECTOR_SERVER_HANDSHAKE_TOKEN=mypassword \    -p 8080:8080 -p 8887:8887 -it "$containerName" bash -c "nginx && ./run.sh"

Теперь контейнер можно запускать!


./run-container.sh

При запуске могут быть какие-то ошибки. Желательно прочитать лог и найти строчки типа:


[INFO] :: ProjectorServer :: WebSocket SSL is enabled: /tmp/ssl.properties[INFO] :: ProjectorServer :: Server started

Установка сертификата в браузеры


Скопируйте файл ca.crt на то устройство, откуда собираетесь соединяться. Дальше нужно открыть браузер и установить сертификат.


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


Firefox:


  1. Настройки
  2. Вкладка Privacy & Security
  3. В самом низу настроек кнопка View Certificates
  4. Вкладка Authorities
  5. Кнопка Import...
  6. Ищем сертификат в диалоговом окне выбора файлов
  7. Прощёлкиваем, все доступные галки.
  8. Заканчиваем импорт.


Chrome для Windows:


  1. Настройки
  2. Раздел Privacy and security
  3. Раздел Securty
  4. Кнопка Manage certificates
  5. Вкладка Trusted Root Certification Authorities
  6. Кнопка Import...
  7. Открывается мастер, выбираем файл, соглашаемся импортировать именно в Trusted Root Certification Authorities.
  8. После импорта обязательно закрываем Chrome. На Windows это может оказаться совсем непросто. Когда вы закрыли Chrome, откройте Диспетчер задач и посмотрите, не осталось ли процессов с именем Chrome. Все такие процессы нужно убить кнопкой Delete.
  9. После перезапуска Chrome всё должно работать.


Chrome для Linux:


  1. Настройки
  2. Раздел Privacy and security
  3. Раздел Securty
  4. Кнопка Manage certificates
  5. Вкладка Authorities
  6. Кнопка Import...
  7. Выбираем файл ca.crt,
  8. Прощёлкиваем, все доступные галки.
  9. Заканчиваем импорт.

Chrome и Fully Kiosk Browser для Android:


Установка под Android может быть очень разной. На Huawei MediaPad M5 мне достаточно было щелкнуть пальцем на сертификат в файловом менеджере Solid Explorer и он установился почти как на компьютере.


На других устройствах можно попробовать вот такой путь:


  1. Settings
  2. Security & privacy
  3. More Settings
  4. Encription and credentials
  5. Install from storage
  6. Выбрать ca.crt
  7. Заканчиваем импорт.

Важно понимать, что каждый производитель Android-устройства сам себе хозяин, и пункт "Install from storage" может оказаться в любом месте настроек, и называться любым именем. Придется повозиться.


Подключаемся из браузера


Для локальной машины: https://localhost:8080/projector/?wss&token=mypassword


Для облачного сервера: https://hostname:8080/projector/?wss&host=hostname&port=8887&token=mypassword


Поиск проблем


Если ничего не помогло, попробуйте открыть адрес https://hostname:8887 и посмотрите, что напишет браузер. Вомзожно, там будет кнопка типа "всё равно доверять этому серверу навсегда" или что-то в этом роде. Возможно, там будет говорящее сообщение об ошибке.


Выводы


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


С другой стороны, один раз сделал и живи спокойно.

Подробнее..

Консольный менеджер сертификатов для JKSPCKS12

05.02.2021 14:16:53 | Автор: admin

Привет Хабр!

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

habr-certificatehabr-certificate

Сертификаты, которые любой может сгенерировать сам;
Сертификаты которые выдает местный СА в компании, доверие к которому есть только внутри компании;
Бесплатный публичный let's encrypt
Платный сертификат от крупных центров авторизации с дополнительными услугами, типа проверки компании.

Сертификаты для tls/ssl, сертификаты для авторизации, сертификаты для two-say-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"

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

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

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

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

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

Также используется sed и grep, по поводу последнего - я не очень уверен, насколько POSIX-совместимо grep -P. Но если что, там несложно переписать на sed.

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

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

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

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

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

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

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

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

Автоматическая подстройка панелей под высоту/ширину экрана.

Так как экран у меня перерисовывается почти с каждым нажатием, то менять ширину экрана (например если сидеть через графический ssh клиент) можно в произвольное время - после первого же нажатия любой клавиши экран перерисуется и все адаптируется. Пару вечеров ушло на опции отображения/скрытия столбцов - нужно было высчитать и отладить подстройку для одно-панельного и двух-панельного режима, плюс заголовки и текст считается разными формулами. Вот кусочек для определения насколько надо обрезать Certificate 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"

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

Некоторые специальные keypress могут иметь длину до 4 символов, поэтому просто через read было сделать непросто - он не позволяет вариативно менять длину читаемой строки, но после поиска в гугле и экспериментов c read в bash/dash, это выглядит так:

# Special keypress could take up to 4 charactersread -rsN1 keypressif [ "$keypress" == "$escape_char" ]; then    read -sn1 -t 0.01 k1    read -sn1 -t 0.01 k2    read -sn1 -t 0.01 k3    read -sn1 -t 0.01 k4    keypress=${k1}${k2}${k3}${k4}    unset k1 k2 k3 k4fi

Теперь можно сравнивать $keypress с комбинациями типа '[A' (стрелка вверх), '[B' (стрелка вниз), '[13~' (F3) и так далее. Я не совсем уверен, что мой вариант будет работать везде идеально - поэтому на всякий случай почти все хоткеи продублированы обычными буквами.

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

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

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

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

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

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

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

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

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru