Скорость работы VCP у STM32

Одним из самых распространенных вариантов обмена информации с внешним устройством это последовательный порт. Давно известная технология, куча примеров для любых языков программирования и все ошибки давно уже найдены и описаны. Сейчас обычно используется COM-over-USB, так как переписывать ничего не надо.

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

Для начала сгенерировал в STM32CubeMX пустой проект. В котором есть только USB и он определен как CDC.

Потом прямо в коде приема блока тут же его отправляю его назад. Кусок из usbd_cdc_if.c

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  CDC_Transmit_FS(&Buf[0], *Len);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

И написал маленькую программку на питоне, которая тупо спамит в порт увеличивающимися блоками и замеряет скорость. Можно взять тут https://github.com/kiltum/usb-rs485/blob/master/test/test/test.py

import time
import threading
import serial
# f042
#ser = serial.Serial(port='/dev/cu.usbmodem2058335047481')
# f303
ser = serial.Serial(port='/dev/cu.usbmodem2057385756311')

ser.isOpen()
# For windows
#ser.set_buffer_size(rx_size=262144, tx_size=262144)

bytesReceived = 0
minimalSpeed = 10000000
maximumSpeed = 0
counterStep = 0
blockSize = 1
shallExit = 0


def res():
    global bytesReceived
    global minimalSpeed
    global maximumSpeed
    global counterStep
    global blockSize
    global ser
    global shallExit

    if minimalSpeed > bytesReceived:
        if bytesReceived > 0:
            minimalSpeed = bytesReceived
    if maximumSpeed < bytesReceived:
        maximumSpeed = bytesReceived
    bytesReceived = 0

    counterStep = counterStep + 1
    if counterStep > 60:
        print("BlockSize:", blockSize, "Minimal:", minimalSpeed, "Maximum:", maximumSpeed,
              "Average:", round((minimalSpeed+maximumSpeed)/2048), "kb/s")
        with open("result.csv", "a") as myfile:
            myfile.write(str(blockSize) + "," + str(minimalSpeed) + "," + str(maximumSpeed) + "\n")
        ser.read(ser.inWaiting())
        counterStep = 0
        minimalSpeed = 100000000
        maximumSpeed = 0
        blockSize = blockSize * 2

    if shallExit == 0:
        threading.Timer(1, res).start()


with open("result.csv", "w") as myfile:
    myfile.close()

res()


while 1:
    if blockSize > 65536:
        shallExit = 1
        exit(0)
    s = "A" * blockSize
    b = s.encode()
    ser.write(b)
    bytesReceived = bytesReceived + ser.inWaiting()
    ser.read(ser.inWaiting())

Сильно я не заморачивался, поэтому указать нужный порт придется вам самим прямо в коде. “Человекочитаемые” программа пишет в консоль и попутно генерирует result.csv для импорта в excel или другую подобную программу

Под рукой у меня оказалось только два stm32 с usb: F042 и F303. Оранжевая линия это максимальная скорость, синяя – минимальная. Такие прыжки максимальной скорости вызваны буферизацией у всех участников процесса. Ну по крайней мере я сейчас так думаю.

Результаты довольно показательные. Как найду еще процессоров – попробую повторить. Но пока можно сказать, что не стоит использовать блоки больше 128-256 байт и можно надеяться на скорость не менее 200 килобайт в секунду.

UPDATE1: Добавил график от F779. Суть та же. Видимо, где-то прямо в коде CDC у stm большие проблемы

Windows 11 – альтернативная смена раскладки

Внезапно оказалось, что в Windows 11 (подозреваю, что и в windows 10) поддерживается два варианта смены раскладок. Первый и основной – это Win+Space комбинация. Корявая, но тем не менее.

Но нечаянно тут нажал и оказалось, что “старая” комбинация по умолчанию Alt+Shift тоже работает. Причем без дебильного всплывающего окна.

Что бы сменить на более каноничное (для меня) Ctlr+Shift надо сходить Settings – Time & language – Typing – Advanced keyboard settings – Input language hot keys. Откроется привычное по старым windows окно

Пока не понятно зачем это, но прикольно.

gitlab-runner lookup docker no such host

Жила-была репа в gitlab. Был в ней CI, был в ней и CD. Пользовалась репа шаренными раннерами от gitlab и успешно тратила кучу минут на сборку. Все было хорошо, пока число этих минут не стало расти угрожающими темпами. В общем, надо поднимать свой раннер и не один

Поначалу ничего этакого, все идет по инструкции

docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register

docker run -d --name gitlab-runner --restart always -v /srv/gitlab-runner/config:/etc/gitlab-runner      -v /var/run/docker.sock:/var/run/docker.sock      gitlab/gitlab-runner:latest

Все пошло хорошо, пока не возникла ошибка

error during connect: Post http://docker:2375/v1.40/auth: dial tcp: lookup docker on x.x.x.x:53: no such host

Первым, что выдают рецепты из интернета, так это запустить докер в привелигированном режиме. Другие советы типа “пробрось docker.sock” уже учтены в инструкции гитлаба. Но даже будучи включенными – не помогают. Все равно докер ломится по tcp, полностью игнорируя сокет.

Погуглив еще немного, обнаружил, что если стоит переменная DOCKER_HOST, то все остальное игнорируется. Ок, значит надо сказать unset DOCKER_HOST перед выполнением. И вуаля! Вот пример рабочего config.toml. Значимые изменения от дефолтного я выделил

concurrent = 2
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "gitlab-runner-docker"
  url = "https://gitlab.com/"
  token = "TOKEN"
  executor = "docker"
  pre_build_script = "unset DOCKER_HOST"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "docker:latest"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
    shm_size = 0

Как убрать лишние раскладки в Windows

Для установки Windows я использую International версию isoшки. С одной стороны привык, что все на английском, а с другой стороны если взять русскую, то потом замумукаешься русский выковыривать отовсюду. И с какой-то версии эта “интернациональная” версия по умолчанию ставит все от United Kingdom. В результате получается так

Лечится это двумя способами: либо в региональных настройках добавляем language pack от United Kingdom, в нем добавляем клавиатуры и потом их удаляем. Либо запуском regedt32 и открытием следующей ветки реестра

Computer\HKEY_CURRENT_USER\Keyboard Layout\Preload

Там видно такое

Последовательность записей совпадает с тем, что показывается при переключении языка. В моем случае грохаем последние две и перелогиниваемся. Результат

Знай свой cgroup

Давеча столкнулся с непонятным (для меня до сегодня) поведением cgroup. Изначально описание проблемы было очень информативным “сервер тормозит”.

Захожу я на сервер и вижу картину маслом:

Куча свободной памяти, но сервер сидит в свопе и выбираться оттуда категорически не желает. Я последовательно начал перебирать все известные мне лимиты и ограничения: везде норм, хорошо и ничего не вызывает подозрений.

Так как эта нода кубернетеса, то я посмотрел и на ограничения подов в /sys/fs/cgroup/memory/. Тоже все согласно описанному, везде memory.limit_in_bytes соответствуют нужному.

Затем я скопипастил микроскрипт что бы посмотреть, кто занял своп

SUM=0
OVERALL=0
for DIR in `find /proc/ -maxdepth 1 -type d -regex "^/proc/[0-9]+"`
do
    PID=`echo $DIR | cut -d / -f 3`
    PROGNAME=`ps -p $PID -o comm --no-headers`
    for SWAP in `grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'`
    do
        let SUM=$SUM+$SWAP
    done
    if (( $SUM > 0 )); then
        echo "PID=$PID swapped $SUM KB ($PROGNAME)"
    fi
    let OVERALL=$OVERALL+$SUM
    SUM=0
done
echo "Overall swap used: $OVERALL KB"

Но скрипт выдал совершенно не совпадающие с системными утилитами значение. Согласно его выводу, своп использовался на 6 гигов. А я вижу на скриншоте выше – 12. Проверил выборочно значения из /proc – совпадают с высчитанными …

Ок, проверю вообще работу подсистему памяти. Набросал быстренько микропрограммку на С, которая раз в секунду сжирала гиг памяти. top честно показал сначала исчерпание free, потом окончание свопа. После пришел OOM и убил программку. Всё правильно, всё так и должно быть.

Долго я ломал голову и пробовал разные варианты. Пока в процессе очередного созерцания top внезапно глаз не зацепился за главного пожирателя памяти. Вернее за его показатель VIRT в 32 гига памяти. Так-то я смотрел на %MEM и RES. В общем, появился резонный вопрос “какого?”

Забрезжила идея, что что-то не так с cgroup. Ок, делаю группу с лимитом памяти в 10 гигов, проверяю, что memory.limit_in_bytes стоят, запускаю снова программку-пожиратель памяти … и вуаля! Через 10 секунд сожралось ровно 10 гигов RAM, и начал жраться своп. Вопрос “какого?” стал более актуальным

Начал гуглить. https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt говорит скромно

memory.memsw.usage_in_bytes # show current usage for memory+Swap (See 5.5 for details)

memory.limit_in_bytes # set/show limit of memory usage

memory.memsw.limit_in_bytes # set/show limit of memory+Swap usage

Про memsw я специально добавил. Но на этой машине Ubuntu 20.04 с cgroup V2 и параметра с memsw нет. Нахожу дальнейшим гуглежом https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html

The main argument for a combined memory+swap facility in the original cgroup design was that global or parental pressure would always be able to swap all anonymous memory of a child group, regardless of the child’s own (possibly untrusted) configuration. However, untrusted groups can sabotage swapping by other means – such as referencing its anonymous memory in a tight loop – and an admin can not assume full swappability when overcommitting untrusted jobs.

Особенно понравились слова про саботаж. То есть, докер ограничивал использование только RAM, но не SWAP. Теперь, когда проблема стала понятной, стало понятно, что и надо гуглить.

https://docs.docker.com/engine/install/linux-postinstall/#your-kernel-does-not-support-cgroup-swap-limit-capabilities

Грубо говоря, надо добавить в конфиг grub

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"

Но тут нода “боевая”, надо дать доработать сервису, поэтому просто увеличили лимиты для пода.

Как говорится, все “побежало и поскакало”

PS Про то, что на ноде с k8s не должно быть свопа я в курсе. Как и то, что начиная с версии 1.21 он поддерживается.

Windows 10 ssh key

Как-то задалбывает под WSL2 постоянно вводить пароль к ssh ключам. Рецепт для ubuntu простой:

sudo apt-get install keychain
cat >> .bash_profile
/usr/bin/keychain -q --nogui $HOME/.ssh/id_rsa
source $HOME/.keychain/$HOSTNAME-sh

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

Get-Service -Name ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add ~\.ssh\id_ed25519
ssh-add ~\.ssh\id_rsa

Удаленный доступ в WSL

В прошлом посте я получил доступ до консоли windows через ssh. Это жалкое, душераздирающее зрелище. Но внутри виндовса живет ubuntu. Можно конечно начать заморачиваться с пробросом портов, но проще сделать так:

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\WINDOWS\System32\bash.exe" -PropertyType String -Force

И все, теперь отличить получившееся от нормальной машины можно только по косвенным признакам.

Windows 10 ssh key auth

Потребовалось тут сходить на windows 10 по ssh. Казалось бы, идешь в настройки, приложения, добавляешь “фичу” в виде OpenSSH server и вуаля! А в реальности оказалось фиг там.

Во-первых, почему-то по умолчанию ssh сервер не запущен и не запускается автоматически. Но это лечится запуском консоли powershell и скармливанием туда следующих команд

Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'

После этого надо узнать свой логин для ssh. Это чуть проще – просто открываем окно терминала и смотрим.

C:\Users\multi>

Почему-то логин у меня multi, хотя везде я multik. Куда делась последняя буква – я не знаю.

Следующим шагом я довольно долго пытался сделать авторизацию по ключу. Фигу. Сервер упорно сопротивлялся. Оказалось, что микрософт зачем-то только для администраторов вынес ключи не туда, где им положено быть, а в C:\ProgramData\ssh\administrators_authorized_keys . Повторюсь, только для админов.

Вылечить это можно поправив sshd_config в каталоге выше и закомментировав две последние строки. Ну либо забить и в этот файлик любым способом сложить ключи. После этого надо вернуть эту файлу права (куда они делись – хз). Для этого надо скормить в консоль повершелла следующее

$acl = Get-Acl C:\ProgramData\ssh\administrators_authorized_keys     
$acl.SetAccessRuleProtection($true, $false)     
$administratorsRule = New-Object system.security.accesscontrol.filesystemaccessrule("Administrators","FullControl","Allow")     
$systemRule = New-Object system.security.accesscontrol.filesystemaccessrule("SYSTEM","FullControl","Allow")     
$acl.SetAccessRule($administratorsRule)     
$acl.SetAccessRule($systemRule)     
$acl | Set-Acl

Все. После этого у меня заработал вход на винду по ключам.

FreeIPA login failed unknown reason

Просто записка для памяти. Внезапно (для меня) FreeIPA отказалась пускать к себе в веб-админку. При этом в консоли симптомы следующие:

# ipa ping
ipa: ERROR: did not receive Kerberos credentials

В логах проскакивало

[Fri Oct 30 21:21:02.328320 2020] [auth_gssapi:error] [pid 31560] [client x.x.x.x:43956] NO AUTH DATA Client did not send any authentication headers, referer: https://servername/ipa/ui/

Стало понятно, что проблема в GSS. Включение дебага в gssproxy (/etc/gssproxy/gssproxy.conf) дало следующее:

Oct 30 12:28:14 servername gssproxy[4702]: [CID 13][2020/10/30 09:28:14]: gp_rpc_execute: executing 6 (GSSX_ACQUIRE_CRED) for service "ipa-httpd", euid: 48,socket: (null)
Oct 30 12:28:14 servername gssproxy[4702]: GSSX_ARG_ACQUIRE_CRED( call_ctx: { "" [  ] } input_cred_handle:  add_cred: 0 desired_name:  time_req: 4294967295 desired_mechs: { { 1 2 840 113554 1 2 2 } } cred_usage: BOTH initiator_time_req: 0 acceptor_time_req: 0 )
Oct 30 12:28:14 servername gssproxy[4702]: gssproxy[4703]: (OID: { 1 2 840 113554 1 2 2 }) Unspecified GSS failure.  Minor code may provide more information, Preauthentication failed
Oct 30 12:28:14 servername gssproxy[4702]: GSSX_RES_ACQUIRE_CRED( status: { 851968 { 1 2 840 113554 1 2 2 } 2529638936 "Unspecified GSS failure.  Minor code may provide more information" "Preauthentication failed" [  ] } output_cred_handle:  )

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

kinit
systemctl stop gssproxy.service
ipa-getkeytab -p HTTP/SERVERNAME@REALM -k /var/lib/ipa/gssproxy/http.keytab
Keytab successfully retrieved and stored in: /var/lib/ipa/gssproxy/http.keytab
systemctl start gssproxy.service

Не забудьте заменить SERVERNAME и REALM на свои.

Ну и результат:

# ipa ping
-------------------------------------------
IPA server version 4.6.6. API version 2.231
-------------------------------------------

Копируем firewall из редхатов

Если взять и поставить любую Ubuntu, то по умолчанию в ней отсутствуют какие-либо правила фаирволла. Ну или мне так везет. Между тем, в centos и прочих fedora’х по умолчанию стоит правило “всех выпускаем, никого не впускаем, только ssh”

В принципе, все оказалось довольно просто. Надо вот эти вот строчки скормить из-под root’a.

ufw disable
echo y | ufw reset
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
echo y | ufw enable

Ускоряем повторные соединения в ssh

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

Добавляем следующие строки в .ssh/config

Host *
    ControlMaster auto
    ControlPath ~/.ssh/master-%r@%h:%p.socket
    ControlPersist 30m

Путь может быть любым, но рекомендую выбирать только доступный вам. %r , %h, %p – это пользователь, хост и порт соответственно.

Загоняем маки спать

Попал в стандартную ситуацию: закрываешь вечером ноутбук, а утром он отказывается включаться и требует зарядку. Маки нынче пошли не те … На самом деле в самоизоляции у меня куча терминалов, всяких ремотных десктопов и прочих штук, про которые мак знает и помогает им оставаться на связи.

Решение очень простое:

  1. Спрашиваем у мака, сколько раз и когда он просыпается: pmset -g log|grep due
  2. Увидев, что он просыпается практически каждую минуту, запрещаем ему поддерживать соединения: sudo pmset -b tcpkeepalive 0

Плюс: мак теперь переживает ночь, теряя 1-2% заряда батареи

Минус: теперь после открытия все соединения разорваны и надо с минуту, пока все вернется в привычное русло.

Android init undocumented

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

Казалось бы, ну в чем проблема? Там внутри линукс, он даже вроде задокументирован. Гуглим, находим https://android.googlesource.com/platform/system/core/+/master/init/README.md

Добавлям все необходимое … и не работает.

Пропускаю кучу мучений с офигенной (в больших кавычках) системой логирования и отладки.

Решение: rc-файлы должны иметь права 644 и никак иначе. Другие права? Не будем с ними работать! Секурсная сесурити, понимаешь. И пофиг, что если я получил доступ до /system, то уж такая-то мелочь меня не остановит “от кражи информации”

Возвращаем четкость маку

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

Если кратко, то в Apple победили менеджеры, которым надо “красиво”, а не “правильно”. В этом оплоте графики и накосячили! Хорошо, что вернуть назад все легко.

Settings-General-Снять галочку с Use font smoothing when available

и в Displays перещелкнуть радиокнопку Resolution на Scaled и выбрать пункт левее от Default. В общем, как на скриншотах выше.

Всё. Эффект офигительный: как будто у тебя снова тот самый первый мак с ретиновским дисплеем, где об засечку у букв можно порезаться!

Обновления. Боль и лечение.

“Обновление необходимо произвести в ночь с субботы на воскресение, в период минимальной нагрузки” – эта фраза знакома любому ИТшнику в любой стране. И точно так же им нелюбима. Что делать, что бы начать спать по ночам?

Я предлагаю зайти сначала с конца и понять, что не так с предложением обновить систему в ночь с субботы на воскресенье?

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

Что плохого?

  • Для начала, работа ночью не является самым желаемым временем работы у ИТ подразделения, что бы не говорили об этом мифы, предания и сказания. Мы такие же люди, мы точно так же любим спать.
  • Как ни странно, но повторюсь: ночью большинство людей спят. И если что-то пойдет не так, решение проблемы может застопориться до утра. Просто потому что дежурная смена не может сделать что-то этакое, что потребовалось. Как бы вы не стояли на голове, но часто в 4 утра нельзя сделать то, что после 9 утра делается за 10 минут. В результате время простоя растет, SLA нарушается, мотивация снижается.
  • И наконец, просто стоимость обновления. Ночные работы в воскресенье гораздо дороже тех же самых, но во вторник утром.

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

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

Во-первых, начать в конце-концов применять техники, позволяющие обновляться без остановки основного сервиса. Их много, они описаны очень хорошо и я не буду тут повторяться. Но начальные слова для гугления например CI/CD и canary deployment.

Главная задача: научиться обновляться быстро и однообразно. Поверьте, это больно только в самом начале. При первой попытке обновления “вне графика” вас ждет весь привычный вам набор проблем при обновлении: что-то забыли, где-то не та версия, какое-то место требует ручной работы и так далее. Но стоит руководству (хотя бы на уровне тимлидов) “упереться” и повторять, как каждое новое обновление будет происходить все быстрее и проще. Люди ленивые: одни напишут скрипты, другие немного изменят процесс или вообще добавят новый.

Мой опыт показывает, что переход от “ой, для обновления нам надо Н часов и работа М людей” до “новая версия появляется где надо через 10-15 минут и сама” необходимо примерно полгода. Это без надрывов и резких движений. И да, эти практики применимы к любым системам.

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

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

  • Никаких обновлений продакшн систем с обеда пятницы до утра понедельника
  • Большие релизы планируются на утро вторника
  • Большие релизы перед праздниками недопустимы

Откуда пошли эти правила? Конечно, из опыта.

Почему никаких релизов перед праздниками и выходными? Потому что в 99% случаев такие даты – это просто кто-то из менеджеров где-то на каком-то совещании сказал что-то типа “ну, 1го числа систему переводим на новые рельсы”. А другой менеджер не имеет достаточно смелости сказать “Нафига обновлять систему 1 го мая? Там длинные праздники”. 1 процент я оставил, потому что где-то наверное “круглые” и “ровные” даты оправданы. Но лично я ни разу не встречал такого.

Почему большие обновления лучше всего планировать на утро вторника?

  • Все вопросы и проблемы, которые были в выходные, обычно уже решены в понедельник, либо понятны их последствия. И если что, легко отменить обновление вообще.
  • Люди вошли в рабочий ритм и все известные мне организации считают вторник рабочим днем.
  • Если что-то пойдет не так, у нас есть куча рабочих дней с очень малой вероятностью прерывания по личным делам.
  • И наконец, “опоздуны” и “потеряшки” могут протратить свои выходные из-за своей лени.

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

Но готовьтесь: первоначально будет сопротивление, да еще какое. В основном как раз от тех самых менеджеров, которые пообещали кому-то там, что новая версия будет доступна в пятницу (вечером, ну на крайний случай, в субботу утром). Вы услышите весь спектр высказываний: от “мы же работаем в одной компании на общее дело” до “меня же заругают”. Надо просто упереться и потерпеть.

Но если выдержать первоначальный наплыв, то буквально через 3-4 недели все заметят сильные позитивные изменения. Предидущие три компании показали: резко снижается напряженность в коллективе и число подъемов ночью на починку сломанного. Остальное думаю у всех свое будет.

И самое приятное: вас потом поблагодарят за возвращенные выходные и спокойный сон ночью.

PS Photo by Andrew Neel on Unsplash

CentOS 7 и MariaDB 10

Внезапно потребовалось обновить на старой центоси mariadb до свежих версий. Оказалось довольно просто:

Удаляем старое, добавляет новое, обновляем.

# cat > /etc/yum.repos.d/MariaDB10.repo
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
# systemctl stop mariadb
# yum remove mariadb-server mariadb mariadb-libs
# yum clean all
# yum -y install MariaDB-server MariaDB-client
# systemctl enable mysql
# systemctl start mysql
# mysql_upgrade -p
......
cj64070_base.b_xml_tree                            OK
information_schema
performance_schema
Phase 7/7: Running 'FLUSH PRIVILEGES'
OK

И всё.

PS 10.4 почему-то встает криво, лень разбираться

FreeIPA и Ubuntu 18.04

Попробовал эту связку. Кратко: Ubuntu использовать можно только как клиент. Как сервер – огребете дикую тучу проблем. Просто из-за того, что никто так не делает. А репликация вообще не работает, потому что сломана в потрохах системы.

Но на всякий случай, если очень охота поднять сервер и клиента на убунту

И на сервере и на клиенте

apt-get install rng-tools

cat >> /etc/default/rng-tools
HRNGDEVICE=/dev/urandom

systemctl enable rng-tools
systemctl start rng-tools

на сервере

chmod o+r /var/lib/krb5kdc
chmod o+x /var/lib/krb5kdc
touch /etc/krb5kdc/kadm5.acl

apt install libjs-scriptaculous

cd /usr/share/fonts/truetype
ln -s font-awesome /usr/share/fonts/truetype/fontawesome

и убрать из

# cat /etc/apache2/conf-enabled/ipa.conf|grep DEF
AddOutputFilterByType DEFLATE text/html text/plain text/xml 

Повторюсь, репликацию я так и не смог настроить. Где-то в районе wsgi-dbus они друг друга не любят

Игродельство

Чего-то зачесалось у меня в старые игрушки поиграть. Но быстрый поиск показал, что фиг вам там. Либо надо ставить эмуляторы и искать образы, либо идти и платить непонятно за что с каким качеством (у меня до сих пор в голове свежи воспоминания, как угробили pac-man, mario и boulder dash).

Ну если оно не получается, то почему бы не взять и не написать самому? В тех играх не ни графики, ни звука, ни работ на 100500 мульонов денег. А интерес-то тот же …

В общем, отряхнул я руки и за пол-дня написал первую игру: Пинг-Понг.

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

Брать тут https://github.com/kiltum/games/tree/master/pingpong

Пароли – наше все!

Давным давно, аж 5 лет назад, я уже задавался темой хранения паролей. Тогда я выбрал платный 1Password и до недавнего времени был полностью доволен.

За 5 лет изменилось довольно многое и к примеру тот 1Password уже не купить: нынче всё по подписке, за каждый чих требуют денег. Да и требования к хранению паролей лично у меня изменились. Немного, но значительно.

Во-первых, я больше не хочу верить. Все маркетинговые слова про “улучшенную защиту”, “aes-256”, “PBKDF2” и “SHA256” остаются словами до тех пор, пока не будет доказательств. Нет, в реальности это может быть и так, но проверить нечем.

Во-вторых, я не хочу больше отдавать контроль над моими паролями кому-то еще. Со старой версией 1Password все хорошо: она позволяет хранить пароли в iCloud, Dropbox или любом каталоге по выбору. Нынешняя, как и остальные, предлагают хранить пароли непонятно где и не понятно как защищенными. Специально сейчас прошелся по сайтам 1Password, Dashline, Lastpass, Roboform и прочим, все тот же набор маркетингового буллшита и никаких доказательств. А возможность доступа к паролям из браузера вообще считают за достоинство …

И наконец, я хочу халявы. Не то, что бы денег жалко, но садиться на иглу “платите нам $10 в месяц” не охота

По своей старой привычке “а оно надо?” я посмотрел профиль использования своих данных. Чаще всего мне надо использовать различные ключи к облачным сервисам. Вот эти вот все GCP_PROJECT, AWS_ACCESS_KEY_ID, pem файлы для ssh и так далее. А вот пароли как пароли у меня используются довольно редко. Ну раз, ну два в день. Лицензии и прочие подобные ключи я вообще использую раз в месяц, когда переустанавливаю все в рамках DRP.

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

Довольно специфичные условия, не так ли? Но нет предела совершенству!

Первым делом я пошел смотреть на KeePass. За прошедшие 5 лет он никуда не делся, все такой же монстр с кучей свистелок и перделок. И все так же хочет кучу всего, потому что и может практически все. Можно, не если честно, не вставляет.

Затем поиск вывел меня на довольно новый менеджер паролей Bitwarden. В нем все, как я люблю: у него открытый код и абсолютно прозрачная модель монетизации. За $10 в год можно получить абсолютно все, что необходимо от менеджера паролей в настоящее время. Более того, можно поставить свой собственный сервер и все клиенты будут синхронизироваться с ним, а не с сервером компании.

Попутно обнаружилась совершенно шикарная вещь: у битвардена есть консольный клиент. Выглядит это так (пароли все равно поменял)

[kiltum@mbook ~]$ bw unlock
? Master password: [hidden]
Your vault is now unlocked!

To unlock your vault, set your session key to the `BW_SESSION` environment variable. ex:
$ export BW_SESSION="WgOBidzNy5wybOFgJ8t9MB3gHN2ZQww1ux0ovrbmaA0N21xRS0rrwlBofi8sp6bKe1+HmYaybCgIQnZxGqzkWB=="
> $env:BW_SESSION="WgOBidzNy5wybOFgJ8t9MB3gHN2ZQww1ux0ovrbmaA0N21xRS0rrwlBofi8sp6bKe1+HmYaybCgIQnZxGqzkWB=="

You can also pass the session key to any command with the `--session` option. ex:
$ bw list items --session WgOBidzNy5wybOFgJ8t9MB3gHN2ZQww1ux0ovrbmaA0N21xRS0rrwlBofi8sp6bKe1+HmYaybCgIQnZxGqzkWB==

[kiltum@mbook ~]$ bw list items --session WgOBidzNy5wybOFgJ8t9MB3gHN2ZQww1ux0ovrbmaA0N21xRS0rrwlBofi8sp6bKe1+HmYaybCgIQnZxGqzkWB==
[{"object":"item","id":"de683640-15ca-4dc0-98ec-a95400951086","organizationId":null,"folderId":null,"type":1,"name":"kiltum.livejournal.com","notes":null,"favorite":false,"login":{"uris":[{"match":null,"uri":"https://kiltum.livejournal.com/"}],"username":"kiltum","password":"passwordwasdeleted","totp":null,"passwordRevisionDate":null},"revisionDate":"2018-09-07T09:02:43.6466667Z"},{"object":"item","id":"161cff1e-eeaf-4091-8c0f-a954009ee2ab","organizationId":null,"folderId":null,"type":1,"name":"www.facebook.com","notes":null,"favorite":false,"login":{"uris":[{"match":null,"uri":"https://www.facebook.com/"}],"username":"multik@multik.org","password":"herewaspassword","totp":null,"passwordRevisionDate":null},"revisionDate":"2018-09-07T09:38:29.0466667Z"}]

Как видно, на выход идет обычный json, из которого можно выдрать необходимые поля любым подручным средством.

Но после небольшой дискуссии в #unix.ru мне было предложено посмотреть на Pass. Поначалу я попробовал и весь расплевался. Этот менеджер паролей … ну в общем, он совершенно перпендикулярен всем остальным. В нем все не так и не туда. И вообще он какой-то кривой. Да, кривой и точка!

Но так как больше других менеджеров не находилось, решил оставить и попользоваться всеми тремя менеджерами (1password, bitwarden и pass) одновременно. Создавать новые пароли, ключи и токены, перемещаться между машинами и вообще пытаться вести обычную жизнь DevOps/SRE/SysAdmin/CTO/чебурашки.

Практически сразу выяснилось, что pass это просто развесистый bash скрипт, который в своей работе использует gpg и git. В теории это означает, что pass будет работать на всех платформах где есть эти программы. В реальности я его попробовал только под OS X и Linux

Что в итоге я получил?

Во-первых, мне больше не надо верить. Для шифрования используется gpg из дистрибутива с моим личным ключем. Каждая запись – это зашифрованный gpg файл. При желании можно взять и достать вручную.

$ gpg aws_prod.gpg 
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
gpg: encrypted with 4096-bit RSA key, ID B2698444DC05C50F, created 2017-09-11
      "Viacheslav Kaloshin "

Во-вторых, использование git на своем сервере снимает все вопросы про “кто еще получает доступ до моих данных”. Как и полную историю всех изменений с самого начала. Никаких “30 последних изменений”. Хранится всё.

$ git log|head -5
commit 8ab2f5fae8bf9a8b48dc97df908343c25a1745c1
Author: Viacheslav Kaloshin 
Date:   Mon Sep 24 15:41:37 2018 +0300

    Rename cs/ed_aws_qa to cs/ed/aws_qa.

И наконец, эта опенсорс, халява и возможность поправить и сделать по-своему.

Описывать, как устанавливать pass смысла нет: это и так прекрасно расписано на официальном сайте. Более того, на новых машинах можно просто склонировать репозиторий в ~/.password-store и на этом вся установка будет завершена.

И наконец, то, что мне больше всего понравилось.

Безопасное переключение между окружениями. В данном случае AWS, но этот же механизм работает с GCE, Azure и любым другим софтом, хранящим ключи в переменных окружения.

$ pass show cs/ed/aws_qa
AWS_ACCESS_KEY_ID=BKIAIELZCTWSJ7FECP4Z
...
$ pass show cs/ed/aws_prod 
AWS_ACCESS_KEY_ID=BKIAIN56RKIABTBHJXTW
...
$ export  `pass show cs/ed/aws_qa`
$ set|grep AWS_ACC
AWS_ACCESS_KEY_ID=BKIAIELZCTWSJ7FECP4Z
$ export  `pass show cs/ed/aws_qa`
$ set|grep AWS_ACC
AWS_ACCESS_KEY_ID=BKIAIN56RKIABTBHJXTW

Замена конструкции ssh -i key.pem user@hostname

$ pass show cs/qapem
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAw4AMstljzZRxvqNIO/ZsXnkCMm8O+FXuuTGqzII2ysH5fz8Q3pLZmKVXfz+7
....
eNK7UAHXBLGciXfFjlYlvZaLci93wtY4reWCgmsCmNx98WBMZUmF0R1VCjU/DYleIpMtNBY=
-----END RSA PRIVATE KEY-----
$ pass show cs/qapem| ssh-add -
Identity added: (stdin) ((stdin))
$ ssh user@hostname

В чем главный плюс? На машине ничего не остается в открытом виде. И стоит закрыть сессию, как все доступы магическим образом исчезнут. Никаких больше “оберегайте свой .aws от чужих глаз и прочее”.

В чем главный минус? На каждое изменение надо звать pass git push и не забывать при переходе на другую машину делать pass git pull. Но для любого современного разработчика это совершенно привычные действия, поэтому и минус-то не большой.