Geben Sie das sudo-Passwort für Ansible an

224

Wie gebe ich ein Sudo-Passwort für Ansible auf nicht interaktive Weise an?

Ich verwende Ansible Playbook wie folgt:

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

Aber ich möchte es so laufen lassen:

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

Gibt es einen Weg? Ich möchte meine Projektbereitstellung so weit wie möglich automatisieren.

Slava Fomin II
quelle
4
Siehe auch: serverfault.com/questions/560106/…
utapyngo

Antworten:

168

Sie können eine Variable in der Befehlszeile über übergeben --extra-vars "name=value". Sudo Passwortvariable ist ansible_sudo_pass. Ihr Befehl würde also so aussehen:

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

Update 2017 : Ansible 2.2.1.0 verwendet jetzt var ansible_become_pass. Beides scheint zu funktionieren.

Alexandr Nikitin
quelle
7
Aus Sicherheitsgründen die beste Antwort, wenn Sie Folgendes hinzufügen: history -cNach der Ausführung des yml.
Kiltek
12
@kiltek: oder füge ein zusätzliches Leerzeichen am Anfang der Zeile (in Bash) hinzu, in das die Zeile * nicht * geschrieben wird .bash_history.
ccpizza
44
Es empfiehlt sich nicht, Kennwörter über die Befehlszeile einzugeben. Jeder kann das Passwort in der Prozessliste sehen, während der Befehl ausgeführt wird ...
Pavel Chernikov
22
Trotzdem, tu es einfach nicht. --ask-sudo-pass
JasonG
2
@scrutari In einigen Situationen ist dies vollkommen gültig: Beispiel: Ändern Sie von einem weltweit bekannten Standard-Anfangskennwort, um den öffentlichen SSH-Schlüssel des Benutzers einzufügen ... Denken Sie an die Erstkonfiguration eines frisch neu abgebildeten Systems.
Ceredig
236

In den Dokumenten wird dringend empfohlen, das sudo-Kennwort nicht im Klartext festzulegen und stattdessen --ask-sudo-passbeim Ausführen in der Befehlszeile zu verwendenansible-playbook


Update 2016:

Ansible 2.0 (nicht 100% wenn) --ask-sudo-passals veraltet markiert . In den Dokumenten wird jetzt empfohlen, --ask-become-passstattdessen zu verwenden und gleichzeitig die Verwendung in sudoallen Playbooks mit auszutauschen become.

deefour
quelle
16
Ja, ich kann sehen, warum dies empfohlen wird. Wenn wir Ansible jedoch als Teil des Bereitstellungsprozesses verwenden, wie kann dies besser automatisiert werden? Es ist nicht sehr praktisch, mitten im Bereitstellungsprozess anzuhalten und den Benutzer zur Eingabe des sudo-Kennworts aufzufordern.
Slava Fomin II
9
Hinweis --ask-sudo-pass kann mit -K abgekürzt werden. Soweit ich sehen kann, gibt es jedoch keine Möglichkeit, ein Playbook zu handhaben, das auf mehreren Servern mit unterschiedlichen Passwörtern ausgeführt wird (es fragt Sie nur einmal), daher denke ich, dass es passwortlos ist Sudo ist der richtige Weg.
William Turrell
1
Scheint nicht zu funktionieren. aber der nächste Vorschlag ("some-host ansible_sudo_pass = 'foobar'") macht
nadavkav
--ask-sudo-pass wurde früher, in 1.9
Chris Betti
Ich würde die Antwort gerne mit einem Quelllink aktualisieren, wenn Sie einen haben.
Deefour
106

Der wahrscheinlich beste Weg, dies zu tun - vorausgesetzt, Sie können die von scottod bereitgestellte NOPASSWD-Lösung nicht verwenden, ist die Verwendung der Lösung von Mircea Vutcovici in Kombination mit Ansible Vault .

Zum Beispiel könnten Sie ein Spielbuch wie das folgende haben:

- hosts: all

  vars_files:
    - secret

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

Hier fügen wir eine Datei mit dem Namen secretsudo hinzu, die unser sudo-Passwort enthält.

Wir werden ansible-vault verwenden, um eine verschlüsselte Version dieser Datei zu erstellen:

ansible-vault create secret

Sie werden nach einem Kennwort gefragt und öffnen dann Ihren Standardeditor, um die Datei zu bearbeiten. Sie können Ihre ansible_sudo_passhier setzen.

zB secret::

ansible_sudo_pass: mysudopassword

Speichern und beenden, jetzt haben Sie eine verschlüsselte secretDatei, die Ansible entschlüsseln kann, wenn Sie Ihr Playbook ausführen. Hinweis: Sie können die Datei mit bearbeiten ansible-vault edit secret(und das Kennwort eingeben, das Sie beim Erstellen der Datei verwendet haben).

Das letzte Puzzleteil besteht darin, Ansible eine zu geben, mit --vault-password-fileder es Ihre secretDatei entschlüsseln kann.

Erstellen Sie eine Datei mit dem Namen vault.txtund geben Sie das Kennwort ein, das Sie beim Erstellen Ihrer Datei verwendet habensecret Datei verwendet haben. Das Kennwort sollte eine Zeichenfolge sein, die als einzelne Zeile in der Datei gespeichert ist.

Aus den Ansible Docs:

.. Stellen Sie sicher, dass die Berechtigungen für die Datei so sind, dass niemand sonst auf Ihren Schlüssel zugreifen kann, und fügen Sie Ihren Schlüssel nicht der Quellcodeverwaltung hinzu

Endlich: Sie können Ihr Playbook jetzt mit so etwas wie ausführen

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

Das Obige setzt das folgende Verzeichnislayout voraus:

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

Weitere Informationen zu Ansible Vault finden Sie hier: https://docs.ansible.com/playbooks_vault.html

toast38coza
quelle
5
Hinweis: Ab Ansible 1.9 können Sie die Variable ansible_sudo_pass (oder ansible_become_pass) anscheinend nicht mehr verwenden: "fatal: [...] => Fehlendes Passwort"
toast38coza
6
Ich verwende diese Lösung in der Produktion. Jenkins speichert das Tresorkennwort als verschleierte Umgebungsvariable, schreibt es zur Laufzeit in eine temporäre Datei und ruft ansible auf.
Simone Cittadini
6
oder einfacher: ansible-vault create group_vars/all/ansible.ymlund dort hinzufügen ansible_sudo_pass: yourpassword. Keine Notwendigkeit, Spielbücher oder Inventar zu ändern
Bouke Versteegh
1
Versuchte dies, aber ich bekam diesen Fehler:fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
JohnnyQ
8
Was nützt ein Tresor, wenn Sie das Passwort für den Tresor im Klartext direkt daneben speichern?
Erik
44

Wenn Sie sich den Code ( runner/__init__.py) ansehen, können Sie ihn wahrscheinlich in Ihrer Inventardatei festlegen:

[whatever]
some-host ansible_sudo_pass='foobar'

Es scheint auch einige Bestimmungen in der ansible.cfgKonfigurationsdatei zu geben, die derzeit jedoch nicht implementiert sind ( constants.py).

Leukos
quelle
7
Eine gute Möglichkeit, dies sicher zu konfigurieren, besteht darin, dies im Verzeichnis host_varsoder zu speichern group_varsund die Datei dann mit ansible-vault zu
Kyle
44

Ich glaube nicht, dass Sie mit ansible ein Passwort in den Flags angeben können, wie Sie es möchten. Es kann irgendwo in den Konfigurationen sein, dass dies eingestellt werden kann, aber dies würde die Verwendung von Ansible insgesamt weniger sicher machen und würde nicht empfohlen werden.

Sie können einen Benutzer auf dem Zielcomputer erstellen und ihm kennwortlose Sudo-Berechtigungen für alle Befehle oder eine eingeschränkte Liste von Befehlen gewähren.

Wenn Sie sudo visudoeine Zeile wie die folgende ausführen und eingeben, muss der Benutzer 'privilegedUser' kein Kennwort eingeben müssen, wenn er Folgendes ausführt sudo service xxxx start:

%privilegedUser ALL= NOPASSWD: /usr/bin/service
Scottod
quelle
7
@bschlueter also befürwortest du schlechte Praxis?
Stephen
1
Ich halte das nicht für eine gute Idee. Die Verwendung von --ask-sudo-pass macht für mich Sinn.
kgpdeveloper
@ Simon Cittadini Ich stimme vollkommen zu, da dies die Antwort ist, die ich geben wollte. Dieser ist ein Sicherheitsrisiko.
Einarc
Es ist weniger ein Sicherheitsrisiko, wenn Sie passwortloses sudo für die Bereitstellung auf Staging / Prod verwenden, diese Antworten jedoch verwenden möchten, um zu überspringen, dass Sie Ihr lokales Laptop-Anmeldekennwort eingeben müssen, wenn Sie es jeden Tag alle 15 Minuten auf Ihrem lokalen Host bereitstellen.
Jonathan Hartley
Wie fügt man diese Zeile mit Ansible hinzu?
Matthias
21

Das sudo-Passwort wird als aufgerufene Variable gespeichertansible_sudo_pass . Sie können diese Variable auf verschiedene Arten festlegen:

Pro Host in Ihrer Inventar-Hosts-Datei ( inventory/<inventoryname>/hosts)

[server]
10.0.0.0 ansible_sudo_pass=foobar

Pro Gruppe in Ihrer Inventargruppendatei ( inventory/<inventoryname>/groups)

[server:vars]
ansible_sudo_pass=foobar

Pro Gruppe in Gruppe vars ( group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"

Pro Gruppe verschlüsselt ( ansible-vault create group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"
Bouke Versteegh
quelle
18

Sie können das Kennwort für eine Gruppe oder für alle Server gleichzeitig festlegen:

[all:vars]
ansible_sudo_pass=default_sudo_password_for_all_hosts

[group1:vars]
ansible_sudo_pass=default_sudo_password_for_group1
Mircea Vutcovici
quelle
14

Ich habe mir hier die Haare ausgerissen, jetzt habe ich eine Lösung gefunden, die macht, was ich will:

1 verschlüsselte Datei pro Host mit dem sudo-Passwort

/ 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

Dann erstellen Sie für jeden Host eine verschlüsselte Var-Datei wie folgt:

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

mit Inhalt

ansible_sudo_pass: "my_sudo_pass_for_host_node-0"

Wie Sie das Tresorkennwort (Eingabe über --ask-vault-pass) oder per cfg organisieren, liegt ganz bei Ihnen

Aufgrund dessen vermute ich, dass Sie einfach die gesamte Hosts-Datei verschlüsseln können ...

greenone83
quelle
Das Verschlüsseln mit Vault ist für mich am sinnvollsten, obwohl ich Schwierigkeiten hatte, sie zu verwenden ansible-playback. Ich musste -e @vault/filename.extden Tresor mit meinem ansible-playbookAnruf benutzen .
Alex
9

Ein versierter Weg , dies zu tun , ist Sie speichern sudoPasswort in einem sicheren Tresor wie Lastpass oder KeePass und es dann passiert ansible-playbookdie Verwendung , -e@sondern um den Inhalt in einer aktuellen Datei von hartzucodieren, können Sie das Konstrukt verwenden -e@<(...)einen Befehl in einem laufen Unter-Shell und leiten Sie die Ausgabe (STDOUT) an einen anonymen Dateideskriptor weiter, und geben Sie das Kennwort effektiv an die -e@<(..).

Beispiel

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

Das Obige macht mehrere Dinge, lassen Sie es uns zusammenfassen.

  • ansible-playbook -i /tmp/hosts pb.yml - Offensichtlich ein Playbook über Ansible-Playbook laufen lassen
  • $(lpass show folder1/item1 --password)" - führt die LastPass-CLI aus lpass und ruft das zu verwendende Kennwort ab
  • echo "ansible_sudo_pass: ...password..." - nimmt den String 'ansible_sudo_pass:' und kombiniert ihn mit dem von lpass
  • -e@<(..)- fügt das Obige zusammen und verbindet die Subshell von <(...)als Dateideskriptor für den Verbrauch ansible-playbook.

Weitere Verbesserungen

Wenn Sie das lieber nicht jedes Mal eingeben möchten, können Sie einfach solche Dinge tun. Erstellen Sie zunächst einen Alias .bashrcwie folgt:

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

Jetzt können Sie Ihr Playbook folgendermaßen ausführen:

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

Verweise

slm
quelle
1
Die Verwendung einer Unterschale ist eine sehr kluge Idee! Für diejenigen, die sich fragen, hier ist, wie es mit 1Passwords CLI aussieht:--extra-vars @<(echo ansible_become_pass: $(op get item <item name> | jq --raw-output '.details.sections[0].fields[] | select(.t=="password").v'))
Diti
1
Ich mag das, weil das Passwort beim Überprüfen des Bach-Verlaufs nicht im Klartext angezeigt wurde. Dies gilt wahrscheinlich auch für den Fall, dass der Befehl beim Aktivieren der Systemüberwachung als Lesen einer Datei protokolliert wird, z. B. /dev/fd/63wenn das Kennwort in einem temporären Dateideskriptor enthalten ist, wird es nicht offengelegt.
JPvRiel
5

Wenn Sie mit der Speicherung von Kennwörtern in Nur-Text-Dateien vertraut sind, können Sie auch eine JSON-Datei mit dem Parameter --extra-vars verwenden (schließen Sie die Datei unbedingt von der Quellcodeverwaltung aus):

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

Ansible unterstützt diese Option seit 1.3 .

Beiwagen
quelle
5

Sie können das Sudo-Passwort für Ihr Playbook wie folgt in die Hosts-Datei schreiben:

[host-group-name]
host-name:port ansible_sudo_pass='*your-sudo-password*'
fawadRafiq
quelle
5

Ansible Vault wurde hier ein paar Mal vorgeschlagen, aber ich bevorzuge Git-Crypt, um vertrauliche Dateien in meinen Playbooks zu verschlüsseln. Wenn Sie git verwenden, um Ihre ansible Playbooks zu behalten, ist es ein Kinderspiel. Das Problem, das ich bei ansible vault festgestellt habe, ist, dass ich unweigerlich auf verschlüsselte Kopien der Datei stoße, mit der ich arbeiten möchte, und sie entschlüsseln muss, bevor ich arbeiten kann. git-cryptbietet einen schöneren Workflow IMO.

Auf diese Weise können Sie Ihre Passwörter in eine Variable in Ihrem Playbook einfügen und Ihr Playbook wie folgt als verschlüsselte Datei markieren .gitattributes:

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

Ihr Playbook wird auf Github transparent verschlüsselt. Dann müssen Sie entweder Ihren Verschlüsselungsschlüssel auf dem Host installieren, auf dem Sie ansible ausführen, oder den Anweisungen in der Dokumentation folgen, um ihn einzurichten gpg.

Hier finden Sie gute Fragen und Antworten zu Weiterleitungsschlüsseln gpgwie Ihren Weiterleitungs- ssh-agentSSH-Schlüsseln: /superuser/161973/how-can-i-forward-a-gpg-key-via-ssh-agent .

user2432419
quelle
3

Sie können das sshpassDienstprogramm wie folgt verwenden:

$ sshpass -p "your pass" ansible pattern -m module -a args \
   -i inventory --ask-sudo-pass
Sachin
quelle
3

Die Verwendung von ansible 2.4.1.0 und den folgenden Funktionen soll funktionieren:

[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

Führen Sie das Playbook mit diesem Inventar wie folgt aus :

ansible-playbook -i inventory copyTest.yml
Gehört
quelle
3

Mein Hack, um dies zu automatisieren, bestand darin, eine Umgebungsvariable zu verwenden und über darauf zuzugreifen --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'".

Exportieren Sie eine env-Variable, vermeiden Sie jedoch den Bash- / Shell-Verlauf (stellen Sie ein Leerzeichen oder andere Methoden voran). Z.B:

     export ANSIBLE_BECOME_PASS='<your password>'

Suchen Sie die env- ansible_become_passVariable ansible-playbook, während Sie die zusätzliche Variable an Folgendes übergeben: ZB:

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

Gute alternative Antworten:

JPvRiel
quelle
2

Sie können ansible Tresor verwenden der Ihr Passwort in einen verschlüsselten Tresor . Danach können Sie Variablen aus dem Tresor in Playbooks verwenden.

Einige Dokumentationen zu Ansible Vault:
http://docs.ansible.com/playbooks_vault.html

Wir verwenden es als Tresor pro Umgebung. Um den Tresor zu bearbeiten, haben wir folgenden Befehl:
ansible-vault edit inventories/production/group_vars/all/vault

Wenn Sie eine Tresorvariable aufrufen möchten, müssen Sie ansible-playbook mit folgenden Parametern verwenden:
ansible-playbook -s --vault-password-file=~/.ansible_vault.password

Ja, wir speichern das Tresorkennwort im lokalen Verzeichnis im Klartext, aber es ist nicht gefährlicher als das Speichern des Stammkennworts für jedes System. Das Root-Passwort befindet sich in der Tresordatei oder Sie können es wie eine Sudoers-Datei für Ihren Benutzer / Ihre Gruppe haben.

Ich empfehle, die sudoers-Datei auf dem Server zu verwenden. Hier ist ein Beispiel für den Gruppenadministrator:
%admin ALL=(ALL) NOPASSWD:ALL

maxo
quelle
1

Nach fünf Jahren kann ich sehen, dass dies immer noch ein sehr relevantes Thema ist. Spiegelt etwas die Antwort von Leukos wider, die ich in meinem Fall am besten finde, indem ich nur ansible Tools verwende (ohne zentralisierte Authentifizierung, Token oder was auch immer). Dies setzt voraus, dass Sie auf allen Servern denselben Benutzernamen und denselben öffentlichen Schlüssel haben. Wenn Sie dies nicht tun, müssen Sie natürlich genauer sein und die entsprechenden Variablen neben den Hosts hinzufügen:

[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

Hinzufügen:

myserver_sudo: mysecretpassword

Dann:

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

Zumindest müssen Sie auf diese Weise nicht mehr die Variablen schreiben, die auf die Passwörter verweisen.

Lethargos
quelle
1

Die obige Lösung von @ toast38coza hat bei mir funktioniert. nur das sudo: ja ist in Ansible jetzt veraltet. Verwenden Sie stattdessen Werden und Werden_Benutzer .

tasks:
 - name: Restart apache service
   service: name=apache2 state=restarted
   become: yes
   become_user: root
Nätu
quelle
0

Wir können EXPECT BLOCK auch in ansible verwenden, um Bash zu erzeugen und es an Ihre Bedürfnisse anzupassen

- 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
quelle
0

Sehr einfach und nur in der Variablendatei hinzufügen:

Beispiel:

$ vim group_vars/all

Und fügen Sie diese hinzu:

Ansible_connection: ssh
Ansible_ssh_user: rafael
Ansible_ssh_pass: password123
Ansible_become_pass: password123
rafaelrms
quelle
Danke, aber ich denke du meinst ansible_become_pass statt Ansible_become_pass.
Krishnom
0

Nur ein Nachtrag, damit niemand sonst den Ärger durchmacht, den ich kürzlich gemacht habe:

AFAIK, die beste Lösung ist eine nach dem Vorbild von toast38coza. Wenn es sinnvoll ist, Ihre Passwortdateien und Ihr Playbook statisch miteinander zu verknüpfen, folgen Sie seiner Vorlage mit vars_files(oder include_vars). Wenn Sie sie getrennt halten möchten, können Sie den Tresorinhalt wie folgt in der Befehlszeile angeben:

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

Das ist im Nachhinein offensichtlich, aber hier sind die Fallstricke:

  1. Das verdammte @ Zeichen. Wenn Sie es weglassen, schlägt das Parsen im Hintergrund fehl und das Ansible-Playbook wird so fortgesetzt, als hätten Sie die Datei überhaupt nicht angegeben.

  2. Sie müssen den Inhalt des Tresors explizit importieren, entweder mit einer Befehlszeile --extra-vars / -e oder innerhalb Ihres YAML-Codes. Das --ask-vault-passFlag macht nichts für sich (außer Sie zur Eingabe eines Werts aufzufordern, der später verwendet werden kann oder nicht).

Mögen Sie Ihre "@" einfügen und eine Stunde sparen.

Eric Anderson
quelle
-3

Das hat bei mir funktioniert ... Erstellt Datei /etc/sudoers.d/90-init-users Datei mit NOPASSWD

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

Dabei ist "Benutzer" Ihre Benutzer-ID.

ScottM
quelle