← Blog
Bezpieczeństwo13 min czytania

step CLI — automatyzacja PKI i certyfikatów wewnętrznych

Wygasły certyfikat to klasyczna awaria, której nikt nie przewidział, bo wszystko działało do wczoraj. step CLI zamienia obsługę certyfikatów w polecenia, które da się wpisać do skryptu — a jego polecenie sprawdzające ma zaskakująco odwrócone kody wyjścia.

Jest taka kategoria awarii, która różni się od wszystkich innych: nikt niczego nie wdrażał, nikt nie ruszał konfiguracji, a usługa przestała działać. Wygasł certyfikat.

Publiczne certyfikaty TLS mamy dziś w większości zautomatyzowane — Let's Encrypt i protokół ACME załatwiły to za nas. Kłopot zaczyna się wewnątrz: przy połączeniach między usługami, przy bazie danych wymagającej TLS, przy ruchu w klastrze, przy urządzeniach w sieci firmowej. Tam publiczne urzędy certyfikacji nie pomogą, bo nazwy nie są publiczne. Zostaje własna infrastruktura klucza publicznego — a ta w wielu firmach oznacza katalog z plikami, jednego kolegę, który wie, jak to zrobić, i skrypt z openssl, którego nikt nie chce dotykać.

step jest narzędziem wiersza poleceń, które ten obszar porządkuje.

Czym to jest, a czym nie jest

Projekt Smallstep składa się z dwóch osobnych repozytoriów i warto od razu wiedzieć, które jest które.

smallstep/cli to polecenie step — narzędzie klienckie i zestaw narzędzi kryptograficznych. Sam opis mówi o „szwajcarskim nożu zerowego zaufania do pracy z X.509, OAuth, JWT i OATH OTP".

smallstep/certificates to step-ca — serwer, czyli prywatny urząd certyfikacji z wbudowanym serwerem ACME.

Rzecz istotna dla oceny wdrożenia: step jest użyteczny bez serwera. Dużą część jego poleceń — oglądanie certyfikatów, sprawdzanie ich poprawności, generowanie kluczy, podpisywanie tokenów, kody jednorazowe — wykonasz na własnej maszynie, nie uruchamiając niczego. Można więc wejść w to narzędzie stopniowo: najpierw jako lepszy zamiennik openssl w skryptach, dopiero potem jako klient własnego urzędu certyfikacji.

Stan projektu

step ma 4326 gwiazdek, 317 forków i istnieje od lipca 2018 — to jedna z dojrzalszych pozycji w tej serii. step-ca jest jeszcze popularniejszy: 8855 gwiazdek, 590 forków. Oba na licencji Apache 2.0, oba w Go, oba z commitami z ostatnich dni.

Tu jednak potrzebna jest uczciwa uwaga, bo sama liczba commitów potrafi wprowadzić w błąd. Przejrzałem historię gałęzi domyślnej step od początku 2026 roku: na sto commitów tylko dwanaście nie było automatycznym podbiciem zależności, a z tych dwunastu większość dotyczyła procesu wydawniczego i konfiguracji analizatora kodu. Prawdziwych poprawek było kilka, w tym jedna dobra — zawieszanie się step ssh proxycommand, gdy serwer zamykał połączenie przed zamknięciem strumienia wejściowego. Ostatnie stabilne wydanie klienta, v0.30.6, jest z czerwca 2026.

Klient jest więc w trybie utrzymaniowym, a nie porzucony — i to rozróżnienie jest tu kluczowe. Zależności są podbijane co tydzień, zgłoszenia są przyjmowane, a narzędzie o takim zakresie po siedmiu latach po prostu ma już to, co ma mieć. Serwer wygląda inaczej: w step-ca od maja 2026 znalazłem 27 commitów niebędących podbiciem zależności, z realną pracą nad poświadczaniem tożsamości urządzeń z Androida, listami odwołań i usuwaniem przestarzałych właściwości biblioteki TLS. Praca idzie tam, gdzie dzieje się rozwój protokołów.

Otwartych zgłoszeń jest odpowiednio 197 i 296. Przy projekcie ośmioletnim o takim zasięgu to liczba do przyjęcia, ale nie jest to projekt z pustą kolejką.

Pięć grup poleceń

Zakres najlepiej widać po podziale na grupy — i to jest ten moment, w którym widać, że nazwa „szwajcarski nóż" nie jest przesadą:

  • step certificate — tworzenie, podpisywanie, oglądanie, sprawdzanie i pakowanie certyfikatów X.509; instalowanie certyfikatu głównego w magazynie zaufania systemu i przeglądarki.
  • step ca — obsługa własnego step-ca albo dowolnego serwera zgodnego z ACME: pobieranie, odnawianie, przekluczanie i odwoływanie certyfikatów.
  • step crypto — ogólny zestaw kryptograficzny: JWT, JWS, JWE, JWK, kody jednorazowe TOTP, funkcje wyprowadzania klucza (scrypt, bcrypt, argon2), skróty plików, narzędzia z rodziny NaCl.
  • step oauth — pełny przepływ jednokrotnego logowania OAuth 2.0 z wiersza poleceń, w tym przepływ urządzenia i tokeny odświeżające.
  • step ssh — certyfikaty SSH dla ludzi i dla maszyn, zamiast plików z listą kluczy.

Do tego drobnica, która okazuje się przydatna częściej, niż się spodziewałem: step crl inspect do oglądania list odwołań, step context do przełączania się między kilkoma urzędami certyfikacji na jednej maszynie oraz step fileserver — mały serwer plików, w praktyce do obsługi wyzwania ACME typu http-01.

Odwrócone kody wyjścia, czyli detal, który zepsuje ci skrypt

To jest miejsce, w którym trzeba czytać dokumentację, a nie zgadywać — i najważniejsza rzecz, jaką znalazłem, przeglądając kod tego narzędzia.

Polecenie step certificate needs-renewal sprawdza, czy certyfikat wymaga odnowienia. Domyślnie uznaje, że wymaga, gdy minęło 66% jego okresu ważności — progiem sterujesz flagą --expires-in, przyjmującą albo czas trwania (--expires-in 1h15m), albo procent (--expires-in 75%). Ustawienie --expires-in 0s sprowadza pytanie do „czy już wygasł".

Do tego działa nie tylko na plikach, ale i na zdalnych usługach — możesz podać wprost adres z protokołem, więc jednym poleceniem sprawdzisz cudzy certyfikat bez pobierania go na dysk. Z flagą --bundle sprawdza cały łańcuch, nie tylko certyfikat końcowy, a z --roots zweryfikuje go względem twojego własnego certyfikatu głównego.

A teraz rzecz zaskakująca. Cytuję opis polecenia: zwraca 0, jeżeli certyfikat wymaga odnowienia, i 1, jeżeli mieści się w granicach ważności i odnowienia nie wymaga. Do tego 2, gdy plik nie istnieje, i 255 przy każdym innym błędzie.

To jest odwrotnie, niż podpowiada odruch. W powłoce zero znaczy „w porządku", więc naturalne if step certificate needs-renewal cert.crt; then … zadziała dokładnie na opak, a jego autor tego nie zauważy — bo skrypt będzie milczał tak długo, aż certyfikat naprawdę zacznie wygasać. Logika jest przy tym spójna: polecenie odpowiada „tak" na pytanie zawarte w nazwie, a „tak" w powłoce to zero. Trzeba tylko o tym wiedzieć. I trzeba oddzielić 2 oraz 255 od pozostałych, bo brakujący plik albo błąd sieci to nie to samo co „nie wymaga odnowienia".

Odnawianie jako usługa systemowa

Sprawdzanie to jedno, odnawianie to drugie. Polecenie step ca renew ma tryb demona i zestaw flag, które wprost celują w utrzymanie produkcyjne.

Flaga --daemon uruchamia je jako proces stale odnawiający certyfikat; --renew-period i --expires-in ustalają, kiedy to robić. Najciekawsze są jednak trzy pozostałe: --exec uruchamia polecenie po każdym udanym odnowieniu, a --pid oraz --pid-file wysyłają sygnał wskazanemu procesowi, żeby wczytał nowy certyfikat.

To jest cała ta część problemu, którą zwykle się odkłada. Odnowienie pliku na dysku nie kończy sprawy — serwer trzyma stary certyfikat w pamięci, dopóki go nie przeładujesz. Wbudowanie przeładowania w to samo polecenie oznacza, że nie musisz pisać do tego własnej obudowy ani zadania w harmonogramie, które czasem się rozjedzie.

Serwer: skąd bierze się zaufanie

Jeżeli dojdziesz do step-ca, najciekawszą jego częścią jest lista sposobów, w jakie można uwierzytelnić żądanie o certyfikat. Bo pytanie „jak maszyna ma dowieść, że jest tą, za którą się podaje, jeszcze przed otrzymaniem certyfikatu" jest sednem całego zagadnienia.

step-ca wystawia certyfikat w wymianie za: odpowiedź na wyzwanie ACME, token jednokrotnego logowania OAuth OIDC (Okta, Azure AD, Auth0, ale też własny Keycloak czy Dex), dokument tożsamości instancji chmurowej na AWS, GCP i Azure, jednorazowy krótkotrwały token wystawiony przez twoje narzędzie wdrożeniowe, zaufany certyfikat X.509, certyfikat hosta z sieci Nebula, wyzwanie SCEP albo wygasający certyfikat hosta SSH.

Wariant chmurowy jest tu najelegantszy: maszyna wirtualna dowodzi swojej tożsamości dokumentem podpisanym przez dostawcę chmury, więc nie musisz na nią wcześniej wkładać żadnego sekretu. Problem pierwszego zaufania rozwiązuje infrastruktura, na której i tak polegasz.

Sprawdziłem też, co w kodzie serwera jest naprawdę: w acme/challenge.go zdefiniowany jest typ wyzwania device-attest-01, a obok niego zaciągnięte biblioteki do poświadczania tożsamości urządzeń z Androida i modułów TPM. Poświadczanie sprzętowe jest więc w kodzie otwartym, nie za progiem płatnym. Jako zaplecze bazy danych działa Badger, BoltDB, PostgreSQL albo MySQL.

Gdzie przebiega granica open core

I teraz część, której nie da się pominąć, a którą — trzeba to Smallstepowi oddać — sami opisali w pliku README, zamiast pozwolić ci odkryć ją po wdrożeniu.

step-ca jest, cytując, zoptymalizowany pod dwupoziomową infrastrukturę klucza publicznego dla typowych zastosowań DevOps. Po stronie produktu płatnego wymieniono między innymi: wiele urzędów certyfikacji, aktywne odwoływanie certyfikatów przez CRL i OCSP, gotową wysoką dostępność, API do zarządzania infrastrukturą jako kodem, zintegrowane wsparcie SCEP i NDES do migracji z usług certyfikatów Active Directory, ewidencję i poświadczanie urządzeń, wiązanie konta zewnętrznego w ACME, panel administracyjny w przeglądarce, kontrolę dostępu opartą na rolach, zgodność z FIPS oraz klucze prywatne zamknięte w sprzętowym module bezpieczeństwa.

Dwie pozycje z tej listy wymagają jednak sprostowania, bo brzmią surowiej, niż wynika z kodu. Obsługa modułów HSM przez PKCS#11 jest w kodzie otwartym — biblioteka kryptograficzna Smallstepu, również na Apache 2.0, zawiera warstwy dla PKCS#11, TPM 2.0, YubiKeya, magazynu kluczy macOS, interfejsu Windows oraz usług kluczy AWS, Azure i Google Cloud. Podobnie dostawca SCEP jest w wersji otwartej; płatne jest zintegrowane wsparcie NDES i ścieżka migracji z Active Directory. Za progiem płatnym leży więc raczej warstwa zarządzania, ewidencji i gwarancji niż same podstawowe mechanizmy.

Najpoważniejszym praktycznym ograniczeniem wersji otwartej jest brak aktywnego odwoływania. Model Smallstepu opiera się na odwoływaniu biernym: certyfikaty są krótkotrwałe, więc wycofanie zaufania polega na zaprzestaniu odnawiania. To rozwiązanie spójne i w wielu scenariuszach lepsze od list odwołań, których nikt nie sprawdza — ale jeśli twój audyt wymaga OCSP, musisz to wiedzieć przed, nie po.

Pułapka, o której nie mówi komunikat instalatora

Skoro PKCS#11 jest w kodzie otwartym, dorzucam rzecz, którą znalazłem w źródłach, a która potrafi zająć pół dnia. Warstwa PKCS#11 jest kompilowana warunkowo — wymaga włączonego cgo. Jeśli używasz gotowego pliku wykonywalnego zbudowanego bez cgo, obsługi modułu HSM w nim nie ma, a jedyne, co zobaczysz, to komunikat o nieobsługiwanym typie mówiący, że program został skompilowany bez cgo lub bez wsparcia PKCS#11.

Komunikat jest uczciwy i wprost nazywa przyczynę — ale pojawia się dopiero przy próbie użycia, a nie przy instalacji. Jeżeli planujesz trzymać klucz urzędu certyfikacji w sprzęcie, zaplanuj budowanie z źródeł i sprawdź to przed zaprojektowaniem procedury.

Kryptografia postkwantowa i podpisane wydania

Dwie rzeczy, które w 2026 roku dobrze świadczą o narzędziu z tej kategorii.

Pierwsza: dziennik zmian wersji 0.30.3 odnotowuje dodanie obsługi oglądania certyfikatów z algorytmami postkwantowymi ML-DSA i SLH-DSA. Zanim zaczniesz ich wystawiać, przydaje się narzędzie, które potrafi je choćby przeczytać — i tu już jest.

Druga: sprawdziłem, co dokładnie leży w wydaniu v0.30.6. Są tam pakiety .deb i .rpm na kilkanaście architektur, od amd64 i arm64 po ppc64le i mips, a przy każdym pliku — łącznie z plikiem sum kontrolnych — leży osobne poświadczenie Sigstore. W repozytorium serwera jest dodatkowo klucz publiczny cosign. Przy narzędziu, które ma stać się korzeniem zaufania w twojej sieci, weryfikowalny łańcuch dostawy nie jest ozdobą, a warunkiem sensu całej operacji.

Pułapki w jednym miejscu

  • Kody wyjścia needs-renewal są odwrócone — 0 znaczy „wymaga odnowienia", 1 znaczy „nie wymaga". Obsłuż też 2 (brak pliku) i 255 (inny błąd).
  • Obsługa HSM przez PKCS#11 wymaga cgo; gotowe pliki wykonywalne mogą jej nie mieć. Sprawdź przed projektowaniem procedury.
  • W wersji otwartej nie ma aktywnego odwoływania (CRL, OCSP). Model opiera się na krótkich certyfikatach i biernym wycofywaniu zaufania.
  • Jeden urząd certyfikacji, dwa poziomy. Bardziej rozbudowana hierarchia to już produkt płatny.
  • Odnowienie pliku to nie przeładowanie usługi. Użyj --exec, --pid albo --pid-file, bo inaczej serwer zostanie ze starym certyfikatem w pamięci.
  • step certificate install zmienia magazyn zaufania systemu. To operacja o dużych konsekwencjach — od tej chwili maszyna ufa wszystkiemu, co podpisze twój urząd.
  • Klucz certyfikatu głównego jest najcenniejszym sekretem, jaki będziesz mieć. Kto go wykradnie, może podszyć się pod dowolną domenę wobec każdej maszyny, która zainstalowała twój korzeń — a przy ruchu wewnętrznym niosącym dane osobowe oznacza to nie tylko incydent techniczny, ale i obowiązki wynikające z RODO. Trzymaj korzeń poza siecią, w trybie działania podpisuj pośrednim.
  • Klient jest w trybie utrzymaniowym. Nie oczekuj nowych funkcji w samym step; rozwój dzieje się w step-ca.
  • Wkład w projekt wymaga podpisania umowy licencyjnej współtwórcy. Oba repozytoria mają wpięty mechanizm CLA — jeśli twoja firma ma na to politykę, sprawdź ją przed pierwszym zgłoszeniem zmiany.

Podsumowanie

step jest narzędziem, po które warto sięgnąć w dwóch bardzo różnych momentach. Pierwszy: gdy chcesz przestać kleić skrypty z openssl i mieć polecenia o czytelnych nazwach, przewidywalnych kodach wyjścia i sensownym wypisywaniu. Drugi: gdy dojrzejesz do własnego urzędu certyfikacji i automatycznego odnawiania w sieci wewnętrznej.

  • Działa bez serwera — jako zestaw narzędzi kryptograficznych jest użyteczny od pierwszego dnia, bez żadnej infrastruktury.
  • Własny serwer ACME pozwala użyć w sieci wewnętrznej tych samych klientów, które już znasz z Let's Encrypt: certbota, acme.sh, Caddy'ego, Traefika.
  • Osiem sposobów uwierzytelnienia żądania, w tym dokumenty tożsamości instancji chmurowych, które rozwiązują problem pierwszego zaufania bez wkładania sekretu na maszynę.
  • Odnawianie z przeładowaniem usługi w jednym poleceniu, z sygnałem do procesu i haczykiem na polecenie własne.
  • Certyfikaty SSH dla ludzi i maszyn — realna droga wyjścia z plików z listą kluczy.
  • Wydania z poświadczeniami Sigstore przy każdym pakiecie, dla kilkunastu architektur.
  • Granica wersji płatnej opisana wprost w pliku README, zamiast odkrywana po wdrożeniu.

Oba projekty są wydane na licencji Apache 2.0, i przy narzędziu tej klasy jest to wybór wart odnotowania. Apache 2.0 daje bowiem coś, czego prostsze licencje permisywne nie dają: wyraźne udzielenie licencji patentowej przez współtwórców. W kryptografii i infrastrukturze klucza publicznego, gdzie patenty bywają realnym zagadnieniem, to konkretna wartość dla działu prawnego, nie formalność. W zamian licencja nakłada obowiązki: zachowanie informacji o prawach autorskich i pliku NOTICE oraz oznaczenie wprowadzonych zmian, jeśli rozprowadzasz zmodyfikowaną wersję. Do użytku wewnętrznego, a taki będzie w tym przypadku najczęstszy, nie zmienia to nic.

Warto natomiast pamiętać o naturze modelu open core. Apache 2.0 obejmuje kod już wydany i tego nie da się cofnąć — ale to, co znajdzie się w kolejnych wersjach, pozostaje decyzją firmy. Przy komponencie, który ma stać się korzeniem zaufania w twojej sieci na lata, warto tę zależność zapisać świadomie i sprawdzić, czy lista funkcji zastrzeżonych dla produktu płatnego nie zawiera czegoś, co twój audyt uzna za obowiązkowe.