W redakcji. Artykuł jest wersją roboczą, nie jest jeszcze wersją finalną i może ulec zmianie.
Zanim zaczniesz: ważne
- Osiem błędnych PIN-ów z rzędu kończy się utratą kluczy FIDO na tym YubiKey. Po trzech błędnych próbach z rzędu YubiKey trzeba wyjąć i włożyć ponownie, żeby próbować dalej. Po ośmiu aplikacja FIDO2 blokuje się i logowanie przestaje działać. Odblokować ją może tylko reset FIDO, który kasuje wszystkie klucze FIDO2 i U2F z urządzenia: klucze SSH oraz rejestracje w bankach i OVHcloud. Blokady nie sprawdzamy na próbę.
- PIN jest jeden dla całego YubiKey i obowiązuje w SSH, bankach i OVHcloud. Zapamiętujemy go albo trzymamy w menedżerze haseł, nigdy w pliku obok kluczy. Ustawiamy go w kroku 0.
- Drugi YubiKey rejestrujemy wszędzie, zanim cokolwiek wyłączymy. Dopiero gdy zapasowy klucz działa na każdym serwerze i w każdym serwisie, usuwamy hasło albo stary klucz.
- Kody zapasowe trzymamy poza komputerem. 10 kodów z OVHcloud i dane do odzyskania dostępu w bankach przechowujemy oddzielnie od YubiKey i laptopa. Listę danych do kopii zapasowej podajemy w sekcji o kopiach zapasowych.
- Sesja awaryjna zostaje otwarta. Przy zmianach na serwerze nie zamykamy działającej sesji SSH ani konsoli dostawcy, dopóki nowe logowanie nie przejdzie testu.
Limity prób i skutki resetu opisuje manual techniczny YubiKey 5.
Stan dokumentacji: 1 października 2026 r. Procedurę SSH opieramy na kodzie i dokumentacji OpenSSH oraz Yubico, a mechanizm Ansible sprawdziliśmy z ansible-core 2.21.3 (najnowsze wydanie: 2.21.4) i OpenSSH 9.6p1. Przed wdrożeniem testujemy procedurę na własnym kliencie i serwerze. Nazwy kont, hostów i kluczy są celowo demonstracyjne.
Anonimizacja jest częścią procedury. Nie publikujemy numerów seryjnych, PIN-ów, kodów odzyskiwania, kodów jednorazowych OTP, adresów infrastruktury, odcisków kluczy hostów, wartości kluczy publicznych, wyników ykman, logów ssh -vvv ani danych klientów. admin-a, server01.example.net i 192.0.2.10 są wyłącznie przykładami.
Spis treści
- Co daje YubiKey podczas logowania przez SSH
- Jak FIDO2, WebAuthn i OpenSSH korzystają z YubiKey
- Co dokładnie dzieje się podczas logowania SSH
- Trzy klucze dla dwóch administratorów
- Przygotowanie stanowiska i serwera
- Logowanie SSH z YubiKey - krok po kroku
- Krok 0. Ustawiamy PIN FIDO2 na YubiKey przed utworzeniem pierwszego klucza SSH
- Krok 1. Tworzymy klucz SSH na pierwszym YubiKey
- Krok 2. Dodajemy klucz publiczny na serwerze
- Krok 3. Sprawdzamy nowe logowanie
- Krok 4. Wykonujemy test bez agenta, hasła i starego połączenia
- Krok 5. Dodajemy i testujemy klucz B oraz klucz S
- Jak aktualizować serwery backupowe przez Ansible i YubiKey
- Krok 1. Przygotowujemy konta i okno serwisowe
- Krok 2. Wydzielamy serwery backupowe w inventory
- Krok 3. Otwieramy pierwszą sesję z PIN-em i dotykiem YubiKey
- Krok 4. Zapisujemy playbook aktualizacji
- Krok 5. Sprawdzamy zakres i aktualizujemy tylko backup01
- Krok 6. Zamykamy sesję i przechodzimy do backup02
- Automatyzacja bez człowieka potrzebuje innej tożsamości
- YubiKey w banku i panelu OVHcloud
- macOS, Touch ID i iPhone - czym różnią się od YubiKey
- Utrata klucza i odzyskanie dostępu
- Checklista przed zmianą produkcyjną
Co daje YubiKey podczas logowania przez SSH
YubiKey to mały klucz sprzętowy wkładany do portu USB (część modeli działa też przez NFC), który potwierdza naszą tożsamość przy logowaniu. Przechowuje klucze kryptograficzne, których nie da się z niego skopiować. Dzięki temu do zalogowania potrzebujemy fizycznego urządzenia: wykradzione hasło ani skopiowany plik klucza nie wystarczą. W tym artykule używamy go do logowania przez SSH, w Ansible oraz w bankach i panelu OVHcloud.
Ten poradnik jest dla administratorów Linux i DevOps, którzy używają już SSH. Konfigurujemy klucz ed25519-sk, sprawdzamy nowe logowanie bez utraty dotychczasowego dostępu i uruchamiamy playbook aktualizacji dla osobnej grupy serwerów backupowych. Przykłady logowania do panelu WWW pokazują też, czym są FIDO2 i passkeys oraz jaką rolę pełni Touch ID.
Przy zwykłym kluczu ed25519 klient SSH lub agent wykonuje podpis kluczem prywatnym dostępnym na komputerze. Przy ed25519-sk podpis wykonuje YubiKey. Komputer nie otrzymuje klucza prywatnego w postaci pozwalającej podpisywać poza urządzeniem. Zachowuje natomiast lokalny plik OpenSSH potrzebny do zlecenia podpisu; jego zawartość opisujemy poniżej.
Dotknięcie YubiKey nie dodaje tokenu do klucza prywatnego i nie zmienia pary kluczy. Potwierdza obecność użytkownika i pozwala urządzeniu wykonać konkretny podpis. W opisywanej konfiguracji wymagamy również weryfikacji użytkownika PIN-em FIDO2 lub biometrią obsługiwaną przez urządzenie. Serwer weryfikuje podpis kluczem publicznym, a nie kombinację „klucz prywatny + dodatkowy token”.
Ochrona dotyczy nowego uwierzytelnienia, nie całej późniejszej pracy. Wyjęcie YubiKey nie kończy istniejącej sesji SSH ani sesji WWW. Nie zabezpiecza też odblokowanego laptopa przed użyciem już otwartych połączeń. Dlatego klucza nie zostawiamy na stałe w laptopie, a zapas przechowujemy w innym miejscu.
Jak FIDO2, WebAuthn i OpenSSH korzystają z YubiKey
FIDO2 to zestaw standardów, dzięki którym serwis może sprawdzić dostęp do klucza prywatnego zamiast polegać wyłącznie na haśle. Podczas logowania urządzenie podpisuje dane konkretnej próby, a serwis sprawdza podpis zapisanym wcześniej kluczem publicznym. FIDO2 może zastąpić hasło albo być drugim składnikiem logowania - zależy to od wdrożenia usługi. W przeglądarce powiązanie klucza z domeną utrudnia wyłudzenie dostępu przez fałszywą stronę. Nazwa FIDO pochodzi od Fast IDentity Online.
Za ochronę i używanie klucza prywatnego odpowiada authenticator. Może nim być osobny YubiKey albo mechanizm wbudowany w system komputera lub telefonu. YubiKey obsługuje wiele niezależnych poświadczeń: rejestracja tego samego urządzenia w banku, panelu hostingowym i SSH nie oznacza współdzielenia jednej pary kluczy przez te usługi.
FIDO2 łączy dwa standardy. WebAuthn (Web Authentication) określa, jak aplikacja WWW zleca przeglądarce utworzenie poświadczenia lub logowanie. CTAP2 (Client to Authenticator Protocol 2) określa komunikację komputera z zewnętrznym authenticatorem, np. YubiKey przez USB. Przeglądarka i system obsługują te etapy bez przepisywania jednorazowego kodu. Podział opisuje FIDO Alliance.
| Pojęcie | Rola w tym wdrożeniu |
|---|---|
| Poświadczenie FIDO, credential | Obejmuje parę kluczy dla danej aplikacji, identyfikator oraz metadane potrzebne do ich użycia. Strona weryfikująca zna klucz publiczny; authenticator używa klucza prywatnego do podpisywania. |
| Credential ID / key handle | Identyfikator poświadczenia przekazywany urządzeniu przy żądaniu podpisu. Jego zawartość może być zaszyfrowana przez YubiKey; nie jest zwykłą nazwą pliku ani numerem slotu. |
| RP ID (Relying Party Identifier) | Identyfikuje usługę korzystającą z WebAuthn, np. portal.example.net. Przeglądarka sprawdza, czy aktualna strona może użyć poświadczenia przypisanego do tego identyfikatora. |
| UP (User Presence) | Potwierdza interakcję człowieka z urządzeniem, zwykle dotknięcie czujnika podłączonego YubiKey. Zwykły dotyk nie identyfikuje osoby: czujnika może dotknąć każdy, kto ma fizyczny dostęp do klucza. |
| UV (User Verification) | Potwierdza weryfikację użytkownika przez authenticator, np. PIN-em FIDO2 albo odciskiem palca w zgodnym YubiKey Bio. Serwer może wymagać flagi UV w podpisanych danych. |
| PIN FIDO2 i passphrase | PIN sprawdza YubiKey; serwer SSH go nie otrzymuje. Passphrase szyfruje lokalny plik OpenSSH. Są to dwa niezależne zabezpieczenia, a nie dwa określenia tego samego hasła. |
| Resident / discoverable credential | Urządzenie przechowuje dane pozwalające odnaleźć poświadczenie bez wcześniejszej kopii lokalnego pliku. OpenSSH może je pobrać przez ssh-keygen -K. Nie eksportuje przy tym klucza prywatnego zdolnego do samodzielnego podpisywania. |
W SSH korzystamy z tego samego urządzenia, ale nie z logowania WWW. OpenSSH komunikuje się z YubiKey przez bibliotekę libfido2 i CTAP2, bez przeglądarki i WebAuthn. Klucz -sk ma identyfikator application, domyślnie ssh:, zamiast domeny panelu. Nie zwalnia nas to ze sprawdzania klucza hosta w known_hosts. Role protokołów opisuje dokumentacja CTAP.
Budowa YubiKey: jedno urządzenie USB z trzema interfejsami
YubiKey 5 to jedno urządzenie USB, które przedstawia się systemowi jako trzy interfejsy. Każdy obsługuje inne aplikacje:
| Interfejs | Jak widzi go system | Co przez niego działa |
|---|---|---|
| OTP (One-Time Password, hasło jednorazowe) | klawiatura USB | Aplikacja OTP. Dlatego YubiKey potrafi „wpisać” kod jednorazowy tak jak klawiatura. |
| FIDO | urządzenie HID (Human Interface Device) | FIDO2 i U2F: klucze SSH -sk oraz logowanie do OVHcloud i banków. |
| CCID (Chip Card Interface Device) | czytnik kart chipowych | PIV (Personal Identity Verification, karta kryptograficzna), OATH (kody jednorazowe TOTP i HOTP, czyli liczone z czasu albo z licznika) oraz OpenPGP. |
YubiKey nie ma interfejsu pamięci masowej: system nie widzi go jako dysku i nie zapiszemy na nim plików. Interfejsy opisuje manual techniczny YubiKey 5.
PIV, OATH i firmware - kiedy są potrzebne
Ta instrukcja używa aplikacji FIDO w YubiKey. PIV (Personal Identity Verification) udostępnia klucze i certyfikaty w modelu karty kryptograficznej. Aplikacja OATH (Initiative for Open Authentication) obsługuje mechanizmy kodów jednorazowych. Żadna z tych funkcji nie jest potrzebna do opisanego ed25519-sk ani playbooka Ansible.
Jeśli konkretna polityka wymaga PIV lub kart inteligentnych, planujemy to jako osobne wdrożenie z inwentaryzacją i drogą odzyskania. Reset aplikacji FIDO albo PIV usuwa zapisane w niej dane, dlatego nie używamy go jako zwykłego kroku diagnostycznego. Zakres firmware 5.8 opisuje dokumentacja Yubico.
Co dokładnie dzieje się podczas logowania SSH
Co znajduje się na komputerze, a co chroni YubiKey
Po wykonaniu ssh-keygen -t ed25519-sk powstają dwa lokalne pliki. Plik .pub zawiera klucz publiczny OpenSSH, łącznie z polem application. Plik bez .pub używa formatu pliku klucza prywatnego OpenSSH, ale jego zawartość dla typu -sk jest inna niż dla zwykłego Ed25519: zawiera m.in. klucz publiczny, application, flagi oraz key_handle. To ten plik podajemy przez ssh -i i dodajemy do agenta przez ssh-add.
Główna instrukcja używa opcji -O resident: YubiKey zachowuje dane pozwalające później odnaleźć poświadczenie. Istnieje też wariant nierezydentny, w którym key_handle nie musi wskazywać trwałego rekordu w pamięci urządzenia. Yubico opisuje mechanizm, w którym YubiKey generuje parę kluczy, szyfruje klucz prywatny wraz z metadanymi własnym kluczem głównym i zwraca zaszyfrowane dane jako identyfikator poświadczenia. Przy podpisywaniu urządzenie odtwarza klucz prywatny wewnętrznie. Klucz główny nie opuszcza YubiKey. Dlatego sama kopia lokalnego pliku nie wystarcza do podpisania nowego logowania.
Lokalny plik może więc zawierać zaszyfrowaną reprezentację klucza prywatnego, której nie da się użyć bez właściwego urządzenia. Dodatkowa passphrase OpenSSH chroni ten plik niezależnie od szyfrowania wykonywanego przez YubiKey. Format opisuje OpenSSH, a sposób zabezpieczenia identyfikatora - Yubico: generowanie kluczy.
Jak klient zleca podpis i co sprawdza serwer
Administrator A pracuje na laptopie i uruchamia ssh -i ~/.ssh/id_ed25519_sk_admin_a_on_key_a admin-a@server01.example.net. YubiKey A jest podłączony do tego laptopa, nie do serwera. Po drugiej stronie sshd ma w authorized_keys konta admin-a odpowiedni klucz publiczny. Przebieg tego połączenia wygląda następująco:
- Klient zestawia szyfrowany transport SSH i weryfikuje klucz hosta. Wymiana kluczy ustala identyfikator tej sesji.
- Klient buduje dane uwierzytelnienia obejmujące identyfikator sesji oraz pola żądania
SSH_MSG_USERAUTH_REQUEST, m.in. konto, usługę, metodępublickey, algorytm i klucz publiczny. Nie jest to po prostu dowolny „token przysłany przez serwer”. - OpenSSH, bezpośrednio lub przez agenta, zleca YubiKey podpis. Przekazuje
key_handle,applicationi skrót SHA-256 danych uwierzytelnienia. - YubiKey sprawdza wymagane UV i UP. Dla zwykłego modelu oznacza to PIN FIDO2 oraz dotyk. YubiKey Bio sprawdza UV odciskiem palca zamiast PIN-u. OpenSSH 8.4 obsługiwał wyłącznie PIN; weryfikację na urządzeniu, w tym biometrię, bez zbędnych pytań o PIN obsługuje od wersji 8.9.
- YubiKey wykonuje podpis kluczem prywatnym i zwraca podpis wraz z flagami oraz licznikiem. Klient umieszcza wynik w żądaniu uwierzytelnienia SSH.
sshdsprawdza, czy klucz publiczny jest uprawniony dla danego konta, weryfikuje podpis i wymagane flagi. Następnie stosuje pozostałą politykę logowania, w tym ewentualne dodatkowe metody zAuthenticationMethods.
Powiązanie danych z identyfikatorem sesji sprawia, że przechwycony podpis nie uwierzytelni innego połączenia. Zakres danych SSH określa RFC 4252, sekcja 7.
Dla opisanego ed25519-sk, bez dodatkowych rozszerzeń, dane podpisywane przez authenticator można przedstawić tak. Znak || oznacza połączenie pól w jeden ciąg bajtów, nie działanie na kluczach:
dane_podpisu =
SHA256(application)
|| flags
|| counter
|| SHA256(dane_uwierzytelnienia_SSH)
podpis = Ed25519.sign(
klucz_prywatny,
dane_podpisu
)
Flagi zawierają m.in. UP (0x01) i UV (0x04). Są objęte podpisem, więc klient nie może dopisać potwierdzenia dotyku lub PIN-u bez unieważnienia podpisu. counter jest licznikiem authenticatora, nie kodem OTP. Szczegóły weryfikacji pokazuje implementacja Ed25519-SK w OpenSSH.
Dotyk jest domyślnie wymagany przez sshd dla kluczy -sk. UV egzekwujemy opcją verify-required przy kluczu w authorized_keys albo odpowiednią polityką PubkeyAuthOptions. Samo ustawienie opcji klienta nie zastępuje wymagania po stronie serwera. To nadal metoda SSH publickey; PIN FIDO2 nie jest osobnym hasłem przesyłanym do sshd. Dokumentacja serwera opisuje egzekwowanie tych flag.
Trzy klucze dla dwóch administratorów
Dla jednej osoby minimum to dwa fizyczne YubiKey: klucz używany codziennie i klucz zapasowy, trzymany w innym miejscu. Poniższy wariant dotyczy pary wzajemnie zaufanych administratorów. Każdy z dwóch kluczy codziennych jest podstawowym dla jednej osoby i zapasowym dla drugiej. Trzeci klucz leży w zaplombowanym sejfie i służy wyłącznie do odzyskania dostępu.
| Fizyczny YubiKey | Gdzie jest | Rola |
|---|---|---|
| Klucz A | Przy administratorze A | Podstawowy klucz SSH dla konta admin-a oraz osobny klucz zapasowy dla konta admin-b. |
| Klucz B | Przy administratorze B | Podstawowy klucz SSH dla konta admin-b oraz osobny klucz zapasowy dla konta admin-a. |
| Klucz S | Sejf, poza biurem i torbami administratorów | Klucz do osobnego konta breakglass. Testujemy go przed zaplombowaniem i używamy wyłącznie według procedury incydentowej. |
Na każdym urządzeniu tworzymy osobne poświadczenie SSH-FIDO dla każdego wskazanego konta. Nie kopiujemy jednego klucza prywatnego między YubiKeyami. Dla urządzenia A lokalne pliki nazywamy id_ed25519_sk_admin_a_on_key_a oraz id_ed25519_sk_admin_b_on_key_a. Urządzenie B ma dwa analogiczne poświadczenia. Nazwy pomagają w ewidencji, ale same nie ograniczają dostępu: uprawnienia nadajemy przez dodanie odpowiedniego klucza publicznego do właściwego authorized_keys.
PIN FIDO2 obowiązuje dla całego urządzenia, a nie osobno dla każdego poświadczenia. Administrator mający YubiKey A i jego PIN może użyć również klucza dla admin-b. Osobne konta zachowują podział uprawnień i logów, lecz sam ten układ nie pozwala jednoznacznie ustalić, która osoba użyła konta. Wzajemny zapas wymaga więc zaufania oraz rejestrowania przekazania i użycia urządzenia. Jeśli dostęp ma być przypisany wyłącznie do konkretnej osoby, każdy administrator powinien mieć własny, niezależny klucz zapasowy.
Klucz S służy do osobnego konta awaryjnego breakglass z jawnie określonymi uprawnieniami sudo i procedurą użycia. PIN przechowujemy oddzielnie od urządzenia, najlepiej pod kontrolą drugiej osoby. YubiKey sam nie egzekwuje udziału dwóch administratorów; musi to zapewnić procedura wydania, bastion lub system zatwierdzania dostępu.
Przygotowanie stanowiska i serwera
Przed zmianą zostawiamy otwartą działającą sesję SSH, konsolę dostawcy albo inną sprawdzoną drogę odzyskania. Nie wyłączamy starego klucza ani logowania hasłem, dopóki każdy nowy YubiKey nie przejdzie testu w osobnej sesji. Nie resetujemy funkcji FIDO i nie sprawdzamy blokady przez wpisywanie błędnego PIN-u.
Warunki techniczne
- Komputer administratora ma YubiKey podłączony przez USB. To na nim uruchamiamy
ssh-keygenissh. - Klient OpenSSH ma wersję co najmniej
8.2i obsługę FIDO przezlibfido2, czyli bibliotekę umożliwiającą rozmowę klienta SSH z YubiKey przez USB. Sam numer wersji nie wystarcza, ponieważ część dystrybucji buduje klienta bez tej obsługi. - Pobieranie poświadczeń rezydentnych przez
ssh-keygen -Kdziała od OpenSSH8.2(strona Yubico podaje8.3, ale polecenie opisują już informacje o wydaniu 8.2). Pełna procedura poniżej wymaga jednak klienta i serwera8.4lub nowszego: używamy-O verify-requiredprzy tworzeniu klucza orazverify-requiredwauthorized_keys. - Serwer akceptuje klucze
sk-ssh-ed25519@openssh.com. Serwer nie potrzebuje podłączonego YubiKey ani bibliotekilibfido2.
Sprawdzamy klienta OpenSSH na Debianie i Ubuntu
Na Debianie lub Ubuntu poniższe polecenia sprawdzają wersję, instalują klienta, a na końcu sprawdzają, czy klient zna nazwy algorytmów sk-. W Debianie 12 i 13 oraz Ubuntu 24.04 i 26.04 pakiet openssh-client sam instaluje bibliotekę libfido2-1. W Fedora, RHEL i innych dystrybucjach nazwy pakietów są inne.
ssh -V
sudo apt update
sudo apt install openssh-client
ssh -Q key | grep -E 'sk-ssh-ed25519@openssh.com|sk-ecdsa-sha2-nistp256@openssh.com'
Ostatnia linia powinna wypisać co najmniej jeden typ klucza zaczynający się od sk-. To tylko wstępny test nazw algorytmów; zgodność biblioteki i urządzenia potwierdzi dopiero utworzenie klucza w kroku 1. Jeżeli linia nic nie wypisuje albo później ssh-keygen nie widzi YubiKey, zatrzymujemy się i sprawdzamy pakiety oraz zasady dostępu USB dla własnej dystrybucji. Nie obchodzimy tego przez obniżanie ochrony.
PIN FIDO2 ustawiamy przed utworzeniem klucza, w kroku 0. PIN wpisujemy tylko w oknie lub monicie narzędzia; nie podajemy go w poleceniu, pliku YAML ani historii powłoki. Nie używamy starego YubiKey Manager GUI: Yubico zakończyło jego wsparcie 19 lutego 2026 r. Narzędzie CLI ykman pozostaje dostępne. Rozróżnienie opisuje dokumentacja Yubico.
Sprawdzamy klienta na macOS: OpenSSH z Homebrew zamiast systemowego
Systemowy klient OpenSSH w macOS nie ma obsługi FIDO potrzebnej do kluczy -sk. Yubico wskazuje instalację OpenSSH z Homebrew; formuła openssh (1 października 2026 r. wersja 10.5p1) jest budowana z libfido2. Po instalacji sprawdzamy, którego programu rzeczywiście używa terminal:
brew install openssh ssh-copy-id
export PATH="$(brew --prefix openssh)/bin:$PATH"
command -v ssh ssh-keygen ssh-agent ssh-add ssh-copy-id
ssh -V
Zmiana PATH dotyczy bieżącego terminala. ssh i ssh-keygen powinny pochodzić z instalacji Homebrew. Sprawdzamy ścieżki przed konfiguracją; istniejący systemowy agent nie zostaje wymieniony samym ustawieniem PATH. Jeżeli korzystamy z agenta, osobno sprawdzamy zgodność ssh-agent i ssh-add. Pakiet ssh-copy-id instalujemy osobno.
Jeżeli ~/.ssh/config zawiera typowy na Macu wpis UseKeychain yes, OpenSSH z Homebrew przerywa działanie komunikatem Bad configuration option: usekeychain. Tak samo reaguje upstream OpenSSH 9.6p1, na którym to sprawdziliśmy. Na początku ~/.ssh/config dopisujemy więc linię:
IgnoreUnknown UseKeychain
Systemowy klient Apple nadal użyje UseKeychain, a klient z Homebrew pominie tę opcję. Następnie wykonujemy kroki SSH i testujemy pojedyncze połączenie. W przykładzie Ansible dla serwerów backupowych otwieramy sesje SSH ręcznie, aby podać PIN na terminalu i dotknąć YubiKey, a potem udostępniamy te połączenia playbookowi.
Sprawdzamy serwer przed dodaniem klucza
Na serwerze Debian/Ubuntu, korzystając z pozostawionej sesji awaryjnej albo konsoli dostawcy, sprawdzamy wersję pakietu serwera oraz aktywną konfigurację. Drugie polecenie wypisuje obowiązujące ustawienia dotyczące kluczy publicznych; oczekujemy w nim co najmniej pubkeyauthentication yes oraz braku wykluczenia typu sk-ssh-ed25519@openssh.com. W innych dystrybucjach wersję pakietu sprawdzamy ich menedżerem pakietów. Opcja sshd -V jest dostępna dopiero od OpenSSH 9.2.
dpkg-query -W openssh-server
sudo sshd -T | grep -Ei 'pubkeyauthentication|pubkeyaccepted(keytypes|algorithms)|pubkeyauthoptions|allowusers|authenticationmethods'
OpenSSH 8.4 używa nazwy pubkeyacceptedkeytypes, a nowsze wersje - pubkeyacceptedalgorithms, dlatego polecenie uwzględnia obie. Dla konfiguracji z blokami Match sprawdzamy ustawienia konkretnego połączenia. W -C pole host oznacza rozwiązaną nazwę klienta, nie serwera, a addr jest adresem klienta widzianym przez serwer, np. adresem po translacji NAT:
sudo sshd -T -C user=admin-a,host=admin-workstation.example.net,addr=192.0.2.10 | \
grep -Ei 'pubkeyauthentication|pubkeyaccepted(keytypes|algorithms)|pubkeyauthoptions|allowusers|authenticationmethods'
Po każdej ręcznej zmianie konfiguracji serwera wykonujemy sudo sshd -t przed przeładowaniem usługi. To sprawdza składnię, ale nie zastępuje nowego testu logowania. Gdy serwer wymaga dodatkowej metody z AuthenticationMethods, wykonujemy test z zachowaniem tej metody.
Czy YubiKey i firmware wystarczą?
Do podstawowej instrukcji SSH potrzebny jest YubiKey z FIDO2. Typ ed25519-sk wymaga firmware co najmniej 5.2.3; na starszym zgodnym urządzeniu można użyć ecdsa-sk w tych samych krokach. Firmware 5.8 rozszerza możliwości FIDO2, lecz nie jest warunkiem działania SSH z ed25519-sk. Firmware YubiKey jest fabryczny, więc nie aktualizujemy go samodzielnie.
Nie resetujemy FIDO ani pozostałych aplikacji YubiKey w ramach testu zgodności. Reset może unieważnić istniejące poświadczenia; brak obsługi algorytmu wymaga sprawdzenia modelu, firmware i klienta, a nie kasowania konfiguracji urządzenia.
Logowanie SSH z YubiKey - krok po kroku
Poniższy przykład pokazuje podstawowy klucz A dla konta admin-a na serwerze server01.example.net. Są to nazwy przykładowe. Administrator pracujący samodzielnie może zastąpić admin-a swoim kontem. Para z tabeli A/B/S powtarza te kroki osobno dla każdego wskazanego połączenia klucza fizycznego i konta.
Krok 0. Ustawiamy PIN FIDO2 na YubiKey przed utworzeniem pierwszego klucza SSH
PIN FIDO2 jest jeden dla całego YubiKey: ten sam obowiązuje w SSH, w banku i w panelu WWW. Ustawiamy go raz, przed krokiem 1. Bez PIN-u YubiKey nie utworzy klucza z -O resident. Na komputerze administratora, z podłączonym tylko YubiKey A, uruchamiamy:
ykman fido access change-pin
Narzędzie pyta o nowy PIN i jego powtórzenie, a jeżeli PIN był już ustawiony, najpierw o obecny. PIN FIDO2 ma co najmniej 4 znaki. Nie podajemy go w parametrach --pin ani --new-pin, bo trafiłby do historii powłoki. Po trzech błędnych próbach z rzędu YubiKey trzeba wyjąć i włożyć ponownie, a osiem błędnych prób z rzędu blokuje FIDO2 do czasu resetu, który kasuje wszystkie klucze FIDO na urządzeniu. To samo zrobimy w aplikacji Yubico Authenticator. Polecenia opisuje dokumentacja ykman.
Sam ustawiony PIN nie sprawia, że SSH o niego pyta. Decyduje o tym konkretny klucz:
- Klucz utworzony z
-O verify-requiredwymaga PIN-u i dotyku przy każdym logowaniu. YubiKey zapisuje ten wymóg w samym poświadczeniu (rozszerzenie FIDOcredProtect) i bez weryfikacji użytkownika nie wykona podpisu. - Klucz utworzony bez tej opcji loguje samym dotykiem, nawet na tym samym YubiKey z ustawionym PIN-em.
- Na jednym YubiKey mogą więc działać oba rodzaje kluczy. Serwer wymusza PIN opcją
verify-requiredwauthorized_keys(krok 2). - OpenSSH nie dodaje
verify-requireddo istniejącego klucza. Klucz bez tej opcji zastępujemy nowym.
Ustawienie PIN-u nie tworzy żadnego pliku na komputerze. PIN jest zapisany w YubiKey, a urządzenie samo liczy błędne próby. Z tego kroku nic nie trafia do kopii zapasowej; PIN zapamiętujemy albo przechowujemy w menedżerze haseł. Pliki do kopii zapasowej powstają dopiero w kroku 1, a ich listę podajemy w sekcji o kopiach zapasowych.
Ustawienie PIN-u nie kasuje kluczy dodanych wcześniej do OVHcloud ani banków. Co zmienia się przy logowaniu do tych serwisów, opisujemy w sekcji o bankach i OVHcloud.
Krok 1. Tworzymy klucz SSH na pierwszym YubiKey
Na komputerze administratora podłączamy wyłącznie YubiKey A. ssh-keygen zleci urządzeniu utworzenie poświadczenia, zapisze lokalny plik klucza OpenSSH oraz plik .pub. W trakcie rejestracji wykonujemy wymagane potwierdzenia PIN-em lub biometrią i dotykiem. Monit Enter passphrase dotyczy szyfrowania lokalnego pliku, nie PIN-u FIDO2; ustawiamy odrębną passphrase.
umask 077
install -d -m 700 "$HOME/.ssh"
ssh-keygen -t ed25519-sk \
-O resident \
-O verify-required \
-O application=ssh:admin-a-key-a \
-C "admin-a-key-a" \
-f "$HOME/.ssh/id_ed25519_sk_admin_a_on_key_a"
ssh-keygen -lf "$HOME/.ssh/id_ed25519_sk_admin_a_on_key_a.pub"
-t ed25519-sk wybiera algorytm z podpisywaniem przez authenticator. -O application=ssh:admin-a-key-a ustawia identyfikator aplikacji FIDO, który staje się częścią klucza publicznego i danych objętych podpisem. Musi zaczynać się od ssh:. Nie ogranicza klucza do konkretnego hosta ani konta. -C dodaje wyłącznie komentarz do ewidencji. umask 077 i uprawnienia katalogu ograniczają lokalny dostęp do tworzonych plików.
-f określa ścieżkę lokalnego pliku klucza OpenSSH, zawierającego opisane wcześniej key_handle i metadane. Plik z końcówką .pub zawiera klucz publiczny przeznaczony na serwer. Ostatnie polecenie wypisuje jego fingerprint; zapisujemy go w prywatnej ewidencji razem z urządzeniem, komentarzem i kontem docelowym.
-O verify-required zapisuje w poświadczeniu na YubiKey wymóg weryfikacji użytkownika, więc każdy podpis wymaga PIN-u. Ten sam wymóg dodamy na serwerze, żeby sshd sam sprawdzał flagę UV w podpisie. -O resident tworzy poświadczenie, którego dane można odnaleźć na YubiKey i pobrać przez ssh-keygen -K na nowej stacji. Osoba mająca urządzenie i PIN również może skorzystać z tej możliwości. Bez resident zachowujemy kopię lokalnego pliku, ponieważ samo urządzenie nie pozwoli odtworzyć go tą metodą.
Krok 2. Dodajemy klucz publiczny na serwerze
Na komputerze administratora ustawiamy trzy zmienne przykładowymi wartościami i kopiujemy klucz publiczny na serwer. ssh-copy-id loguje się dotychczas działającą metodą i dopisuje nową linię z pliku .pub do ~/.ssh/authorized_keys na serwerze. Nie usuwa starego klucza.
target_user=admin-a
target_host=server01.example.net
key_file="$HOME/.ssh/id_ed25519_sk_admin_a_on_key_a"
ssh-copy-id -i "$key_file.pub" "$target_user@$target_host"
Jeżeli łączyliśmy się już z tym serwerem z tego komputera, ssh-copy-id nie zapyta o serwer, bo jego klucz hosta jest zapisany w ~/.ssh/known_hosts. Gdyby ten klucz się zmienił, ssh przerwie połączenie z ostrzeżeniem WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!. Przy pierwszym połączeniu ssh-copy-id zapyta o klucz hosta; jak odpowiedzieć, opisujemy niżej w dodatkowym sprawdzeniu.
Jeżeli organizacja zarządza authorized_keys przez system konfiguracji, nowy klucz publiczny dodajemy w jego źródle. Ręczna zmiana na serwerze mogłaby zostać nadpisana podczas kolejnego wdrożenia.
Najpierw sprawdzamy nowy klucz zgodnie z krokami 3-4. Następnie, zachowując sesję awaryjną, wymagamy UV także na serwerze: przed nową linią klucza w authorized_keys dodajemy verify-required i ponownie wykonujemy rygorystyczny test z kroku 4. Jeżeli linia ma już inne opcje, łączymy je przecinkami w tym samym polu opcji. Dopiero po tym teście uznajemy konfigurację za gotową. Wymóg PIN-u egzekwują wtedy obie strony: YubiKey nie podpisze bez PIN-u, a sshd odrzuci podpis bez flagi UV. Zmiana authorized_keys nie wymaga restartu sshd.
Dodatkowe sprawdzenie: odcisk klucza hosta przy pierwszym połączeniu z serwerem
Gdy łączymy się z serwerem z tego komputera po raz pierwszy, ssh-copy-id pokaże odcisk (fingerprint) klucza hosta i zapyta, czy mu ufamy:
The authenticity of host 'server01.example.net (192.0.2.10)' can't be established.
ED25519 key fingerprint is SHA256:…
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Przy pierwszym połączeniu klient nie ma z czym porównać tego klucza, więc nie odróżni podstawionego serwera od prawdziwego. Logowanie kluczem SSH, także z YubiKey, jest związane z konkretną sesją, więc podstawiony serwer nie użyje go do zalogowania się na prawdziwy. Hasło trafiłoby jednak do podstawionego serwera. Dlatego gdy ssh-copy-id loguje się hasłem, wykonujemy to sprawdzenie zawsze; przy logowaniu kluczem jest ono dodatkowym zabezpieczeniem.
Prawdziwy odcisk odczytujemy drogą, która nie przechodzi przez to połączenie SSH, najprościej przez konsolę serwera w panelu dostawcy (w OVHcloud: konsola KVM). Na serwerze uruchamiamy:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Plik .pub jest czytelny dla każdego użytkownika, więc nie potrzebujemy uprawnień roota. Jeżeli serwer przedstawia klucz innego typu niż Ed25519, odczytujemy odcisk z odpowiadającego mu pliku w /etc/ssh. Na pytanie ssh-copy-id odpowiadamy, wklejając samą część SHA256:… zamiast wpisywać yes. Od OpenSSH 8.0 klient sam porówna oba odciski: zgodny zapisze w known_hosts, a innego nie przyjmie i zapyta ponownie.
Krok 3. Sprawdzamy nowe logowanie
Pierwszy test wykonujemy w nowym terminalu, pozostawiając sesję awaryjną otwartą. Używamy jawnej ścieżki i konta, bez zależności od zmiennych z poprzedniego terminala. Klient może poprosić o passphrase, a authenticator o wymagane UV i UP. Po udanym uwierzytelnieniu otrzymamy wynik id oraz hostname.
ssh -i "$HOME/.ssh/id_ed25519_sk_admin_a_on_key_a" \
admin-a@server01.example.net 'id && hostname'
Krok 4. Wykonujemy test bez agenta, hasła i starego połączenia
Po zwykłym teście wykonujemy drugi, bardziej rygorystyczny test. Pomija on własną konfigurację ~/.ssh/config, wyłącza agenta SSH, logowanie hasłem i istniejące połączenie współdzielone. Dzięki temu wynik potwierdza działanie właśnie wskazanego nowego klucza, a nie starego dostępu pozostawionego w tle.
ssh \
-F /dev/null \
-o ControlMaster=no \
-o ControlPath=none \
-o IdentitiesOnly=yes \
-o IdentityAgent=none \
-o PreferredAuthentications=publickey \
-o PasswordAuthentication=no \
-o KbdInteractiveAuthentication=no \
-i "$HOME/.ssh/id_ed25519_sk_admin_a_on_key_a" \
admin-a@server01.example.net 'id'
-F /dev/null pomija wpisy z własnego ~/.ssh/config, które mogłyby dodać inny plik tożsamości. Pomija także potrzebne tam ustawienia, na przykład bastion ProxyJump lub niestandardowy port. Jeżeli infrastruktura ich wymaga, dopisujemy je jawnie do polecenia jako -J bastion.example.net i/lub -p 2222, używając własnych wartości. ControlMaster=no i ControlPath=none wymuszają nową sesję. IdentityAgent=none wyłącza klucze zapamiętane przez agenta, a IdentitiesOnly=yes ogranicza proponowane tożsamości. Ten ręczny test może ponownie poprosić o passphrase lokalnego pliku klucza. Opcje wyłączające hasło i klawiaturę zapobiegają przypadkowemu użyciu innej metody. Nie używamy StrictHostKeyChecking=no i nie przekazujemy agenta poleceniem ssh -A.
Krok 5. Dodajemy i testujemy klucz B oraz klucz S
Klucz admin-a na urządzeniu A już powstał. Dla pozostałych kombinacji powtarzamy kroki 1-4, łącznie z wymuszeniem UV i ponownym testem. Za każdym razem zmieniamy wszystkie trzy parametry: -O application, -C oraz ścieżkę -f. Sama zmiana komentarza i nazwy pliku nie wystarczy: ponowne użycie tej samej application i identyfikatora użytkownika na jednym urządzeniu może zastąpić wcześniejsze poświadczenie rezydentne.
| Urządzenie / konto | -O application | -C |
|---|---|---|
| A / admin-a | ssh:admin-a-key-a | admin-a-key-a |
| A / admin-b | ssh:admin-b-key-a | admin-b-key-a |
| B / admin-b | ssh:admin-b-key-b | admin-b-key-b |
| B / admin-a | ssh:admin-a-key-b | admin-a-key-b |
| S / breakglass | ssh:breakglass-key-s | breakglass-key-s |
Dla -f wybieramy za każdym razem nową ścieżkę, np. ~/.ssh/id_ed25519_sk_admin_b_on_key_a dla drugiego wiersza. Odpowiadający plik .pub dodajemy wyłącznie do właściwego konta. Ryzyko nadpisania poświadczenia opisuje instrukcja Yubico dla kluczy rezydentnych.
Klucz S testujemy przed umieszczeniem w sejfie i zapisujemy w prywatnej ewidencji, jakie systemy obsługuje, kto może otworzyć sejf, kto przechowuje PIN oraz odciski każdego klucza publicznego. Nie publikujemy tych danych. Starą metodę logowania wyłączamy dopiero wtedy, gdy każdy wymagany klucz przeszedł rygorystyczny test z kroku 4 i działa droga awaryjna. Nie robimy tego w tej samej chwili co pierwszy test.
Jak aktualizować serwery backupowe przez Ansible i YubiKey
Mamy dwa serwery: backup01.example.net i backup02.example.net, oba z Debianem lub Ubuntu. W inventory należą do osobnej grupy backup_servers. Pozostały host app01.example.net należy do grupy application_servers i nie ma zostać objęty aktualizacją. Ansible uruchamiamy na zaufanym laptopie administratora A, do którego podłączamy YubiKey A.
Używamy klucza ed25519-sk utworzonego wcześniej: ~/.ssh/id_ed25519_sk_admin_a_on_key_a. Jest to klucz SSH, którym podpisuje YubiKey, a nie zwykły klucz Ed25519 uzupełniony o jednorazowy kod. Na serwerach backupowych konto admin-a ma jego klucz publiczny z opcją verify-required w authorized_keys. Dodanie i rygorystyczny test wykonujemy według poprzedniej sekcji, osobno dla obu hostów, z zachowaniem dostępu zapasowego.
Krok 1. Przygotowujemy konta i okno serwisowe
Konto admin-a musi mieć uprawnienie sudo potrzebne do aktualizacji pakietów. Na serwerach przygotowujemy Python 3 i pakiet python3-apt. Sprawdzamy ostatnią poprawną kopię i możliwość jej odtworzenia, dostęp do konsoli oraz brak trwającego backupu, odtwarzania lub porządkowania repozytorium. Aktualizację wykonujemy w oknie serwisowym. Playbook nie zna harmonogramu używanego systemu backupowego i sam tego nie sprawdzi.
Nie wykonujemy automatycznego restartu hosta. Aktualizacja pakietów może jednak restartować usługi, dlatego sam brak zadania reboot nie gwarantuje ciągłości backupu. Przykład dotyczy aktualizacji pakietów w bieżącym wydaniu Debian/Ubuntu, a nie przejścia na nowe wydanie systemu.
Krok 2. Wydzielamy serwery backupowe w inventory
Na laptopie, jako zwykły użytkownik uruchamiający Ansible, tworzymy osobny katalog projektu. Poniższe polecenia wykonujemy w jednym terminalu; również późniejsze polecenia Ansible uruchamiamy z tego katalogu:
umask 077
mkdir -p "$HOME/ansible-backup-example/group_vars"
cd "$HOME/ansible-backup-example"
ansible --version
Jeżeli katalog już istnieje, najpierw sprawdzamy jego zawartość i nie nadpisujemy własnej konfiguracji. Zapisujemy poniższy plik inventory.yml. Nazwy hostów zastępujemy własnymi; konto admin-a musi istnieć na obu serwerach backupowych:
all:
children:
backup_servers:
hosts:
backup01:
ansible_host: backup01.example.net
backup02:
ansible_host: backup02.example.net
application_servers:
hosts:
app01:
ansible_host: app01.example.net
vars:
ansible_user: deploy
ansible_ssh_private_key_file: >-
{{ lookup('ansible.builtin.env', 'HOME') }}/.ssh/id_ed25519_deploy
W group_vars/backup_servers.yml zapisujemy ustawienia dotyczące wyłącznie grupy backupowej. Ścieżka klucza jest lokalna na laptopie. Plik nie zawiera PIN-u, passphrase ani hasła sudo:
ansible_connection: ssh
ansible_user: admin-a
ansible_port: 22
ansible_python_interpreter: /usr/bin/python3
ansible_ssh_private_key_file: >-
{{ lookup('ansible.builtin.env', 'HOME') }}/.ssh/id_ed25519_sk_admin_a_on_key_a
ansible_ssh_args: >-
-F /dev/null
-o ControlMaster=no
-o BatchMode=yes
-o IdentityAgent=none
-o IdentitiesOnly=yes
-o PreferredAuthentications=publickey
-o PasswordAuthentication=no
-o KbdInteractiveAuthentication=no
-o StrictHostKeyChecking=yes
-o ProxyCommand=false
ansible_ssh_common_args: >-
-o ControlPath={{ lookup('ansible.builtin.env', 'BACKUP_CONTROL_DIR') }}/%h-%p-%r
Ansible korzysta tu z wcześniej uwierzytelnionego połączenia SSH. ControlPath wskazuje lokalny socket, przez który kolejne procesy klienta otwierają kanały w tym samym połączeniu. %h, %p i %r oznaczają host, port i konto. ProxyCommand=false celowo uniemożliwia zestawienie nowego transportu, gdy socketu zabraknie. Działający master jest sprawdzany wcześniej. Samo ControlMaster=no ani BatchMode=yes nie dawałoby takiej gwarancji. W tym wariancie błąd sesji ma zatrzymać zadanie, a nie uruchamiać inne logowanie. Zasady opisują OpenSSH i plugin SSH Ansible.
Ten mechanizm sprawdziliśmy 1 października 2026 r. z ansible-core 2.21.3 i OpenSSH 9.6p1, na zwykłym kluczu Ed25519 zamiast klucza z YubiKey; dla współdzielonego połączenia typ klucza nie ma znaczenia. Przy otwartym masterze ping i playbook wykonały 23 wywołania ssh i sftp, a serwer zarejestrował jedno połączenie i jedno logowanie. Bez mastera Ansible zgłosił host jako UNREACHABLE i nie otworzył nowego połączenia. Po usunięciu ProxyCommand=false ten sam przebieg otworzył 6 nowych połączeń mimo BatchMode=yes.
Host app01 nie dziedziczy tych opcji. Podział w inventory wybiera sposób połączenia, ale nie jest polityką dostępu serwera: jeśli na backup01 pozostawiono inny klucz lub logowanie hasłem, nadal mogą być użyte poza tym przykładem. Ich ewentualne wycofanie wymaga osobnej decyzji i przetestowanego dostępu awaryjnego.
Krok 3. Otwieramy pierwszą sesję z PIN-em i dotykiem YubiKey
Klucze hostów muszą być już zapisane w ~/.ssh/known_hosts. Poniższa funkcja używa StrictHostKeyChecking=yes, więc nieznany lub zmieniony klucz hosta przerwie połączenie zamiast wyświetlić pytanie. Jeśli łączyliśmy się już z tymi serwerami, wpisy są na miejscu; dla nowego serwera najpierw wykonujemy dodatkowe sprawdzenie odcisku klucza hosta z kroku 2 procedury SSH. Na laptopie tworzymy prywatny katalog socketów i definiujemy funkcję otwierającą połączenie:
export BACKUP_CONTROL_DIR
BACKUP_CONTROL_DIR=$(mktemp -d /tmp/ansible-backup.XXXXXX)
open_backup_ssh() {
SSH_ASKPASS_REQUIRE=never ssh -F /dev/null -MNf \
-p 22 \
-o ControlMaster=yes \
-o ControlPersist=30m \
-S "$BACKUP_CONTROL_DIR/%h-%p-%r" \
-o IdentityAgent=none \
-o IdentitiesOnly=yes \
-o PreferredAuthentications=publickey \
-o PasswordAuthentication=no \
-o KbdInteractiveAuthentication=no \
-o StrictHostKeyChecking=yes \
-i "$HOME/.ssh/id_ed25519_sk_admin_a_on_key_a" \
"admin-a@$1"
}
open_backup_ssh backup01.example.net
ssh -F /dev/null -p 22 \
-S "$BACKUP_CONTROL_DIR/%h-%p-%r" \
-O check admin-a@backup01.example.net
Interaktywny klient może poprosić o passphrase lokalnego pliku, następnie o PIN FIDO2 i dotyk YubiKey. Dopiero po uwierzytelnieniu opcja -f przenosi klienta w tło; -N oznacza, że nie uruchamiamy zdalnego polecenia. -O check powinno potwierdzić działanie mastera. PIN nie trafia do Ansible ani na serwer. Użycie istniejącego połączenia nie wymaga programu graficznego askpass.
ControlPersist=30m oznacza 30 minut bezczynności, nie twardy limit czasu całej pracy. Dlatego drugi host otworzymy dopiero przed jego aktualizacją. Ansible uruchamiamy jako ten sam lokalny użytkownik, bez sudo, aby zachować katalog domowy, zmienne i ścieżki połączenia. Prywatny katalog chroni socket przed innymi zwykłymi użytkownikami, nie przed lokalnym root. Po zmianie terminala trzeba odtworzyć zmienne i sesję. W tym przykładzie nie ma bastionu; jeżeli jest wymagany, jego parametry dodajemy do ręcznego otwarcia mastera. Konto, docelowy host i port muszą zgadzać się z inventory.
Krok 4. Zapisujemy playbook aktualizacji
Plik update-backup-os.yml ma następującą zawartość. hosts: backup_servers ogranicza cel, serial: 1 przetwarza hosty kolejno, a any_errors_fatal: true zatrzymuje dalsze wykonanie po błędzie. Aktualizacja wymaga jawnego potwierdzenia okna serwisowego:
---
- name: Aktualizujemy system serwerow backupowych
hosts: backup_servers
gather_facts: true
become: true
serial: 1
any_errors_fatal: true
pre_tasks:
- name: Sprawdzamy rodzine systemu i zgode na aktualizacje
ansible.builtin.assert:
that:
- ansible_facts['os_family'] == 'Debian'
- >-
ansible_check_mode or
(backup_maintenance_confirmed | default(false) | bool)
fail_msg: >-
Przyklad dotyczy Debian/Ubuntu. Przed aktualizacja potwierdz
okno serwisowe przez backup_maintenance_confirmed=true.
tasks:
- name: Odswiezamy indeksy i aktualizujemy pakiety
ansible.builtin.apt:
update_cache: true
upgrade: dist
fail_on_autoremove: true
lock_timeout: 120
- name: Sprawdzamy plik z informacja o wymaganym restarcie
ansible.builtin.stat:
path: /var/run/reboot-required
register: backup_reboot_required
- name: Pokazujemy informacje o restarcie
ansible.builtin.debug:
msg: >-
{{ 'System zglasza koniecznosc restartu.'
if backup_reboot_required.stat.exists
else 'Brak pliku reboot-required nie gwarantuje, ze restart jest zbedny.' }}
upgrade: dist używa bieżących repozytoriów i może instalować nowe zależności. fail_on_autoremove: true przerywa operację, jeśli wymagałaby usunięcia pakietów; nie wyłączamy tej ochrony bez przejrzenia planu. Przy upgrade: dist moduł zawsze wywołuje apt-get dist-upgrade, a lock_timeout pozwala przez 120 sekund czekać na blokadę pakietów. Brak pliku reboot-required, szczególnie na Debianie, nie dowodzi, że restart nie jest potrzebny. Dokumentacja modułu apt opisuje znaczenie tych opcji.
Krok 5. Sprawdzamy zakres i aktualizujemy tylko backup01
Najpierw sprawdzamy inventory i składnię. Te trzy polecenia nie łączą się z serwerami. W wyniku --list-hosts mają być wyłącznie backup01 oraz backup02, bez app01:
ansible-inventory -i inventory.yml --graph
ansible-playbook -i inventory.yml update-backup-os.yml --syntax-check
ansible-playbook -i inventory.yml update-backup-os.yml --list-hosts
Teraz testujemy połączenie i wykonanie Pythona na pierwszym serwerze. Moduł ping powinien zwrócić pong; nie jest to test ICMP. Następnie wykonujemy podgląd aktualizacji:
ansible -i inventory.yml backup_servers --limit backup01 \
-m ansible.builtin.ping -f 1
ansible-playbook -i inventory.yml update-backup-os.yml \
--limit backup01 --check --diff --ask-become-pass
--ask-become-pass pyta o hasło sudo, nie o PIN YubiKey. Pomijamy tę opcję, jeśli konto ma poprawnie skonfigurowane sudo bez hasła. --check jest prognozą: nie aktualizuje faktycznie indeksów pakietów i nie gwarantuje, że późniejszy przebieg da identyczny wynik. Sprawdzamy listę zmian oraz zgodność z polityką utrzymania serwera. Ograniczenia opisuje dokumentacja check mode.
Po potwierdzeniu warunków z kroku 1 uruchamiamy właściwą aktualizację:
ansible-playbook -i inventory.yml update-backup-os.yml \
--limit backup01 --ask-become-pass \
-e '{"backup_maintenance_confirmed": true}'
Oczekujemy podsumowania failed=0 i unreachable=0. Następnie sprawdzamy usługi backupowe, dostęp do repozytorium i testowe zadanie backupu oraz odtworzenia. Sposób tych testów zależy od używanego oprogramowania; poprawne zakończenie apt ich nie zastępuje. Jeśli potrzebny jest restart hosta, wykonujemy go w uzgodnionym oknie i ponownie sprawdzamy usługi. Przerwanie playbooka ani zamknięcie sesji nie cofa zainstalowanych pakietów; odtworzenie systemu lub konfiguracji wymaga przygotowanej wcześniej procedury.
Krok 6. Zamykamy sesję i przechodzimy do backup02
Po zakończeniu testów zamykamy dostęp do pierwszego hosta i otwieramy nową sesję do drugiego. Przy nowym połączeniu ponownie spełniamy wymagania PIN-u i dotyku:
ssh -F /dev/null -p 22 \
-S "$BACKUP_CONTROL_DIR/%h-%p-%r" \
-O exit admin-a@backup01.example.net
open_backup_ssh backup02.example.net
ansible -i inventory.yml backup_servers --limit backup02 \
-m ansible.builtin.ping -f 1
ansible-playbook -i inventory.yml update-backup-os.yml \
--limit backup02 --check --diff --ask-become-pass
Po osobnym przejrzeniu zmian i potwierdzeniu gotowości drugiego serwera wykonujemy:
ansible-playbook -i inventory.yml update-backup-os.yml \
--limit backup02 --ask-become-pass \
-e '{"backup_maintenance_confirmed": true}'
Powtarzamy testy usług i odtwarzania. Gdy nie ma już działających zadań, zamykamy drugą sesję i usuwamy pusty katalog socketów:
ssh -F /dev/null -p 22 \
-S "$BACKUP_CONTROL_DIR/%h-%p-%r" \
-O exit admin-a@backup02.example.net
rmdir "$BACKUP_CONTROL_DIR"
unset BACKUP_CONTROL_DIR
unset -f open_backup_ssh
rmdir usunie tylko pusty katalog. Jeśli socket nadal istnieje, wyjaśniamy przyczynę zamiast usuwać go rekurencyjnie. Użycie --limit daje rzeczywistą przerwę na ocenę pierwszego hosta. Samo serial: 1 po zakończeniu zadań od razu przeszłoby do następnego. Ansible: wykonanie partiami.
Co dokładnie zabezpiecza YubiKey w tym przykładzie
YubiKey zatwierdza nowe uwierzytelnienie SSH, nie każdy task ani zawartość playbooka. Kolejne zadania korzystają z otwartego mastera. Wyjęcie urządzenia nie zatrzyma aktualizacji, a inny proces działający jako ten sam lokalny użytkownik może wykorzystać socket. Dlatego używamy prywatnego katalogu, chronimy laptop i jawnie zamykamy połączenia po pracy.
Jeżeli sesja wygaśnie lub serwer zostanie zrestartowany, Ansible zgłosi błąd połączenia. Najpierw sprawdzamy stan serwera i to, które zadania już wykonano. Potem świadomie otwieramy nową sesję przez open_backup_ssh i decydujemy o powtórzeniu zadania. Nie usuwamy ProxyCommand=false, żeby ukryć błąd, i nie zapisujemy PIN-u w inventory. Jest to procedura dla administratora obecnego przy laptopie, nie dla nocnego zadania cron.
Automatyzacja bez człowieka potrzebuje innej tożsamości
AWX, CI i cron uruchamiają zadania, gdy administratora nie ma przy komputerze. Nie mogą wtedy podać PIN-u ani dotknąć osobistego YubiKey. Nie rozwiązujemy tego przez wyłączenie PIN-u lub dotyku w kluczu administratora.
Automat dostaje własne konto techniczne, własny klucz lub certyfikat SSH, możliwie mały zakres uprawnień oraz rejestrowanie użycia. Przykładowo job tworzący kopię zapasową może logować się wyłącznie na konto backup, uruchamiać jeden określony program i nie mieć dostępu do sudo. Klucz administratora pozostaje dla pracy wykonywanej przez człowieka.
W większych środowiskach można użyć krótkotrwałych certyfikatów SSH, ale nie są one pierwszym krokiem tej instrukcji. Krótszy czas ważności nie zamyka już zestawionej sesji ani nie cofa wykonanego polecenia. Nadal chronimy kontroler automatyzacji, jego pliki kluczy i uprawnienia na serwerach.
YubiKey w banku i panelu OVHcloud
Każdą usługę WWW rejestrujemy osobno. Przeglądarka i YubiKey tworzą nowe poświadczenie dla RP ID tej usługi; wdrożenie klucza SSH w authorized_keys nie bierze udziału w tym procesie.
Gdy strona prosi o klucz bezpieczeństwa, podłączamy lub przykładamy YubiKey dopiero po wyświetleniu monitu przeglądarki. Nazwy w przeglądarkach bywają różne. Ważne jest, aby monity dotyczyły zewnętrznego fizycznego klucza, a nie już zapisanego sposobu logowania na komputerze lub telefonie. Przed zmianą zostawiamy działającą metodę odzyskania dostępu.
Przykład: dodajemy YubiKey do panelu i logujemy się ponownie
Załóżmy, że przykładowy panel https://portal.example.net obsługuje FIDO2. Jesteśmy już zalogowani na konto administratora i wybieramy dodanie klucza bezpieczeństwa. To rejestracja nowej metody dostępu, a nie kopiowanie klucza SSH do przeglądarki.
- Rejestrujemy klucz. Panel przez WebAuthn zleca utworzenie poświadczenia dla konta i RP ID
portal.example.net. Wybieramy podłączony YubiKey i wykonujemy wymagane potwierdzenie. YubiKey tworzy nową parę kluczy. Panel otrzymuje i zapisuje klucz publiczny oraz identyfikator poświadczenia, ale nie otrzymuje klucza prywatnego. - Rozpoczynamy nowe logowanie. Panel generuje challenge, czyli losowe dane dla tej konkretnej próby. Przekazuje je przeglądarce razem z informacją, którego poświadczenia może użyć. Podpis z poprzedniego logowania nie będzie pasował do nowego challenge.
- Przeglądarka sprawdza domenę i kontaktuje się z YubiKey. Po sprawdzeniu RP ID komputer przekazuje przez CTAP2 dane potrzebne do podpisu. Jeśli konfiguracja wymaga PIN-u, wpisujemy go w oknie systemu lub przeglądarki, a YubiKey go weryfikuje. Dotykamy czujnika urządzenia, aby potwierdzić fizyczną obecność przy kluczu.
- YubiKey wykonuje podpis. Podpis obejmuje dane authenticatora, m.in. skrót RP ID i flagi UP/UV, oraz skrót danych przeglądarki zawierających challenge i origin. Origin określa pochodzenie strony przez protokół, host i port; w tym przykładzie to
https://portal.example.net. Nie podpisujemy odcisku palca ani samego PIN-u. - Panel sprawdza odpowiedź. Przeglądarka odsyła podpis i dane tej próby. Panel sprawdza challenge, origin, RP ID, wymagane flagi oraz podpis przy użyciu zapisanego klucza publicznego. Po poprawnej weryfikacji uznaje ten etap logowania za zakończony.
Fałszywa strona na innej, nieuprawnionej domenie nie może w zgodnej przeglądarce użyć poświadczenia naszego panelu. To istotna różnica względem kodu, który użytkownik może przepisać na stronę phishingową. Przebieg opisują specyfikacja WebAuthn oraz dokumentacja uwierzytelniania Yubico.
Bezpieczny schemat dla każdej strony WWW
- Otwieramy serwis przez własną zakładkę albo wpisany adres, nie przez link z wiadomości.
- Logujemy się obecną, działającą metodą.
- W ustawieniach bezpieczeństwa wybieramy dodanie klucza bezpieczeństwa i postępujemy zgodnie z komunikatami przeglądarki.
- W nowym oknie lub prywatnej sesji sprawdzamy logowanie pierwszym YubiKey.
- Dopiero po tym dodajemy drugi klucz. Nie usuwamy poprzedniej metody, dopóki nie przetestujemy odzyskania dostępu.
Klucza S nie rejestrujemy automatycznie w każdym banku ani panelu. W szczególności wspólny klucz zespołowy może być niedozwolony lub niepraktyczny dla konta osobistego. Rejestrujemy go tylko tam, gdzie pozwala na to właściciel konta i opisana procedura odzyskania dostępu.
Co ustawienie PIN-u zmienia w kluczu dodanym wcześniej do OVHcloud lub banku
Ustawienie ani zmiana PIN-u nie kasują istniejących poświadczeń. YubiKey dodany wcześniej bez PIN-u do OVHcloud albo banku działa dalej. Manual YubiKey 5 mówi wprost: „Changing the FIDO2 PIN will not invalidate any credentials on the YubiKey”.
Zmienić się może tylko sposób potwierdzania logowania. Serwis WebAuthn sam określa, czy chce weryfikacji użytkownika. Przy wartości preferred przeglądarka po ustawieniu PIN-u zacznie o niego pytać, a przy discouraged zostanie sam dotyk. Rejestracje w starszym protokole U2F w ogóle nie używają PIN-u FIDO2. Po ustawieniu PIN-u logujemy się raz do każdego serwisu i sprawdzamy, czego wymaga.
Ryzyko jest gdzie indziej. Po trzech błędnych próbach PIN-u z rzędu YubiKey trzeba wyjąć i włożyć ponownie, a osiem błędnych prób z rzędu blokuje aplikację FIDO2. Jedynym wyjściem jest wtedy reset FIDO, który kasuje wszystkie poświadczenia FIDO2 i U2F, także rejestracje w OVHcloud i bankach, oraz usuwa PIN. Dlatego zanim zaczniemy używać PIN-u, kody zapasowe OVHcloud i dostęp awaryjny do banków przechowujemy poza komputerem.
Klucz bezpieczeństwa w ING Bank Śląski (Moje ING)
Instrukcja ING wskazuje Ustawienia → Bezpieczeństwo → Klucze zabezpieczeń U2F. Pierwszy klucz wymaga również aktywacji: bank opisuje ścieżkę w Moim ING z użyciem mObywatela lub karty NFC oraz możliwość aktywacji w placówce. Dopiero po zakończeniu wymaganych etapów testujemy nowe logowanie i dodajemy zapas. Bank rozdziela rejestrację dla przeglądarki i aplikacji mobilnej, więc sprawdzamy oba kanały. Mimo nazwy funkcji bank wymaga klucza zgodnego z FIDO2. W ustawieniach wybieramy, czy klucz zatwierdza tylko logowanie, czy także transakcje. Bank pozwala dodać dowolną liczbę kluczy i zaleca co najmniej dwa.
Klucz bezpieczeństwa w serwisie internetowym PKO Bank Polski
W PKO BP ścieżka prowadzi przez Ustawienia → Dostęp i bezpieczeństwo → Klucze bezpieczeństwa. Dodajemy pierwszy klucz, sprawdzamy nowe logowanie, a następnie rejestrujemy zapas. Według dokumentacji banku klucz zabezpiecza logowanie; transakcje nadal autoryzujemy dotychczasową metodą.
Klucz bezpieczeństwa w panelu OVHcloud
W panelu OVHcloud klikamy nazwę konta w prawym górnym rogu i przechodzimy do Dostęp do konta → Bezpieczeństwo, a następnie wybieramy Włącz weryfikację dwuetapową i klucz bezpieczeństwa. Przy pierwszej konfiguracji OVHcloud wyświetla 10 jednorazowych kodów zapasowych. Zapisujemy je poza zwykle odblokowanym komputerem i sprawdzamy dostęp zapasowy. Klucz jest drugim składnikiem: panel nadal pyta o login i hasło. Ścieżkę opisuje dokumentacja OVHcloud (stan na 1 października 2026 r.).
Dodanie YubiKey do strony WWW nie zabezpiecza automatycznie aktywnych sesji, tokenów API ani kluczy SSH. Każdy z tych kanałów przeglądamy osobno.
macOS, Touch ID i iPhone - czym różnią się od YubiKey
Touch ID sprawdza odcisk palca lokalnie na Macu i pozwala zatwierdzić użycie klucza prywatnego. Odcisk nie trafia do serwisu i nie zastępuje podpisu kryptograficznego. Przy logowaniu WWW tę operację może wykonać mechanizm macOS zamiast osobnego YubiKey. Trzeba jednak najpierw zarejestrować w usłudze odpowiednie poświadczenie - samo włączenie Touch ID nie daje dostępu do żadnego panelu.
Przykład: do tego samego panelu logujemy się za pomocą Touch ID
Wróćmy do konta w portal.example.net. Tym razem dodajemy passkey, czyli poświadczenie FIDO pozwalające logować się bez hasła. W oknie przeglądarki wybieramy zapis w iCloud Keychain, a nie podłączony klucz bezpieczeństwa.
- Mac tworzy osobne poświadczenie dla panelu. System generuje parę kluczy, a panel zapisuje klucz publiczny i identyfikator. To nowa metoda logowania do tego samego konta, nie kopia poświadczenia z YubiKey.
- Przy kolejnym logowaniu panel przesyła nowy challenge. Przeglądarka przekazuje żądanie do mechanizmu obsługi passkeys w macOS. System wyświetla prośbę o Touch ID, a my przykładamy palec do czytnika Maca.
- Po poprawnej weryfikacji system używa klucza prywatnego. Powstaje podpis danych tej próby logowania, zgodnie z opisanym wcześniej WebAuthn. Panel dostaje podpis i dane do sprawdzenia, w tym informację o wykonaniu weryfikacji użytkownika. Nie otrzymuje odcisku palca ani klucza prywatnego.
W tym wariancie iCloud Keychain synchronizuje passkey między naszymi zatwierdzonymi urządzeniami Apple, używając szyfrowania end-to-end. Możemy więc zalogować się również na innym własnym urządzeniu z dostępnym passkey. Nie przenosimy czytnika Touch ID; drugie urządzenie wykonuje własną lokalną weryfikację użytkownika. Rejestrację, synchronizację i odzyskiwanie opisuje Apple: bezpieczeństwo passkeys.
| Właściwość | Passkey w iCloud Keychain i Touch ID | Poświadczenie FIDO na YubiKey |
|---|---|---|
| Co potwierdzamy fizycznie | Przykładamy palec do Touch ID Maca, aby system dopuścił użycie passkey. | Dotykamy czujnika podłączonego YubiKey. Jeśli wymagane jest UV, urządzenie sprawdza także PIN FIDO2 albo biometrię w modelu Bio. |
| Użycie na innym komputerze | Na własnym urządzeniu możemy użyć zsynchronizowanego passkey. Dostęp zależy od konfiguracji iCloud Keychain i obsługi passkeys. | Przenosimy fizyczny YubiKey do zgodnego komputera. Dla SSH potrzebny jest też lokalny plik OpenSSH albo możliwość pobrania poświadczenia rezydentnego. |
| Utrata urządzenia | Zsynchronizowany passkey może pozostać dostępny na innym urządzeniu. Istotna jest też procedura odzyskiwania iCloud Keychain. | Potrzebny jest niezależnie zarejestrowany klucz zapasowy lub procedura odzyskiwania usługi. Nie odtwarzamy prywatnego klucza FIDO na innym YubiKey. |
Do czego służy Secure Enclave i co zmienia w SSH
Secure Enclave to odizolowany sprzętowo podsystem bezpieczeństwa Apple, oddzielony od głównego procesora i systemu operacyjnego. Uczestniczy m.in. w sprawdzaniu Touch ID. Aplikacja może również wygenerować w nim obsługiwany klucz prywatny, np. P-256, i zlecać podpisy bez odczytywania tego klucza. Taki klucz jest związany z konkretnym urządzeniem. Nie należy go utożsamiać z opisanym wyżej passkey synchronizowanym przez iCloud Keychain. Te dwa przypadki opisują dokumentacja Secure Enclave i instrukcja Apple dotycząca ochrony kluczy.
Przykładowo, mamy na Macu zwykły plik ~/.ssh/id_ed25519. Zapisanie jego passphrase w Keychain pozwala zgodnemu klientowi SSH pobrać ją bez ponownego wpisywania. Nadal jest to jednak klucz prywatny w pliku. Samo użycie Touch ID nie przenosi go do Secure Enclave ani na YubiKey i nie zmienia go w klucz -sk. SSH korzystające z Secure Enclave wymaga osobnego, obsługującego je oprogramowania i zgodnego typu klucza.
W opisanej procedurze SSH z YubiKey używamy OpenSSH z Homebrew (zob. przygotowanie klienta na macOS). Ten klient nie obsługuje opcji Apple UseKeychain: formuła Homebrew celowo nie zawiera tej łatki. Odczyt passphrase z Keychain i podpis YubiKey z PIN-em FIDO2 to zresztą niezależne operacje.
iPhone
Na iPhonie YubiKey służy przede wszystkim do logowania w stronach i aplikacjach, które obsługują klucze bezpieczeństwa WebAuthn. Zgodność przez USB-C lub NFC (Near Field Communication) zależy od modelu telefonu, YubiKey, przeglądarki i danej aplikacji. Udane logowanie w Safari nie dowodzi, że aplikacja bankowa albo klient SSH obsługuje tę samą drogę.
iPhone nie zastępuje opisanej wcześniej stacji Linux lub macOS do generowania klucza ed25519-sk i administracji SSH. Informacje o zgodnych kluczach dla konta Apple publikuje Apple, a informacje o połączeniach USB i NFC - Yubico.
Utrata klucza i odzyskanie dostępu
Gdy zaginie klucz A, najpierw używamy przetestowanego klucza B po uzgodnionym przekazaniu albo klucza S zgodnie z procedurą sejfu. Następnie odbieramy uprawnienia po stronie serwerów i usług. Usunięcie poświadczenia lub reset później odzyskanego YubiKey nie usuwa jego kluczy publicznych z authorized_keys ani rejestracji w usługach WWW.
Pliki YubiKey i SSH, które muszą trafić do kopii zapasowej
Ustawienie PIN-u nie tworzy plików. Pliki powstają dopiero przy ssh-keygen:
| Plik lub dane | Czy do kopii zapasowej |
|---|---|
Plik klucza nierezydentnego, np. id_ed25519_sk_admin_a_on_key_a utworzony bez -O resident | Tak, obowiązkowo. Bez niego tego klucza nie użyjemy nawet z YubiKey. |
Plik klucza rezydentnego (-O resident) | Tak, dla wygody. Odtworzymy go też z tego samego YubiKey przez ssh-keygen -K po podaniu PIN-u. |
Pliki .pub | Tak, do ewidencji kluczy i do authorized_keys. |
| Kody zapasowe OVHcloud i kody odzyskiwania innych serwisów | Tak, poza komputerem i oddzielnie od YubiKey. |
Pliki kluczy są bezużyteczne bez fizycznego YubiKey. Przed utratą urządzenia chroni tylko drugi YubiKey z własnym, osobno zarejestrowanym kluczem. PIN-u ani passphrase nie zapisujemy w kopii zapasowej obok plików kluczy.
Wycofujemy wszystkie wpisy utraconego urządzenia
Przy utracie fizycznego YubiKey wycofujemy wszystkie klucze SSH, które utworzyliśmy na tym urządzeniu, na każdym właściwym koncie i serwerze. W modelu A/B/S oznacza to: dla A - admin-a-key-a i admin-b-key-a; dla B - admin-b-key-b i admin-a-key-b; dla S - breakglass-key-s. Prywatna ewidencja powinna łączyć każdy komentarz z właścicielem urządzenia, kontem docelowym i odciskiem klucza publicznego.
Najpierw logujemy się drugą, działającą drogą, porównujemy te dane z ewidencją i sprawdzamy, czy komentarz występuje tylko przy właściwym kluczu. Poniższy przykład pokazuje usunięcie jednego wpisu z utraconego klucza A:
grep -n 'admin-a-key-a$' ~/.ssh/authorized_keys
Po porównaniu komentarza i fingerprintu z ewidencją tworzymy kopię pliku, a następnie usuwamy całą linię zweryfikowanego klucza. Usunięcie samego komentarza nie odebrałoby dostępu. Polecenia dotyczą GNU sed na właściwym koncie serwera:
cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.before-yubikey-a-removal
sed -i '/[[:space:]]admin-a-key-a$/d' ~/.ssh/authorized_keys
grep -n 'admin-a-key-a$' ~/.ssh/authorized_keys
Ostatnie polecenie nie powinno już zwrócić linii. Powtarzamy tę operację dla pozostałych komentarzy przypisanych do utraconego urządzenia, na właściwych kontach i hostach. Następnie w nowym terminalu wykonujemy rygorystyczny test logowania kluczem B, a gdy procedura tego wymaga - także kluczem S. Jeżeli usunięto niewłaściwy wpis, wciąż w otwartej sesji awaryjnej przywracamy kopię:
cp ~/.ssh/authorized_keys.before-yubikey-a-removal ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Jeżeli plik authorized_keys jest zarządzany przez Ansible, wycofanie wykonujemy w źródle automatyzacji i uruchamiamy playbook, zamiast ręcznie zmieniać jeden serwer.
Wycofujemy dostęp w pozostałych miejscach
- Usuwamy utracony YubiKey z banku, panelu OVHcloud i innych stron zgodnie z ich aktualną procedurą.
- Przeglądamy aktywne sesje WWW, tokeny API, konta odzyskiwania i wpisy na bastionach.
- Na nowym YubiKey generujemy nowe klucze SSH, wdrażamy ich klucze publiczne i ponownie rejestrujemy urządzenie w usługach WWW. Testujemy je przed wycofaniem dostępu awaryjnego.
- Odnotowujemy zdarzenie w prywatnej ewidencji. Nie umieszczamy w publicznej dokumentacji numeru seryjnego, PIN-u, kodów odzyskiwania, pełnych kluczy publicznych ani szczegółowych logów.
Jak odtworzyć lokalne pliki z poświadczenia rezydentnego
Po utracie komputera można odtworzyć lokalne pliki dla poświadczeń rezydentnych z zachowanego YubiKey. Na nowej, zaufanej stacji podłączamy tylko właściwe urządzenie i tworzymy pusty katalog roboczy:
umask 077
recovery_dir=$(mktemp -d "$HOME/recovered-yubikey.XXXXXX")
cd "$recovery_dir" && ssh-keygen -K
ssh-keygen -K pobiera dane poświadczeń rezydentnych i zapisuje lokalne pliki OpenSSH oraz odpowiadające im klucze publiczne. Nie eksportuje kluczy prywatnych umożliwiających podpisywanie poza urządzeniem. Porównujemy fingerprinty z ewidencją, przenosimy właściwe pliki do docelowych ścieżek i wykonujemy test SSH. Dla pliku pobranego bez passphrase można ustawić ją przez ssh-keygen -p -f ścieżka_do_pliku. Pobrane pliki zachowują wymóg PIN-u, bo ssh-keygen -K odczytuje go z poświadczenia. Poświadczenia nierezydentnego nie odzyskamy przez -K; potrzebna jest zachowana kopia lokalnego pliku.
Checklista przed zmianą produkcyjną
- Wiemy, na którym komputerze uruchamiamy polecenia, a na którym serwerze dodajemy klucz publiczny.
- Mamy działającą sesję awaryjną, konsolę lub inny sposób odzyskania dostępu.
- Każdy klucz SSH utworzony na YubiKey ma własny komentarz, własny plik
.pubi osobny pozytywny test SSH. Prywatna ewidencja wiąże komentarz z urządzeniem, kontem docelowym i odciskiem klucza. - Klucze A, B i S są przechowywane w trzech różnych miejscach; klucz S został sprawdzony przed zaplombowaniem.
- Administratorzy używają osobnych kont SSH. Wspólne konto awaryjne ma opisaną procedurę użycia.
- Nowe ręczne SSH wymaga YubiKey. Ansible korzysta z przygotowanego mastera i nie nawiązuje nowego połączenia po jego zamknięciu. Sprawdziliśmy zakres grupy backupowej, dostęp sudo i test odtworzenia po aktualizacji. Automaty mają własną, ograniczoną tożsamość.
- Bank, OVHcloud, przeglądarka i aplikacja mobilna zostały sprawdzone osobno. Klucz SSH nie był mylony z poświadczeniem WebAuthn.
- Nie publikujemy sekretów, identyfikatorów infrastruktury ani wyników szczegółowych logów.
Źródła
Podstawowa procedura SSH: Yubico: SSH z FIDO2, OpenSSH: ssh-keygen oraz OpenSSH: sshd. Konfiguracja Ansible: Ansible: połączenie SSH i Ansible: aktualizacja pakietów apt. Pojęcia WebAuthn: W3C WebAuthn. Ustawienia usług: ING, PKO BP, OVHcloud i Apple.
Zobacz też