Bollywood HungamaJanhvi Kapoor, Sreeleela and Siddharth Gupta team up for Umesh Bisht’s thriller, first schedule begins in NainitalInquirerTaal Volcano records 17 earthquakes in 24 hoursCNN TürkTaksitli alışverişlerde yeni dönem: Cep telefonlarında 12 taksit sınırı değiştiPunchPolice remove Rivers DPO after station renovation by suspected cultistsDaily MaverickKATLEHONG MASS SHOOTING: Girl, 11, who survived mass shooting still has bullet lodged near her spineRTP DesportoFrancisco Cabral na final de pares do Masters 1.000 de XangaiThe Jerusalem PostIDF blocks roads leading to Gaza border after Nahala settlers attempt to build outpost overnightEgypt IndependentTemperatures drop 3°C as rain reaches CairoMalay MailFahmi: No Malaysian palm oil companies involved in burning activities in IndonesiaColliderApple TV's New Crown Jewel Officially Continues Streaming DominationSouth China Morning PostChina’s AI boom, self-sufficiency push fuel earnings surge for local chip firmsSky TG24Sciopero scuola e blocco autotrasportatori: giornata di mobilitazione da Nord a Sud. LIVE
The Daily Newsstand · Free, Always
Friday, October 16, 2026

Touch ID умеет больше, чем вы думали

Translate

Лично у меня пароль на sudo был отключён, SSH-ключи были незашифрованы, а секреты для переменных окружения хранились открытым текстом в ~/.zshrc, потому что я не хочу целыми днями вводить пароли. Уверен, я не один такой.

При этом компьютер разработчика — довольно уязвимое место. Я постоянно ставлю пакеты непонятно от кого, запускаю чужие программы и скрипты. Достаточно одного неосторожного запуска, и кто-то соберёт все мои SSH-ключи и секреты из переменных окружения, получит права суперпользователя, а я этого даже не замечу.

Давно хотелось как-то защитить секреты, не жертвуя удобством. Оказалось, что Touch ID отлично в этом помогает. Рассказываю как.

1. Интеграция с sudo

Я ни разу не видел пароль на sudo на Linux-сервере, поэтому и у себя на маке сразу же отключил его по привычке. Но это было необязательно: в macOS уже есть всё для настройки sudo с Touch ID из коробки.

Начиная с macOS 14 Sonoma, Apple заботливо положили пример в файл /etc/pam.d/sudo_local.template:

# sudo_local: local config file which survives system update and is included for sudo
# uncomment following line to enable Touch ID for sudo
#auth       sufficient     pam_tid.so

Достаточно просто скопировать его в /etc/pam.d/sudo_local:

sudo cp /etc/pam.d/sudo_local.template /etc/pam.d/sudo_local

И раскомментировать последнюю строку, чтобы получилось так:

# sudo_local: local config file which survives system update and is included for sudo
# uncomment following line to enable Touch ID for sudo
auth       sufficient     pam_tid.so

Теперь sudo будет запрашивать подтверждение через Touch ID. Если Touch ID не распознает отпечаток или вы нажмёте «Отмена», sudo попросит пароль, как раньше.

По умолчанию sudo запоминает авторизацию на 5 минут. Таймаут можно уменьшить или отключить совсем: добавьте Defaults timestamp_timeout=0 через visudo.

Поддержка tmux и screen

Внутри tmux и screen Touch ID не сработает: окно Touch ID может показать только процесс из GUI-сессии пользователя, а сервер tmux работает как демон. Можно это исправить установив PAM-модуль, который переподключает процесс к GUI-сессии пользователя:

brew install pam-reattach

И добавить его в sudo_local перед pam_tid.so. Итоговый sudo_local должен выглядеть так:

auth       optional       /opt/homebrew/lib/pam/pam_reattach.so
auth       sufficient     pam_tid.so

2. Хранение SSH-ключей в Secure Enclave

Второе место, где я не хочу каждый раз вводить пароль, — подключение по SSH. Было бы удобно расшифровывать ключ с помощью Touch ID, но есть решение даже лучше. Уже давно все маки имеют Secure Enclave — аппаратное криптографическое хранилище, в котором можно хранить в том числе и приватные SSH-ключи. Начиная с macOS 26 Tahoe, уже всё готово, чтобы этим пользоваться.

Создаём ключ прямо в Secure Enclave:

sc_auth create-ctk-identity -l user@server -k p-256-ne -t bio

Смотрим список ключей:

sc_auth list-ctk-identities

Появится список в таком виде:

Key Type Public Key Hash                          Prot Label       Common Name Email Address Valid To          Valid
p-256-ne 18F409BAEA5400C276C6551409F9C6111697CA7B bio  user@server user@server               09.09.2027, 22:41 YES

Может смутить столбик «Valid To» и возникнуть вопрос: мой ключ протухнет через год?

Ответ: нет

«Valid To» относится к самоподписанному сертификату X.509, который sc_auth автоматически создаёт и привязывает к CTK-идентичности. Сам приватный ключ остаётся в Secure Enclave. В обсуждении нативной поддержки Secure Enclave в SSH это прямо подтверждают: сертификат используется для TLS, клиентской аутентификации и S/MIME, а SSH его не использует.

Поэтому для SSH срок «Valid To» не важен.

Теперь нужно получить публичный ключ. Это можно сделать двумя способами.

Способ 1. Экспортируем публичный ключ в файл:

cd ~/.ssh
ssh-keygen -w /usr/lib/ssh-keychain.dylib -K -N ""

Когда появится запрос PIN, оставьте его пустым.

В папке появятся два файла:

  • id_ecdsa_sk_rk.pub — публичный ключ, который можно положить в authorized_keys на серверах;

  • id_ecdsa_sk_rk — хоть и выглядит как приватный ключ, на самом деле содержит только данные для обращения к аппаратному ключу: его идентификатор и параметры провайдера. Скопировать этот файл на другую машину и подключиться с ним не получится.

Способ 2. Посмотреть публичный ключ без создания файлов можно, добавив его в SSH-агент.

Удаляем из агента все лишние ключи:

ssh-add -D

Добавляем в агент ключи из Secure Enclave:

ssh-add -K -S /usr/lib/ssh-keychain.dylib

Смотрим публичные ключи в агенте:

ssh-add -L

Настраиваем SSH

Чтобы SSH-клиент начал использовать ключи из Secure Enclave, нужно указать ему провайдер SecurityKeyProvider и файл ключа IdentityFile.

Это можно сделать в файле ~/.ssh/config:

Host *
    SecurityKeyProvider /usr/lib/ssh-keychain.dylib
    IdentityFile ~/.ssh/id_ecdsa_sk_rk

или добавив строку в ~/.zprofile:

export SSH_SK_PROVIDER=/usr/lib/ssh-keychain.dylib

Теперь при подключении по SSH появится запрос Touch ID.

Важно помнить, что ключ из Secure Enclave нельзя скопировать даже для бэкапа. Позаботьтесь о запасном доступе к серверам на случай, если с вашим маком что-то случится.

Подробнее об этом можно почитать здесь.

Сервер должен быть не старее OpenSSH 8.2 (февраль 2020).

Как проверить

Проверить сервер можно так:

ssh -V
ssh -Q key | grep sk-ecdsa

Если вторая команда ничего не вывела, этот OpenSSH не знает такой тип ключей.

Даже на свежем сервере тип ключа может быть отключён в sshd_config через PubkeyAcceptedAlgorithms (в версиях до 8.5 — PubkeyAcceptedKeyTypes). Проверить итоговые настройки sshd можно так:

sudo sshd -T | grep -i pubkeyaccepted

В списке должен быть sk-ecdsa-sha2-nistp256@openssh.com.

Если у вас macOS старше Tahoe, в качестве альтернативы посмотрите на эти проекты:

3. Защита секретов в переменных окружения

У меня много секретов в переменных окружения, и все они прописаны открытым текстом в ~/.zshrc. Это ключи от разных Docker Registry, токены облачных провайдеров, токен GitHub, ключи шифрования Ansible Vault и т. д.

Меня всегда смущало, что любой процесс может прочитать их все, а не только те, которые ему нужны. Но в документации часто предлагают добавить секрет именно в ~/.zshrc.

Хотелось бы удобно выдавать каждому приложению только нужные ему секреты и вообще не хранить их на диске в открытом виде.

Консольная утилита от 1Password использует изящное решение: программа запускается через обёртку, которая подставляет секреты в переменные окружения только запускаемого процесса.

Как это работает?

Создаём файл .env файл который хранит ссылки на секреты:

DATABASE_URL=op://Development/PostgreSQL/connection_string
API_TOKEN=op://Development/MyService/credential

Программу, которой нужны секреты, запускаем не напрямую, а через op run:

op run --env-file=.env -- myapp --my-flags

На диске не хранится ни одного секрета, а программа получает только те, которые ей нужны.

Почему бы не написать такую же обёртку самому? Выглядит просто.

И да, эта идея уже много кому пришла в голову до меня. Я нашёл множество проектов, которые реализуют в точности такое поведение на всех возможных языках, но почему-то все эти проекты непопулярны.

Я попробовал всё, что смог найти, и больше всего мне понравился envrcctl на Python. Его я и буду использовать в качестве примера.

Подставляем секреты через envrcctl exec

Устанавливаем:

brew install rioriost/tap/envrcctl

Добавляем секрет:

envrcctl secret set ANSIBLE_VAULT_PASSWORD --account myproject:ansible_vault

Проверяем:

envrcctl exec -- printenv ANSIBLE_VAULT_PASSWORD

envrcctl запросит Touch ID, достанет секрет из Keychain и передаст его printenv. Если всё хорошо printenv напечатает пароль.

Пример запуска ansible:

envrcctl exec -- ansible-playbook playbooks/basic.yml --diff --check

Загружаем нужные секреты в текущий shell

Если запускать команды через envrcctl exec неудобно, секреты можно экспортировать в shell. Так менее безопасно, потому что все переменные увидит любой процесс, запущенный из этого shell. Но это всё равно лучше, чем хранить пароли в ~/.zshrc.

Сам envrcctl не может добавить переменные окружения в текущий shell: в Unix дочерний процесс не может менять переменные окружения родителя. Зато он умеет печатать их в формате export VAR=VALUE, поэтому envrcctl inject нужно вызвать через eval или source:

eval "$(envrcctl inject --shell)"

или

source <(envrcctl inject --shell)

Чтобы каждый раз не писать такую длинную команду мы можем создать функцию в ~/.zshrc и использовать её:

senv() {
    eval "$(envrcctl inject --shell)"
}

Теперь для экспорта секретов в текущий shell достаточно написать senv и запускать программы как раньше.

Автоматически загружаем секреты при входе в папку

Можно ещё проще!

Есть популярная утилита direnv, которая автоматически загружает переменные окружения в shell при входе в папку с файлом .envrc. envrcctl умеет с ней интегрироваться.

Устанавливаем:

brew install direnv

Добавляем хук в ~/.zshrc:

eval "$(direnv hook zsh)"

Создаём новый .envrc:

envrcctl init --inject

Разрешаем direnv работать в этой папке:

direnv allow

Перезапускаем терминал, чтобы применился хук.

Теперь при переходе в папку сразу появится запрос Touch ID, и в shell добавятся нужные переменные окружения из Keychain.

Заключение

На каждый из трёх способов уходит 5–10 минут. Нужно только то, что уже есть в macOS, и пара утилит из brew. Привычная работа почти не меняется: вместо ввода пароля достаточно коснуться Touch ID.

Что изменилось:

  • sudo больше не срабатывает молча. Любой скрипт или агент, которому понадобились права root, упрётся в запрос Touch ID.

  • Приватный SSH-ключ не украсть, скопировав файл: он никогда не покидает Secure Enclave.

  • В ~/.zshrc больше нет секретов в открытом виде, и каждая программа получает только свои.

Это не защита от всего, но заметный шаг вперёд за минимальную цену. Если вы, как и я, отключали защиту ради удобства, рекомендую попробовать: возможно, отключать её больше не захочется.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.