Jak bezpiecznie wdrożyć ansible z hasłami poszczególnych hostów?

108

Chciałbym użyć ansible do zarządzania grupą istniejących serwerów. Utworzyłem ansible_hostsplik i pomyślnie przetestowałem (z -Kopcją) poleceniami skierowanymi tylko na jeden host

ansible -i ansible_hosts host1 --sudo -K # + commands ...

Mój problem polega na tym, że hasła użytkowników na każdym hoście są różne, ale nie mogę znaleźć sposobu na poradzenie sobie z tym w Ansible.

Używając -K, jestem proszony tylko o jedno hasło sudo z góry, które wydaje się być wypróbowane dla wszystkich kolejnych hostów bez pytania:

host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password

Dotychczasowe badania:

  • pytanie StackOverflow z jednej błędnej odpowiedzi ( „Use -K”) i jednej odpowiedzi przez autora mówiąc: «Okazało się, że potrzebne pozbawione hasła sudo»

  • Dokumenty Ansible , które mówią: „Korzystanie z sudo bez hasła ułatwia automatyzację, ale nie jest wymagane ”. (moje podkreślenie)

  • to pytanie bezpieczeństwa StackExchange, które przyjmuje je jako przeczytane, które NOPASSWDjest wymagane

  • artykuł „Skalowalne i zrozumiałe udostępnianie ...”, który mówi:

    „uruchomienie sudo może wymagać wpisania hasła, co jest pewnym sposobem na zablokowanie Ansible na zawsze. Prostą poprawką jest uruchomienie visudo na hoście docelowym i upewnienie się, że użytkownik Ansible użyje się do zalogowania, nie musi wpisywać hasła”

  • artykuł „Podstawowe Ansible Playbooks” , który mówi

    „Ansible może zalogować się na serwerze docelowym jako root i uniknąć potrzeby sudo lub pozwolić użytkownikowi na sudo bez hasła, ale sama myśl o tym powoduje, że moja śledziona grozi przeskoczeniem przełyku i zablokowaniem tchawicy, więc ja nie „

    Dokładnie moje myśli, ale jak wyjść poza pojedynczy serwer?

  • numer ansible nr 1227 : „Ansible powinien poprosić o hasło sudo dla wszystkich użytkowników w podręczniku”, który rok temu został zamknięty przez mpdehaan z komentarzem „Nie widziałem dużego popytu na to, myślę, że większość ludzi sudo od jednego konto użytkownika lub przez większość czasu używając kluczy. ”

Więc ... jak ludzie używają Ansible w takich sytuacjach? Ustawienie NOPASSWDw /etc/sudoers, ponowne hasło całej hostów lub umożliwiające logowanie SSH korzeń wszystko wydaje się dość drastyczne zmniejszenie bezpieczeństwa.

supervacuo
źródło
2
Czy istnieje powód, dla którego nie używasz kluczy SSH?
Trondh,
22
Już używam kluczy SSH; nie wpływają sudo(co nadal powinno wymagać hasła).
supervacuo
1
Może nie jest to dokładnie to, czego szukasz, ale na pudełkach Ubuntu nadal używam kluczy, tj. Umieszczając mój klucz publiczny w katalogu / root / uprawnione_ klucze, aby dostać się bezpośrednio jako root. Oczywistą wadą jest możliwość logowania użytkownika root przez ssh ... Nie zezwalam również na logowanie się hasłem przez ssh i uruchamiam fail2ban dla zwiększenia bezpieczeństwa.
senorsmile,
27
@senorsmile dzięki za odpowiedź! Czy mógłbyś zamiast tego udzielić odpowiedzi, abym mógł zagłosować za to, że nie przeczytałeś pytania?
supervacuo
4
tzn . ansible_ssh_passwordustawienie dotyczy tylko hasła SSH (wskazówka znajduje się w nazwie ...). I już używam logowania SSH opartego na kluczach.
supervacuo

Odpowiedzi:

53

Z pewnością przeprowadziłeś swoje badania ...

Z całego mojego doświadczenia z odpowiedzią na to, co chcesz osiągnąć, nie jest obsługiwane. Jak wspomniałeś, ansible stwierdza, że ​​nie wymaga sudo bez hasła i masz rację, nie wymaga. Ale nie widziałem jeszcze żadnej metody używania wielu haseł sudo w ansible, oczywiście bez uruchamiania wielu konfiguracji.

Nie mogę więc zaoferować dokładnego rozwiązania, którego szukasz, ale zapytałeś ...

„Więc ... jak ludzie używają Ansible w takich sytuacjach? Ustawienie NOPASSWD w / etc / sudoers, ponowne użycie hasła na hostach lub włączenie logowania root SSH wydaje się dość drastyczne zmniejszenie bezpieczeństwa.”

Mogę dać ci jeden pogląd na ten temat. Mój przypadek użycia to 1 000 węzłów w wielu centrach danych obsługujących globalną firmę SaaS, w której muszę zaprojektować / wdrożyć niektóre niezwykle ścisłe kontrole bezpieczeństwa ze względu na charakter naszej działalności. Bezpieczeństwo jest zawsze działaniem równoważącym, większa użyteczność, mniej bezpieczeństwa, proces ten nie różni się, jeśli korzystasz z 10 serwerów lub 1000 lub 100 000.

Masz całkowitą rację, że nie używasz loginów root ani za pomocą hasła ani kluczy ssh. W rzeczywistości logowanie roota powinno być całkowicie wyłączone, jeśli serwery mają podłączony kabel sieciowy.

Porozmawiajmy o ponownym użyciu hasła w dużym przedsiębiorstwie, czy rozsądne jest poproszenie sysadminów o różne hasła w każdym węźle? może dla kilku węzłów, ale moi administratorzy / inżynierowie zbuntowaliby się, gdyby musieli mieć inne hasła na 1000 węzłów. Wdrożenie, które byłoby prawie niemożliwe, każdy użytkownik musiałby gdzieś przechowywać własne hasła, miejmy nadzieję, że będą to klucze, a nie arkusze kalkulacyjne. Za każdym razem, gdy umieścisz hasło w miejscu, w którym można je usunąć zwykłym tekstem, znacznie zmniejszasz swoje bezpieczeństwo. Wolałbym, żeby znali na pamięć jedno lub dwa naprawdę silne hasła, niż musieli sprawdzać plik klucza za każdym razem, gdy musieli się zalogować lub wywołać sudo na maszynie.

Dlatego ponowne użycie hasła i standaryzacja jest czymś całkowicie akceptowalnym i standardowym nawet w bezpiecznym środowisku. W przeciwnym razie ldap, keystone i inne usługi katalogowe nie musiałyby istnieć.

Kiedy przechodzimy do automatycznych użytkowników, klucze ssh działają świetnie, aby Cię wprowadzić, ale nadal musisz przejść przez sudo. Twoje wybory to standardowe hasło dla użytkownika automatycznego (co jest akceptowalne w wielu przypadkach) lub włączenie NOPASSWD, jak wskazałeś. Większość zautomatyzowanych użytkowników wykonuje tylko kilka poleceń, więc jest całkiem możliwe i na pewno pożądane włączenie NOPASSWD, ale tylko dla wstępnie zatwierdzonych poleceń. Sugeruję użycie twojego zarządzania konfiguracją (w tym przypadku ansible) do zarządzania plikiem sudoers, abyś mógł łatwo zaktualizować listę poleceń bez hasła.

Teraz możesz podjąć pewne kroki po rozpoczęciu skalowania w celu dalszej izolacji ryzyka. Chociaż mamy około 1000 węzłów, nie wszystkie z nich są serwerami „produkcyjnymi”, niektóre są środowiskami testowymi itp. Nie wszyscy administratorzy mogą uzyskać dostęp do serwerów produkcyjnych, którzy nie mogą jednak korzystać z tego samego klucza SSO dla użytkownika / hasła | . Ale zautomatyzowani użytkownicy są nieco bardziej bezpieczni, na przykład zautomatyzowane narzędzie, do którego administratorzy nieprodukcyjni mogą uzyskać dostęp, ma użytkownika i poświadczenia, których nie można użyć w produkcji. Jeśli chcesz uruchomić ansible na wszystkich węzłach, musisz to zrobić w dwóch partiach, raz dla nieprodukcji i raz dla produkcji.

Używamy również marionetki, ponieważ jest to narzędzie do wymuszania zarządzania konfiguracją, więc większość zmian we wszystkich środowiskach zostanie przez to wypchnięta.

Oczywiście, jeśli cytowane żądanie funkcji zostanie ponownie otwarte / ukończone, to, czego szukasz, będzie całkowicie obsługiwane. Mimo to bezpieczeństwo to proces oceny ryzyka i kompromisu. Jeśli masz tylko kilka węzłów, dla których możesz zapamiętać hasła, bez uciekania się do karteczek post-it, osobne hasła byłyby nieco bardziej bezpieczne. Ale dla większości z nas nie jest to wykonalna opcja.

Zeb
źródło
Dzięki, @Zeb - wyobrażałem sobie, że użytkownicy z dziesiątkami do tysięcy serwerów i tak będą korzystać NOPASSWDze względów higienicznych (prawdopodobnie obsługiwanych przez ściślejsze reguły zapory ogniowej itp. ), Ale dobrze jest przeczytać swoją instrukcję użycia i przemyślenia na temat zagrożenia Model.
supervacuo
16
Jeden komentarz do twojej sugestii dotyczącej ograniczenia się do sudopoleceń „wstępnie zatwierdzonych” (co przyszło mi do głowy, kiedy odkryłem, że NOPASSWDjest to prawie wymagane). Niestety, wydaje się to również całkowicie nieobsługiwane - ansible nie obiecuje bezpośredniego wywołania np. chown Lub mkdirplików binarnych i musi być w stanie, aby sudo /bin/shwiększość modułów działała.
supervacuo
Wydaje mi się, że jeden z moich inżynierów narzekał na to jakiś czas temu, to denerwujące.
Zeb
36

Począwszy od Ansible 1.5, można używać zaszyfrowanego skarbca dla host_vars i innych zmiennych. To pozwala przynajmniej bezpiecznie przechowywać ansible_sudo_passzmienną dla jednego hosta (lub dla grupy) . Niestety, --ask-vault-passmonituje tylko o jedno hasło do przechowalni na każde wywołanie, więc nadal jesteś ograniczony do jednego hasła do przechowalni dla wszystkich hostów, których będziesz używać razem.

Niemniej jednak w przypadku niektórych zastosowań może to być ulepszenie w stosunku do posiadania jednego hasła sudo na wielu hostach, ponieważ osoba atakująca bez dostępu do zaszyfrowanych host_vars nadal potrzebowałaby osobnego hasła sudo dla każdej maszyny (lub grupy maszyn), którą atakuje.

Daniel Neades
źródło
3
Ta ansible_sudo_passopcja również wydaje się nowa - i wydaje się robić to, o co prosiłem. Jedno hasło do skarbca jest również idealne do moich celów. Dzięki!
supervacuo
Czy istnieje sposób na uniknięcie szyfrowania wszystkich host_vars przy użyciu tej metody? (potencjalne ograniczenie odnotowane przez Alexa Dupuya)
supervacuo
1
@ supervacuo - Aby uniknąć szyfrowania wszystkich zmiennych hosta, po prostu użyj katalogu var hosta zawierającego main.yml (niezaszyfrowany) i secret.yml (zaszyfrowany) - patrz ostatnia część tego dokumentu, gdzie mówi o grupie „raleigh” - ta sama technika działa dla różnych hostów i grup. Używam tego bardzo często, jedyną odmianą jest to, że jeśli sekret jest potrzebny tylko w przypadku niektórych podręczników, przydatne może być przechowanie go w innym drzewie w całości i dołączenie ścieżki zawierającej nazwę hosta lub zmiennej.
RichVel
1
Jeśli zaszyfrowałem wartość „ansible_ssh_pass” w skarbcu, więc muszę również zduplikować wartość „ansible_sudo_pass”? Czy istnieje sposób, aby druga wartość sudo_pass poprawiła pierwszą wartość „ssh_pass”?
emeraldjava
Dobre informacje na temat używania hasła ze sklepionym hasłem można znaleźć tutaj: stackoverflow.com/a/37300030/5025060
CODE-REaD
22

W Ansible 1.5 można ustawić zmienną ansible_sudo_pass za pomocą lookup('password', …):

ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"

Uważam to za wygodniejsze niż używanie plików host_vars/z kilku powodów:

  • Właściwie używam with_password: "passwords/{{ inventory_hostname}} encrypt=sha256_crypt" do udostępniania haseł zdalnemu użytkownikowi wdrażania (który jest następnie potrzebny dla sudo ), więc są one już obecne w plikach (chociaż te wyszukiwania tekstowe tracą wartość soli zapisaną w pliku, gdy generowana jest wartość mieszana) .

  • Zachowuje to tylko hasła w pliku ( ansible_sudo_pass:nieznany tekst jawny), aby zwiększyć bezpieczeństwo kryptograficzne epsilon. Co ważniejsze, oznacza to, że nie szyfrujesz wszystkich innych zmiennych specyficznych dla hosta, dzięki czemu można je odczytać bez hasła do skarbca.

  • Umieszczenie haseł w osobnym katalogu ułatwia utrzymanie plików poza kontrolą źródła lub użycie narzędzia takiego jak git-crypt do przechowywania ich w postaci zaszyfrowanej (możesz użyć tego z wcześniejszą wersją Ansible, która nie ma funkcji przechowalni). Używam git-crypt, a ponieważ sprawdzam repozytorium tylko w odszyfrowanej formie na zaszyfrowanych systemach plików, nie zawracam sobie głowy skarbcem i dlatego nie muszę wpisywać hasła do skarbca. (Korzystanie z obu byłoby oczywiście bezpieczniejsze).

Możesz także użyć funkcji wyszukiwania z ansible_ssh_pass ; może to być nawet możliwe we wcześniejszych wersjach Ansible, które nie mają ansible_sudo_pass .

Alex Dupuy
źródło
2
W końcu udało mi się tego spróbować (dzięki!), Ale nie widzę, jak by to działało git-crypt; o ile widzę. Wygląda na to, że Ansible nie ma jeszcze obsługi używania lookupw zaszyfrowanym skarbcu. Dokumenty passwordmodułu mówią, że istnieje jeszcze nieudokumentowana obsługa szyfrowanej pamięci, ale nie znalazłem jeszcze szczegółów. Jakieś wskazówki?
supervacuo
19

Korzystanie z pass jest prostą metodą dostarczania ansible haseł sudo. pass przechowuje jedno hasło na plik, co ułatwia udostępnianie haseł za pomocą git lub innych metod. Jest również bezpieczny (przy użyciu GnuPG), a jeśli używasz gpg-agent, pozwala korzystać z ansible bez podawania hasła przy każdym użyciu.

Aby podać hasło przechowywane jako servers/fooserwer foodo odebrania, użyj go w pliku inwentaryzacyjnym takim jak ten:

[servers]
foo ansible_sudo=True \
    ansible_sudo_pass="{{ lookup('pipe', 'pass servers/foo') }}"

Biorąc pod uwagę, że wcześniej odblokowałeś klucz dla gpg-agent, uruchomi się on w trybie ansible bez potrzeby podawania hasła.

fqxp
źródło
3

Jest to jednak dość stary wątek:

  • Używamy dwóch różnych systemów uwierzytelniania we własnym zakresie, zarządzanie maszynami odbywa się z lokalnych stacji roboczych w moim zespole.
  • Napisałem vars_plugindla Ansible (raczej pełną implementację można znaleźć na https://gist.github.com/mfriedenhagen/e488235d732b7becda81 ), która wyróżnia kilka systemów uwierzytelniania:
  • Nazwa systemu uwierzytelniania jest specyficzna dla grupy.
  • Użyty użytkownik loginu / sudo jest specyficzny dla grupy i administratora.
  • Wyciągam więc użytkownika ze środowiska administratora i odpowiednie hasło poprzez bibliotekę kluczy Pythona z bezpiecznego hasła (używamy pęku kluczy Mac OS X, ale z dokumentacji obsługiwane są również kwalety Gnome i _win_crypto).
  • Ustawiam uprawnienia do haseł w pęku kluczy systemu Mac OS X, aby powiadomić mnie o fakcie, że zabezpieczenia programu wiersza poleceń żądają dostępu do hasła do każdego systemu uwierzytelniania używanego przez hosty, więc uruchamiam polecenie „ansible -s all -m ping” i otrzymuję dwa monity (po jednym dla każdego systemu uwierzytelniania), w których naciskam spację, a ansible odbiera hasła.
Mirko Friedenhagen
źródło
Wygląda to bardzo schludnie, dziękuję - podoba mi się pomysł, aby nie przechowywać haseł w dwóch miejscach. W tej chwili utknąłem przy użyciu KeepassX (ponieważ brelok GNOME nie wydaje się zbyt przenośny), ale może uda mi się python-keepasszadziałać?
supervacuo
O ile rozumiem, kluczowanie w Pythonie jest abstrakcją, więc twoi koledzy mogą używać innych systemów operacyjnych. A może przechowujesz db keepassx na pamięci USB i musisz administrować ze stacji roboczych z różnymi systemami operacyjnymi?
Mirko Friedenhagen
zrozumiany; Miałem na myśli, że muszę już korzystać z KeepassX, aby mieć dostęp do haseł w systemach innych niż GNOME, więc ich przechowywanie gnome-keyringoznaczałoby przechowywanie duplikatów. Wciąż o wiele ładniejsza niż używanie NOPASSWD, chociaż…
supervacuo
0

Jednym z możliwych sposobów jest użycie zmiennych środowiskowych.

na przykład

pass1=foo pass2=bar ansible-playbook -i production servers.xml

Następnie w sztukach możesz wyszukać hasło sudo, używając:

lookup('env', 'pass1') 
lookup('env', 'pass2') 
Paul Calabro
źródło