Especifique la contraseña de sudo para Ansible

225

¿Cómo especifico una contraseña de sudo para Ansible de manera no interactiva?

Estoy ejecutando el libro de jugadas Ansible de esta manera:

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

Pero quiero ejecutarlo así:

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

¿Hay alguna manera? Quiero automatizar la implementación de mi proyecto tanto como sea posible.

Slava Fomin II
fuente
44
Ver también: serverfault.com/questions/560106/…
utapyngo

Respuestas:

170

Puede pasar variable en la línea de comando a través de --extra-vars "name=value". La variable de contraseña de sudo es ansible_sudo_pass. Entonces su comando se vería así:

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

Actualización 2017 : Ansible 2.2.1.0 ahora usa la var ansible_become_pass. Cualquiera parece funcionar.

Alexandr Nikitin
fuente
77
Desde la perspectiva de la seguridad, la mejor respuesta es si agrega lo siguiente: history -cdespués de la ejecución del yml.
kiltek
12
@kiltek: o agregue un espacio extra al comienzo de la línea (en bash) que * no * escribirá la línea .bash_history.
ccpizza
44
No es una buena práctica pasar contraseñas en la línea de comandos. Cualquiera podrá ver la contraseña en la lista de procesos, mientras se ejecuta el comando ...
Pavel Chernikov
22
Aún así, no lo hagas. --ask-sudo-pass
JasonG
2
@scrutari Es perfectamente válido en algunas situaciones: por ejemplo: cambiar de una contraseña inicial predeterminada, mundialmente conocida, para inyectar la clave ssh pública del usuario ... Piense en la configuración inicial de un sistema recién reimpreso.
Ceredig
236

Los documentos recomiendan enfáticamente no establecer la contraseña de sudo en texto sin formato y, en su lugar, usarla --ask-sudo-passen la línea de comando cuando se ejecutaansible-playbook


Actualización 2016:

Ansible 2.0 (no 100% cuando) marcado --ask-sudo-passcomo obsoleto. Los documentos ahora recomiendan usar en su --ask-become-passlugar, al mismo tiempo que cambian el uso de sudoen sus libros de jugadas con become.

deefour
fuente
16
Sí, puedo ver por qué se recomienda esto. Sin embargo, cuando usamos Ansible como parte del proceso de implementación, ¿cuál es la mejor manera de automatizar esto? No es muy conveniente detenerse en medio del proceso de implementación y pedirle al usuario que ingrese la contraseña de sudo.
Slava Fomin II
99
Nota --ask-sudo-pass se puede abreviar a -K, sin embargo, por lo que puedo ver, no hay forma de manejar un libro de jugadas que se ejecute en varios servidores con contraseñas diferentes (solo se le pide una vez), así que creo que sin contraseña sudo es el camino a seguir.
William Turrell
1
No parece funcionar pero la siguiente sugerencia ("some-host ansible_sudo_pass = 'foobar'") sí
nadavkav
--ask-sudo-pass fue desaprobado anteriormente, en 1.9
Chris Betti el
Me encantaría actualizar la respuesta con un enlace de origen si tiene uno.
deefour
106

Probablemente la mejor manera de hacerlo, suponiendo que no pueda usar la solución NOPASSWD proporcionada por scottod es usar la solución de Mircea Vutcovici en combinación con la bóveda Ansible .

Por ejemplo, puede tener un libro de jugadas como este:

- hosts: all

  vars_files:
    - secret

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

Aquí incluimos un archivo llamado secretque contendrá nuestra contraseña de sudo.

Utilizaremos ansible-vault para crear una versión encriptada de este archivo:

ansible-vault create secret

Esto le pedirá una contraseña, luego abra su editor predeterminado para editar el archivo. Puedes poner tu ansible_sudo_passaquí.

por ejemplo secret::

ansible_sudo_pass: mysudopassword

Guarde y salga, ahora tiene un secretarchivo cifrado que Ansible puede descifrar cuando ejecuta su libro de jugadas. Nota: puede editar el archivo con ansible-vault edit secret(e ingresar la contraseña que utilizó al crear el archivo)

La pieza final del rompecabezas es proporcionar a Ansible una --vault-password-fileque usará para descifrar su secretarchivo.

Cree un archivo llamado vault.txty en ese lugar coloque la contraseña que utilizó al crear su secretarchivo. La contraseña debe ser una cadena almacenada como una sola línea en el archivo.

De los documentos de Ansible:

.. asegúrese de que los permisos en el archivo sean tales que nadie más pueda acceder a su clave y no agregue su clave al control de origen

Finalmente: ahora puedes ejecutar tu libro de jugadas con algo como

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

Lo anterior supone el siguiente diseño de directorio:

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

Puede leer más sobre Ansible Vault aquí: https://docs.ansible.com/playbooks_vault.html

tostadas38coza
fuente
55
Nota: a partir de ansible 1.9, parece que ya no puede usar la variable ansible_sudo_pass (o ansible_become_pass): "fatal: [...] => Falta la contraseña"
toast38coza
66
Estoy usando esta solución en producción, jenkins almacena la contraseña de la bóveda como una variable de entorno ofuscada, la escribe en tiempo de ejecución en un archivo temporal y procede a llamar a ansible.
simone cittadini
66
o más simplemente: ansible-vault create group_vars/all/ansible.ymly agregar ansible_sudo_pass: yourpasswordallí. No es necesario cambiar los libros de jugadas o el inventario
Bouke Versteegh
1
Intenté esto pero recibí este error:fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
JohnnyQ
8
¿De qué sirve una bóveda si almacena la contraseña de la bóveda en texto plano justo al lado?
Erik
44

Mirando el código (runner/__init__.py ), creo que probablemente pueda configurarlo en su archivo de inventario:

[whatever]
some-host ansible_sudo_pass='foobar'

Parece que también hay alguna disposición en el ansible.cfgarchivo de configuración, pero no implementada en este momento ( constants.py).

leucos
fuente
77
Una excelente manera de configurar esto de forma segura sería almacenar esto en el directorio host_varsor group_varsy luego cifrar el archivo usando ansible-vault
Kyle
44

No creo que ansible le permita especificar una contraseña en las banderas como desee. Puede haber algún lugar en las configuraciones que se puede configurar, pero esto haría que el uso de ansible sea menos seguro en general y no se recomendaría.

Una cosa que puede hacer es crear un usuario en la máquina de destino y otorgarles privilegios de sudo sin contraseña para todos los comandos o una lista restringida de comandos.

Si ejecuta sudo visudoe ingresa una línea como la siguiente, entonces el usuario 'usuario privilegiado' no debería tener que ingresar una contraseña cuando ejecuta algo como sudo service xxxx start:

%privilegedUser ALL= NOPASSWD: /usr/bin/service
escocés
fuente
77
@bschlueter, ¿estás respaldando las malas prácticas?
Stephen
1
No creo que sea una buena idea. Usar --ask-sudo-pass tiene sentido para mí.
kgpdeveloper
@simone cittadini Estoy totalmente de acuerdo, de hecho, esa es la respuesta que iba a dar. Este es un riesgo de seguridad.
einarc
Es menos riesgoso para la seguridad si está utilizando sudo sin contraseña para realizar la puesta en escena / producción, pero desea utilizar estas respuestas para evitar tener que escribir la contraseña de inicio de sesión de su computadora portátil local cuando se implementa en su host local cada 15 minutos durante todo el día todos los días.
Jonathan Hartley
¿Cómo agrega esta línea usando Ansible?
Matthias
21

La contraseña de sudo se almacena como una variable llamada ansible_sudo_pass. Puede configurar esta variable de varias maneras:

Por host, en su archivo de hosts de inventario ( inventory/<inventoryname>/hosts)

[server]
10.0.0.0 ansible_sudo_pass=foobar

Por grupo, en su archivo de grupos de inventario ( inventory/<inventoryname>/groups)

[server:vars]
ansible_sudo_pass=foobar

Por grupo, en grupo vars ( group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"

Por grupo, encriptado ( ansible-vault create group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"
Bouke Versteegh
fuente
18

Puede establecer la contraseña para un grupo o para todos los servidores a la vez:

[all:vars]
ansible_sudo_pass=default_sudo_password_for_all_hosts

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

Me estaba arrancando el pelo sobre este, ahora encontré una solución que hace lo que quiero:

1 archivo encriptado por host que contiene la contraseña de 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

luego crea para cada host un archivo var cifrado de esta manera:

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

con contenido

ansible_sudo_pass: "my_sudo_pass_for_host_node-0"

cómo organiza la contraseña de la bóveda (ingrese a través de --ask-vault-pass) o mediante cfg

basado en esto, sospecho que puede cifrar todo el archivo de hosts ...

greenone83
fuente
Cifrar usando la bóveda tiene más sentido para mí, aunque luché para usarlos ansible-playback. Tuve que usar -e @vault/filename.extpara usar la bóveda con mi ansible-playbookllamada.
Alex
9

Una forma más inteligente de hacer esto es almacenar su sudocontraseña en una bóveda segura como LastPass o KeePass y luego pasarla a ansible-playbookusar el -e@pero, en lugar de codificar el contenido en un archivo real, puede usar la construcción -e@<(...)para ejecutar un comando en un sub-shell y redirige su salida (STDOUT) a un descriptor de archivo anónimo, alimentando efectivamente la contraseña al -e@<(..).

Ejemplo

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

Lo anterior está haciendo varias cosas, vamos a desglosarlo.

  • ansible-playbook -i /tmp/hosts pb.yml - obviamente, ejecutar un libro de jugadas a través de ansible-playbook
  • $(lpass show folder1/item1 --password)" - ejecuta la CLI de LastPass lpass y recupera la contraseña para usar
  • echo "ansible_sudo_pass: ...password..." - toma la cadena 'ansible_sudo_pass:' y la combina con la contraseña proporcionada por lpass
  • -e@<(..)- pone todo lo anterior junto, y conecta la subshell de <(...)como un descriptor de archivo para ansible-playbookconsumir.

Futuras mejoras

Si prefiere no escribir eso cada vez, simplemente puede hacer cosas así. Primero crea un alias en tu .bashrclike así:

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

Ahora puedes ejecutar tu libro de jugadas así:

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

Referencias

slm
fuente
1
¡Usar una subshell es una idea muy inteligente! Para aquellos que se preguntan, esto es lo que parece con la CLI de 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
Me gusta esto porque cuando revisé el historial de bach, la contraseña no estaba expuesta en texto sin formato. También es cierto que si la auditoría del sistema está habilitada, el comando se registra como lectura de un archivo, por ejemplo, /dev/fd/63si la contraseña se encuentra en un descriptor de archivo temporal, no se revela.
JPvRiel
5

Si se siente cómodo manteniendo las contraseñas en archivos de texto sin formato, otra opción es usar un archivo JSON con el parámetro --extra-vars (asegúrese de excluir el archivo del control de origen):

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

Ansible ha admitido esta opción desde 1.3 .

sidecarcat
fuente
5

puede escribir la contraseña de sudo para su libro de jugadas en el archivo de hosts de esta manera:

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

Se ha sugerido la bóveda de Ansible un par de veces aquí, pero prefiero git-crypt para cifrar archivos confidenciales en mis libros de jugadas. Si está utilizando git para mantener sus libros de jugadas ansibles, es muy fácil. El problema que he encontrado con Ansible Vault es que inevitablemente encuentro copias cifradas del archivo con el que quiero trabajar y tengo que descifrarlo antes de poder trabajar. git-cryptofrece un mejor flujo de trabajo de la OMI.

Con esto, puede poner sus contraseñas en una variable en su libro de jugadas y marcar su libro de jugadas como un archivo encriptado de .gitattributesesta manera:

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

Su libro de jugadas se cifrará de forma transparente en Github. Luego solo necesita instalar su clave de cifrado en el host que utiliza para ejecutar ansible, o seguir las instrucciones en la documentación para configurarlo gpg.

Hay un buen Q&A sobre el reenvío de gpgclaves como las ssh-agentclaves SSH de reenvío aquí: /superuser/161973/how-can-i-forward-a-gpg-key-via-ssh-agent .

usuario2432419
fuente
3

Puede usar la sshpassutilidad de la siguiente manera,

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

Usando ansible 2.4.1.0 y lo siguiente funcionará:

[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

Y simplemente ejecute el libro de jugadas con este inventario como:

ansible-playbook -i inventory copyTest.yml
Hearen
fuente
3

Mi truco para automatizar esto fue usar una variable de entorno y acceder a ella a través de --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'".

Exporte una var env, pero evite el historial de bash / shell (anteponer un espacio u otros métodos). P.ej:

     export ANSIBLE_BECOME_PASS='<your password>'

Busque la ansible_become_passvariable env mientras pasa la variable adicional a ansible-playbook, por ejemplo:

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

Buenas respuestas alternativas:

JPvRiel
fuente
2

Puedes usar la bóveda ansible que codificará su contraseña en la bóveda encriptada. Después de eso, puedes usar variables de vault en playbooks.

Alguna documentación sobre la bóveda ansible:
http://docs.ansible.com/playbooks_vault.html

Lo estamos utilizando como bóveda por entorno. Para editar la bóveda tenemos comando como:
ansible-vault edit inventories/production/group_vars/all/vault

Si desea llamar a la variable de bóveda, debe usar ansible-playbook con parámetros como:
ansible-playbook -s --vault-password-file=~/.ansible_vault.password

Sí, estamos almacenando la contraseña de la bóveda en el directorio local en texto plano, pero no es más peligroso como almacenar la contraseña de root para cada sistema. La contraseña de root está dentro del archivo de almacenamiento o puede tenerla como un archivo sudoers para su usuario / grupo.

Estoy recomendando usar el archivo sudoers en el servidor. Aquí hay un ejemplo para el administrador del grupo:
%admin ALL=(ALL) NOPASSWD:ALL

maxo
fuente
1

Después de cinco años, puedo ver que este sigue siendo un tema muy relevante. Algo similar a la respuesta de leucos, que encuentro la mejor en mi caso, usando solo herramientas ansibles (sin autenticación centralizada, tokens o lo que sea). Esto supone que tiene el mismo nombre de usuario y la misma clave pública en todos los servidores. Si no lo hace, por supuesto necesitaría ser más específico y agregar las variables correspondientes al lado de los hosts:

[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

Añadir:

myserver_sudo: mysecretpassword

Luego:

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

Al menos de esta manera, no tiene que escribir más las variables que apuntan a las contraseñas.

Lethargos
fuente
1

La solución anterior de @ toast38coza funcionó para mí; solo ese sudo: sí está obsoleto en Ansible ahora. Uso convertirse y become_user lugar.

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

también podemos usar EXPECT BLOCK en ansible para generar bash y personalizarlo según sus necesidades

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

Muy simple, y solo agregue en el archivo variable:

Ejemplo:

$ vim group_vars/all

Y agregue estos:

Ansible_connection: ssh
Ansible_ssh_user: rafael
Ansible_ssh_pass: password123
Ansible_become_pass: password123
rafaelrms
fuente
Gracias, pero creo que te refieres a ansible_become_pass en lugar de Ansible_become_pass.
Krishnom
0

Solo un apéndice, para que nadie más pase por la molestia que hice recientemente:

AFAIK, la mejor solución es una de las líneas generales de tostadas38coza de arriba. Si tiene sentido vincular sus archivos de contraseña y su libro de jugadas de forma estática, siga su plantilla con vars_files(o include_vars). Si desea mantenerlos separados, puede proporcionar el contenido de la bóveda en la línea de comando de la siguiente manera:

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

Eso es obvio en retrospectiva, pero aquí están las trampas:

  1. Ese sangriento signo @ . Si lo deja fuera, el análisis fallará en silencio , y ansible-playbook procederá como si nunca hubiera especificado el archivo en primer lugar.

  2. Debe importar explícitamente el contenido de la bóveda, ya sea con una línea de comandos --extra-vars / -e o dentro de su código YAML. El --ask-vault-passindicador no hace nada por sí mismo (además de pedirle un valor que puede o no usarse más adelante).

Puede incluir sus "@" y ahorrar una hora.

Eric Anderson
fuente
-3

Esto funcionó para mí ... Archivo creado /etc/sudoers.d/90-init-users archivo con NOPASSWD

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

donde "user" es su ID de usuario.

ScottM
fuente