Zawsze kiedy stawiam nową maszynę albo zbieram się do formatu, zastanawiam się czy będę miał do wszystkiego dostęp albo czy aby na pewno się od czegoś przypadkiem nie odetnę.
Temat haseł w zasadzie mi rozwiązał pass - terminalowy password manager zintegrowany z gitem i szyfrowany kluczem gpg, więc relatywnie bezpiecznie można to w remotowym repo trzymać. Same fajne rzeczy.
Ale skąd na nowej maszynie wezme ten klucz gpg do odszyfrowania haseł? Nie mówiąc już o kluczach ssh etc.
Proste tożsame rozwiązanie to po prostu szyfrowanie takich kluczy ręcznie i podobnie dystrybucja gitem. Wtedy wystarczy że pamiętamy albo jesteśmy w stanie odzyskać jedną kredke do gita i gdzieś mamy klucz. Może to być klucz który będziemy trzymać na pendrivie albo innym yubikeyu, być może skitramy ten klucz w hashicorp vaulcie, albo użyjemy cloudowego KMSa. Wszystko to są całkiem dobre opcje ale z tyłu głowy dla każdej z nich mam gotowy scenariusz, w którym (nie koniecznie bezpowrotnie) tracę dostęp do klucza (nie mam ze sobą pendrive'a albo wyzionął ducha, selfhostowany HCP Vault się wykrzaczył, nie mam internetu żeby dostać się do Cloud KMSa).
Najlepiej więc byłoby wszystkie te nasze klucze prywatne szyfrować na kilka metod żeby mieć w razie czego fallback, ale to brzmi trochę jak kupa roboty jeżeli robilibyśmy to ręcznie.
Na szczęście mądrzejsi ludzie już ten problem rozwiązali i dali nam SOPS.
Sops po prawdzie raczej ma na celu rozwiązanie problemu sekretów w konfiguracji, tak żebyśmy nie musieli robić zbyt dużo gimanstyki z jakimiś wtyczkami w zależności od softu który będzie tą konfiguracje trawił, albo dziergać jakieś inne rozwiązania na integrację z natywnymi dla jakiegoś danego CI secret storami. Sops pozwala nam niejako w locie rozszyfrować yamla i podać go gdzie tam jest potrzebny. Do VSCode'a nawet chyba jest wtyczka która powoduje że edycja takich plików jest totalnie przezroczysta dla użytkownika. Nas to tutaj szczególnie nie interesuje, ale gwoli ścisłości uważam że warto to tu nadmienić bo to dobry tech.
Sops pozwoli nam z minimalnym configiem szyfrować pliki wieloma metodami i równie prosto je rozszyfrowywać.
W tym przykładzie używam GCP KMS i age. Ale no stronie SOPSa znaleźć można dokumentacje dla innych technologii.
Będziemy potrzebowali pełnej nazwy klucza (tj. całej ścieżki z projektem, lokacją, keyringiem etc.):
gcloud kms keys list --location global --keyring sops | awk '{print $1}' | grep -v NAME
Generowanie klucza age i zrzucenie go do defaultowej ścieżki dla sops:
age-keygen -o ~/.config/sops/age/keys.txt
W ścieżce będzie zarówno klucz publiczny (potrzebny potem) jak i prywatny. Zawartość tego pliku powinniśmy skitrać na jakimś nośniku fizycznym i wsadzić w jakieś bezpieczne miejsce.
W moim przypadku interesują mnie konkretnie klucze SSH i gpg, ale z czasem pewnie dorzucę jakieś inne identity file'e.
Tu sprawa jest dosyć prosta
cp -r ~/.ssh/id_* .
# chyba że ktoś używa bardziej egzotycznych nazw kluczy
Export kluczy publicznych:
gpg -a --export > publickeys.asc
Export kluczy prywatnych (i ich kluczy publicznych):
gpg -a --export-secret-keys > privatekeys.asc
Export trustdb:
gpg --export-ownertrust > trustdb.txt
Tworzymy .sops.yaml
do umieszczenia w repozytorium
creation_rules:
- age: age1*********************************************************
gcp_kms: projects/******/locations/global/keyRings/sops/cryptoKeys/sops-key
i szyfrujemy wszystkie pliki:
for f in $(ls); do sops encrypt -i $f; done
Teraz możemy zcommitować wszystko w repo (.sops.yaml
teoeretycznie nie musi być w repo bo dane na temat tego jakie klucze zostały użyte i tak są w wynikowych plikach sopsa, ale jeżeli będziemy chcieli dodać nowy plik do repo to oszczędzi nam to roboty).
Zobaczyć zawartość dowolnego pliku możemy przez sops decrypt plik
, adekwatnie więc możemy to pipeować, redirectować i tak dalej. W grę wchodzą też takie rozwiązania jak sops exec-env
który uruchomi nam proces z załadowaną rozszyfrowaną zawartością w env varze albo sops exec-file
który, jak się można dymyślić, wrzuci to do tymczasowego pliku.
I tak np. nasze eksporty gpg możemy importować przez:
for f in publickeys.asc privatekeys.asc trustdb.txt; do
sops decrypt $f | gpg --import
done
Zasadniczo potencjalne problemy są takie:
Na pierwszy problem nie ma rady, trzeba się pilnować
Jeżeli idzie o dostęp do clouda to wiadomo, dobre zmieniane regularnie hasło, Two-Factor przez token (nie numer telefonu) etc.
Podatność w AES256_GCM bolałaby nas w sytuacji w której ktoś miałby dostęp do zaszyfrowanych plików. Najlepiej więc trzymać je w prywatnym repo.