Podaj hasło sudo dla Ansible

224

Jak określić hasło sudo dla Ansible w sposób nieinteraktywny?

Korzystam z instrukcji Ansible w następujący sposób:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username --ask-sudo-pass

Ale chcę uruchomić to w ten sposób:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username` **--sudo-pass=12345**

Czy jest jakiś sposób? Chcę maksymalnie zautomatyzować wdrażanie mojego projektu.

Slava Fomin II
źródło
4
Zobacz także: serverfault.com/questions/560106/…
utapyngo

Odpowiedzi:

169

Możesz przekazać zmienną w wierszu poleceń przez --extra-vars "name=value". Zmienna hasła Sudo to ansible_sudo_pass. Twoje polecenie wyglądałoby więc tak:

ansible-playbook playbook.yml -i inventory.ini --user=username \
                              --extra-vars "ansible_sudo_pass=yourPassword"

Aktualizacja 2017 : Ansible 2.2.1.0 używa teraz var ansible_become_pass. Albo wydaje się, że działa.

Alexandr Nikitin
źródło
7
Z punktu widzenia bezpieczeństwa najlepsza odpowiedź, jeśli dodasz następujące: history -cpo wykonaniu yml.
kiltek
12
@kiltek: lub dodaj dodatkową spację na początku linii (w bash), która * nie * zapisze linii .bash_history.
ccpizza
44
Nie jest dobrą praktyką przekazywanie haseł w wierszu poleceń. Każdy będzie mógł zobaczyć hasło na liście procesów podczas wykonywania polecenia ...
Pavel Chernikov
22
wciąż nie rób tego. --ask-sudo-pass
JasonG
2
@scrutari Jest to poprawne w niektórych sytuacjach: Np .: Zmiana domyślnego, znanego na całym świecie hasła początkowego, aby wprowadzić publiczny klucz ssh użytkownika ... Pomyśl o wstępnej konfiguracji świeżo ponownie obrazowanego systemu.
Ceredig
236

Dokumenty zdecydowanie nie zalecają ustawiania hasła sudo w postaci zwykłego tekstu, a zamiast tego używają --ask-sudo-passw wierszu poleceń podczas uruchamianiaansible-playbook


Aktualizacja 2016:

Ansible 2.0 (nie 100%, gdy) oznaczony --ask-sudo-passjako przestarzały. Doktorzy zalecają teraz używanie --ask-become-passzamiast tego, jednocześnie zamieniając korzystanie z sudowszystkich instrukcji w become.

zniechęcać
źródło
16
Tak, rozumiem, dlaczego jest to zalecane. Kiedy jednak używamy Ansible jako części procesu wdrażania, jaki jest lepszy sposób na zautomatyzowanie tego? Zatrzymywanie się w trakcie procesu wdrażania i proszenie użytkownika o podanie hasła sudo nie jest zbyt wygodne.
Slava Fomin II
9
Uwaga - przepustkę -ask-sudo-pass można przypisać do -K, jednak, o ile widzę, nie ma sposobu, aby obsługiwać playbook działający na wielu serwerach z różnymi hasłami (pyta tylko raz), więc myślę, że bez hasła sudo jest właściwą drogą.
William Turrell,
1
Nie wydaje się działać. ale następna sugestia („some-host ansible_sudo_pass = 'foobar'”) robi
nadavkav
--ask-sudo-pass został wycofany wcześniej, w wersji 1.9
Chris Betti
Chciałbym zaktualizować odpowiedź za pomocą linku źródłowego, jeśli taki masz.
zniesiono
106

Prawdopodobnie najlepszym sposobem na zrobienie tego - zakładając, że nie możesz użyć rozwiązania NOPASSWD dostarczonego przez scottod, jest użycie rozwiązania Mircea Vutcovici w połączeniu z Vault Ansible .

Na przykład możesz mieć taki poradnik:

- hosts: all

  vars_files:
    - secret

  tasks:
    - name: Do something as sudo
      service: name=nginx state=restarted
      sudo: yes

Dołączamy tutaj plik o nazwie, secretktóry będzie zawierał nasze hasło sudo.

Użyjemy ansible-vault, aby utworzyć zaszyfrowaną wersję tego pliku:

ansible-vault create secret

Poprosi Cię o hasło, a następnie otwórz domyślny edytor, aby edytować plik. Możesz umieścić ansible_sudo_passtutaj.

np . secret:

ansible_sudo_pass: mysudopassword

Zapisz i wyjdź, teraz masz zaszyfrowany secretplik, który Ansible jest w stanie odszyfrować po uruchomieniu twojego playbooka. Uwaga: możesz edytować plik za pomocą ansible-vault edit secret(i wprowadzić hasło, którego użyłeś podczas tworzenia pliku)

Ostatnim elementem układanki jest zapewnienie Ansible narzędzia, --vault-password-filektóre wykorzysta do odszyfrowania secretpliku.

Utwórz plik o nazwie vault.txti wpisz hasło użyte podczas tworzenia secretpliku. Hasło powinno być ciągiem przechowywanym jako pojedynczy wiersz w pliku.

Z Ansible Docs:

.. upewnij się, że uprawnienia do pliku są takie, że nikt inny nie może uzyskać dostępu do Twojego klucza i nie dodawać klucza do kontroli źródła

Wreszcie: możesz teraz uruchomić swój podręcznik z czymś takim

ansible-playbook playbook.yml -u someuser -i hosts --sudo --vault-password-file=vault.txt 

Powyższe zakłada następujący układ katalogów:

.
|_ playbook.yml
|_ secret
|_ hosts
|_ vault.txt

Możesz przeczytać więcej o Ansible Vault tutaj: https://docs.ansible.com/playbooks_vault.html

toast38coza
źródło
5
Uwaga: od wersji ansible 1.9 wydaje się, że nie można już używać zmiennej ansible_sudo_pass (lub ansible_become_pass): „fatal: [...] => Missing
into
6
Używam tego rozwiązania w środowisku produkcyjnym, jenkins przechowuje hasło do przechowalni jako zaciemnioną zmienną środowiskową, zapisuje je w czasie wykonywania w pliku tymczasowym i przechodzi do wywołania ansible.
simone cittadini
6
lub prościej: ansible-vault create group_vars/all/ansible.ymli dodaj ansible_sudo_pass: yourpasswordtam. Nie trzeba zmieniać podręczników ani ekwipunku
Bouke Versteegh
1
Próbowałem tego, ale dostałem ten błąd:fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
JohnnyQ
8
Jaki pożytek ma skarbiec, jeśli obok niego przechowywane jest hasło do skarbca w postaci zwykłego tekstu?
Erik
44

Patrząc na kod ( runner/__init__.py), myślę, że prawdopodobnie możesz ustawić go w pliku ekwipunku:

[whatever]
some-host ansible_sudo_pass='foobar'

Wydaje się, że w ansible.cfgpliku konfiguracyjnym znajduje się również pewne postanowienie , ale nie jest teraz zaimplementowane ( constants.py).

leucos
źródło
7
Świetnym sposobem na bezpieczne skonfigurowanie tego byłoby zapisanie tego w katalogu host_varslub, group_varsa następnie zaszyfrowanie pliku przy użyciu ansible-vault
Kyle
44

Nie sądzę, aby ansible pozwoliło ci podać hasło we flagach, jak chcesz. Może być gdzieś w konfiguracjach, które można ustawić, ale spowoduje to, że używanie ansible będzie mniej bezpieczne i nie będzie zalecane.

Jedną rzeczą, którą możesz zrobić, to utworzyć użytkownika na maszynie docelowej i przyznać mu uprawnienia do sudo bez hasła do wszystkich poleceń lub ograniczonej listy poleceń.

Jeśli uruchomisz sudo visudoi wpiszesz wiersz taki jak poniżej, to użytkownik „privilegedUser” nie powinien wprowadzać hasła, gdy uruchamia coś takiego sudo service xxxx start:

%privilegedUser ALL= NOPASSWD: /usr/bin/service
Scott
źródło
7
@bschlueter, więc popierasz złe praktyki?
Stephen
1
Nie sądzę, że to dobry pomysł. Użycie --ask-sudo-pass ma dla mnie sens.
kgpdeveloper
@simone cittadini Całkowicie się zgadzam, bo w rzeczywistości to odpowiedź, którą zamierzam udzielić. To jest zagrożenie bezpieczeństwa.
einarc
Ryzyko związane z bezpieczeństwem jest mniejsze, jeśli używasz sudo bez hasła do wdrażania na etapie testowania / produkcji, ale chcesz użyć tych odpowiedzi, aby pominąć konieczność wpisywania hasła logowania do lokalnego laptopa podczas wdrażania na komputerze lokalnym co 15 minut każdego dnia.
Jonathan Hartley
Jak dodać tę linię za pomocą Ansible?
Matthias
21

Hasło sudo jest przechowywana jako zmienna o nazwie ansible_sudo_pass. Możesz ustawić tę zmienną na kilka sposobów:

Na hosta, w pliku hostów zasobów reklamowych ( inventory/<inventoryname>/hosts)

[server]
10.0.0.0 ansible_sudo_pass=foobar

Na grupę, w pliku grup zapasów ( inventory/<inventoryname>/groups)

[server:vars]
ansible_sudo_pass=foobar

Na grupę, w zmiennych grupowych ( group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"

Na grupę, zaszyfrowane ( ansible-vault create group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"
Bouke Versteegh
źródło
18

Możesz ustawić hasło dla grupy lub wszystkich serwerów jednocześnie:

[all:vars]
ansible_sudo_pass=default_sudo_password_for_all_hosts

[group1:vars]
ansible_sudo_pass=default_sudo_password_for_group1
Mircea Vutcovici
źródło
14

Odrywałem włosy od tego, teraz znalazłem rozwiązanie, które robi to, co chcę:

1 zaszyfrowany plik na host zawierający hasło sudo

/ etc / ansible / hosts:

[all:vars]
ansible_ssh_connection=ssh ansible_ssh_user=myuser ansible_ssh_private_key_file=~/.ssh/id_rsa

[some_service_group]
node-0
node-1

następnie dla każdego hosta tworzysz zaszyfrowany plik var w następujący sposób:

ansible-vault create /etc/ansible/host_vars/node-0

z zawartością

ansible_sudo_pass: "my_sudo_pass_for_host_node-0"

jak zorganizujesz hasło do skarbca (wpisz przez --ask-vault-pass) lub przez cfg, zależy od ciebie

na tej podstawie podejrzewam, że możesz po prostu zaszyfrować cały plik hosts ...

greenone83
źródło
Szyfrowanie przy użyciu skarbca jest dla mnie najbardziej sensowne, chociaż starałem się z nimi korzystać ansible-playback. Musiałem użyć, -e @vault/filename.extaby użyć skarbca z moim ansible-playbookpołączeniem.
Alex
9

Bardziej sprytnym sposobem na to jest przechowywanie sudohasła w bezpiecznym repozytorium, takim jak LastPass lub KeePass, a następnie przekazanie go ansible-playbookprzy użyciu, -e@ale zamiast zakodować zawartość w rzeczywistym pliku, możesz użyć konstrukcji -e@<(...)do uruchomienia polecenia w podpowłokę i przekieruj swoje wyjście (STDOUT) do anonimowego deskryptora pliku, skutecznie przekazując hasło do -e@<(..).

Przykład

$ ansible-playbook -i /tmp/hosts pb.yml \
   -e@<(echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)")

Powyżej robi kilka rzeczy, podzielmy to.

  • ansible-playbook -i /tmp/hosts pb.yml - oczywiście prowadzenie playbooka przez ansible-playbook
  • $(lpass show folder1/item1 --password)" - uruchamia interfejs CLI LastPass lpass i pobiera hasło do użycia
  • echo "ansible_sudo_pass: ...password..." - pobiera ciąg „ansible_sudo_pass:” i łączy go z hasłem podanym przez lpass
  • -e@<(..)- łączy powyższe i łączy podpowłokę <(...)jako deskryptor pliku ansible-playbookdo wykorzystania.

Dalsze doskonalenia

Jeśli wolisz nie pisać tego za każdym razem, możesz po prostu coś takiego. Najpierw utwórz alias w .bashrctaki sposób:

$ cat ~/.bashrc
alias asp='echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)"'

Teraz możesz uruchomić swój poradnik w ten sposób:

$ ansible-playbook -i /tmp/hosts pb.yml -e@<(asp)

Bibliografia

slm
źródło
1
Korzystanie z podpowłoki jest bardzo sprytnym pomysłem! Dla tych, którzy zastanawiają się, oto jak to wygląda z CLI 1Password:--extra-vars @<(echo ansible_become_pass: $(op get item <item name> | jq --raw-output '.details.sections[0].fields[] | select(.t=="password").v'))
Diti
1
Podoba mi się to, ponieważ kiedy sprawdziłem historię Bacha, hasło nie zostało ujawnione jawnym tekstem. Prawdopodobnie prawdą jest również to, że jeśli włączona jest kontrola systemu, polecenie jest rejestrowane jako odczyt pliku, np. /dev/fd/63Dlatego, że hasło znajduje się w deskryptorze pliku tymczasowego, nie jest ujawniane.
JPvRiel
5

Jeśli nie masz nic przeciwko utrzymywaniu haseł w plikach zwykłego tekstu, inną opcją jest użycie pliku JSON z parametrem --extra-vars (pamiętaj, aby wykluczyć plik z kontroli źródła):

ansible-playbook --extra-vars "@private_vars.json" playbook.yml 

Ansible obsługuje tę opcję od 1.3 .

sidecarcat
źródło
5

możesz wpisać hasło sudo do swojego playbooka w pliku hosts:

[host-group-name]
host-name:port ansible_sudo_pass='*your-sudo-password*'
fawadRafiq
źródło
5

Kilka razy sugerowano tutaj skrzynkę głosową, ale wolę git-crypt do szyfrowania poufnych plików w moich podręcznikach. Jeśli używasz git, aby zachować swoje podręczniki, to jest to proste. Problem, który znalazłem w Vault, jest taki, że nieuchronnie trafiam na zaszyfrowane kopie pliku, z którym chcę pracować i muszę go odszyfrować, zanim będę mógł pracować. git-cryptoferuje ładniejszy przepływ pracy IMO.

Korzystając z tego, możesz umieścić swoje hasła w var w swoim playbooku i oznaczyć swój playbook jako zaszyfrowany plik w .gitattributesnastępujący sposób:

 my_playbook.yml filter=git-crypt diff=git-crypt

Twój podręcznik będzie zaszyfrowany w Github. Następnie wystarczy zainstalować klucz szyfrujący na hoście, którego używasz do uruchomienia ansible, lub postępuj zgodnie z instrukcjami w dokumentacji, aby go skonfigurować gpg.

Odpowiedzi na pytania dotyczące przekazywania gpgkluczy, takich jak ssh-agentklucze SSH do przesyłania dalej, są tutaj: /superuser/161973/how-can-i-forward-a-gpg-key-via-ssh-agent .

użytkownik2432419
źródło
3

Możesz użyć sshpassnarzędzia, jak poniżej,

$ sshpass -p "your pass" ansible pattern -m module -a args \
   -i inventory --ask-sudo-pass
Sachin
źródło
3

Korzystanie z ansible 2.4.1.0 i następujących elementów powinno działać:

[all]
17.26.131.10
17.26.131.11
17.26.131.12
17.26.131.13
17.26.131.14

[all:vars]
ansible_connection=ssh
ansible_user=per
ansible_ssh_pass=per
ansible_sudo_pass=per

I po prostu uruchom podręcznik z tym ekwipunkiem jako:

ansible-playbook -i inventory copyTest.yml
Hearen
źródło
3

Moim hackem do zautomatyzowania tego było użycie zmiennej środowiskowej i dostęp do niej poprzez --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'".

Wyeksportuj zmienną env var, ale unikaj historii bash / shell (poprzedzaj spacją lub innymi metodami). Na przykład:

     export ANSIBLE_BECOME_PASS='<your password>'

Wyszukaj ansible_become_passzmienną env podczas przekazywania dodatkowej zmiennej do ansible-playbook, np .:

ansible-playbook playbook.yml -i inventories/dev/hosts.yml -u user --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'"

Dobre alternatywne odpowiedzi:

JPvRiel
źródło
2

Możesz użyć skarbca ansible który twoje hasło w skarbcu szyfrowanym. Następnie możesz używać zmiennej z repozytorium w playbookach.

Trochę dokumentacji dotyczącej ansible vault:
http://docs.ansible.com/playbooks_vault.html

Używamy go jako skarbca dla środowiska. Aby edytować skarbiec, mamy polecenie jako:
ansible-vault edit inventories/production/group_vars/all/vault

Jeśli chcesz wywołać zmienną vault, musisz użyć playbooka Ansible z parametrami takimi jak:
ansible-playbook -s --vault-password-file=~/.ansible_vault.password

Tak, przechowujemy hasło do przechowalni w katalogu lokalnym w postaci zwykłego tekstu, ale nie jest to bardziej niebezpieczne, jak hasło roota sklepu dla każdego systemu. Hasło roota znajduje się w pliku repozytorium lub można je ustawić tak jak plik sudoers dla użytkownika / grupy.

Polecam używać pliku sudoers na serwerze. Oto przykład dla administratora grupy:
%admin ALL=(ALL) NOPASSWD:ALL

maxo
źródło
1

Po pięciu latach widzę, że jest to nadal bardzo istotny temat. W pewnym sensie odzwierciedla odpowiedź Leucos, która wydaje mi się najlepsza w moim przypadku, przy użyciu tylko narzędzi ansible (bez scentralizowanego uwierzytelnienia, tokenów itp.). Zakłada się, że masz tę samą nazwę użytkownika i ten sam klucz publiczny na wszystkich serwerach. Jeśli nie, oczywiście musisz być bardziej szczegółowy i dodać odpowiednie zmienne obok hostów:

[all:vars]
ansible_ssh_user=ansible
ansible_ssh_private_key_file=home/user/.ssh/mykey
[group]
192.168.0.50 ansible_sudo_pass='{{ myserver_sudo }}'

ansible-vault create mypasswd.yml
ansible-vault edit mypasswd.yml

Dodaj:

myserver_sudo: mysecretpassword

Następnie:

ansible-playbook -i inv.ini my_role.yml --ask-vault --extra-vars '@passwd.yml'

Przynajmniej w ten sposób nie musisz pisać więcej zmiennych, które wskazują hasła.

Letargos
źródło
1

Powyższe rozwiązanie autorstwa @ toast38coza działało dla mnie; tylko to sudo: tak jest już przestarzałe w Ansible. Zamiast tego należy użyć funkcji Zostań i zostań_użytkownikiem .

tasks:
 - name: Restart apache service
   service: name=apache2 state=restarted
   become: yes
   become_user: root
Nätu
źródło
0

możemy również użyć EXPECT BLOCK w ansible, aby spawnować bash i dostosowywać go zgodnie z twoimi potrzebami

- name: Run expect to INSTALL TA
  shell: |
    set timeout 100
    spawn /bin/sh -i

    expect -re "$ "
    send "sudo yum remove -y xyz\n"

    expect "$ "
    send "sudo yum localinstall -y {{ rpm_remotehost_path_for_xyz }}\n"

    expect "~]$ "
    send "\n"

    exit 0
  args:
  executable: /usr/bin/expect
Ashish Ranjan
źródło
0

Bardzo proste i dodaj tylko w pliku zmiennych:

Przykład:

$ vim group_vars/all

I dodaj te:

Ansible_connection: ssh
Ansible_ssh_user: rafael
Ansible_ssh_pass: password123
Ansible_become_pass: password123
rafaelrms
źródło
Dzięki, ale myślę, że masz na myśli ansible_become_pass zamiast Ansible_become_pass.
Krishnom
0

To tylko dodatek, więc nikt inny nie przechodzi przez irytację, którą ostatnio zrobiłem:

AFAIK, najlepszym rozwiązaniem jest jedno z ogólnych założeń powyższego toast38coza. Jeśli sensowne jest powiązanie plików haseł i podręcznika ze sobą statycznie, postępuj zgodnie z jego szablonem za pomocą vars_files(lub include_vars). Jeśli chcesz je rozdzielić, możesz podać zawartość skarbca w wierszu poleceń w następujący sposób:

ansible-playbook --ask-vault-pass -e@<PATH_TO_VAULT_FILE> <PLAYBOOK_FILE>

Z perspektywy czasu jest to oczywiste, ale oto gotcha:

  1. Ten cholerny znak @ . Jeśli go pominiesz, parsowanie nie powiedzie się po cichu , a playbook ansible będzie postępował tak, jakbyś nigdy nie określił pliku.

  2. Musisz jawnie zaimportować zawartość skarbca za pomocą wiersza polecenia --extra-vars / -e lub w kodzie YAML. --ask-vault-passFlaga nie ma niczego sobie (oprócz poprosi o wartości, które mogą lub nie mogą być wykorzystane później) zrobić.

Możesz dołączyć swoje „@” i zaoszczędzić godzinę.

Eric Anderson
źródło
-3

To działało dla mnie ... Utworzono plik /etc/sudoers.d/90-init-users za pomocą NOPASSWD

echo "user ALL=(ALL)       NOPASSWD:ALL" > 90-init-users

gdzie „użytkownik” jest twoim identyfikatorem użytkownika.

ScottM
źródło