bash - register - Crear un nuevo usuario y contraseña con Ansible
ansible windows (16)
Así es como funcionó para mí
- hosts: main
vars:
# created with:
# python -c "from passlib.hash import sha512_crypt; print sha512_crypt.encrypt(''<password>'')"
# above command requires the PassLib library: sudo pip install passlib
- password: ''$6$rounds=100000$H/83rErWaObIruDw$DEX.DgAuZuuF.wOyCjGHnVqIetVt3qRDnTUvLJHBFKdYr29uVYbfXJeHg.IacaEQ08WaHo9xCsJQgfgZjqGZI0''
tasks:
- user: name=spree password={{password}} groups=sudo,www-data shell=/bin/bash append=yes
sudo: yes
Tengo una tarea ansible que crea un nuevo usuario en ubuntu 12.04;
- name: Add deployment user
action: user name=deployer password=mypassword
se completa como se esperaba, pero cuando inicio sesión como ese usuario y trato de sudo con la contraseña que configuro, siempre dice que es incorrecta. ¿Qué estoy haciendo mal?
Cómo crear una contraseña encriptada para pasar a la password
var a user
tarea de user
Ansible (del comentario de @Brendan Wood):
openssl passwd -salt ''some_plain_salt'' -1 ''some_plain_pass''
El resultado se verá así:
$1$some_pla$lmVKJwdV3Baf.o.F0OOy71
Ejemplo de tarea de user
:
- name: Create user
user: name="my_user" password="$1$some_pla$lmVKJwdV3Baf.o.F0OOy71"
UPD: crypt usando SHA-512 ver here y here :
Pitón
$ python -c "import crypt, getpass, pwd; print crypt.crypt(''password'', ''/$6/$saltsalt/$'')"
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
Perl
$ perl -e ''print crypt("password","/$6/$saltsalt/$") . "/n"''
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
Rubí
$ ruby -e ''puts "password".crypt("$6$saltsalt$")''
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
Combinando algunas soluciones de arriba, creé un libro de jugadas que genera automáticamente hashes de contraseñas correctos basados en contraseñas de texto plano almacenadas en un archivo ansible vault local codificado:
---
- hosts: [your hosts]
tasks:
- include_vars: [path to your encrypted vault file]
- local_action: "command openssl passwd -salt ''{{password_salt}}'' -1 ''{{password}}''"
register: password_hash
- user: >
name=[your username]
state=present
password="{{password_hash.stdout}}"
Ejecute este comando utilizando la opción "--ask-vault-pass" para descifrar su archivo de bóveda (consulte ansible-vault para obtener información sobre cómo administrar una bóveda encriptada).
El módulo Ansible ''user'' gestiona a los usuarios de forma idempotente . En el libro de jugadas debajo de la primera tarea declara state = present para el usuario. Tenga en cuenta que '' register: newuser '' en la primera acción ayuda a la segunda acción a determinar si el usuario es nuevo (newuser.changed == True) o existente ( newuser.changed==False
), solo para generar la contraseña una vez.
El libro de jugadas de Ansible tiene:
tasks:
- name: create deployment user
user:
name: deployer
createhome: yes
state: present
register: newuser
- name: generate random password for user only on creation
shell: /usr/bin/openssl rand -base64 32 | passwd --stdin deployer
when: newuser.changed
El objetivo del rol en esta respuesta es generar una contraseña aleatoria para new_user_name y caducar la contraseña de inmediato. El new_user_name es necesario para cambiar la contraseña en su primer inicio de sesión.
create_user.yml:
---
# create_user playbook
- hosts: your_host_group
become: True
user: ansible
roles:
- create_user
roles / create_user / tasks / main.yml:
---
# Generate random password for new_user_name and the new_user_name
# is required to change his/her password on first logon.
- name: Generate password for new user
shell: makepasswd --chars=20
register: user_password
- name: Generate encrypted password
shell: mkpasswd --method=SHA-512 {{ user_password.stdout }}
register: encrypted_user_password
- name: Create user account
user: name={{ new_user_name }}
password={{ encrypted_user_password.stdout }}
state=present
append=yes
shell="/bin/bash"
update_password=always
when: new_user_name is defined and new_user_name in uids
register: user_created
- name: Force user to change password
shell: chage -d 0 {{ new_user_name }}
when: user_created.changed
- name: User created
debug: msg="Password for {{ new_user_name }} is {{ user_password.stdout }}"
when: user_created.changed
Cuando quieres crear un nuevo usuario:
ansible-playbook -i hosts.ini create_user.yml --extra-vars "new_user_name=kelvin"
Esta es la manera fácil:
---
- name: Create user
user: name=user shell=/bin/bash home=/srv/user groups=admin,sudo generate_ssh_key=yes ssh_key_bits=2048
- name: Set password to user
shell: echo user:plain_text_password | sudo chpasswd
no_log: True
La definición de tarea para el módulo de usuario debe ser diferente en la última versión de Ansible.
tasks:
- user: name=test password={{ password }} state=present
La respuesta de Mxx es correcta, pero el método crypt.crypt()
python no es seguro cuando están involucrados diferentes sistemas operativos (relacionado con el algoritmo glibc hash utilizado en su sistema).
Por ejemplo, no funcionará si genera su hash de MacOS y ejecuta un libro de jugadas en Linux. En tal caso, puede usar passlib ( pip install passlib
para instalar localmente).
from passlib.hash import md5_crypt
python -c ''import crypt; print md5_crypt.encrypt("This is my Password,salt="SomeSalt")''
''$1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.''
Ninguna de las soluciones funcionó directamente en mi Mac controlando Ubuntu. Entonces, por el bien de los demás, combinando las respuestas de Mxx y JoelB, aquí está la solución actual de Python 3:
pip3 install passlib
python3 -c ''from passlib.hash import md5_crypt; /
print(md5_crypt.encrypt("This is my Password", salt="SomeSalt"))''
El resultado será $1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.
como en la respuesta de Mxx.
Mejor aún , use SHA512 en lugar de MD5:
python3 -c ''from passlib.hash import sha512_crypt; /
print(sha512_crypt.encrypt("This is my Password", salt="SomeSalt"))''
Resultado:
$ 6 $ rondas = 656000 $ SomeSalt $ oYpmnpZahIsvn5FK8g4bDFEAmGpEN114Fe6Ko4HvinzFaz5Rq2UXQxoJZ9ZQyQoi9zaBo3gBH / FEAov3FHv48
Puede que sea demasiado tarde para responder esto, pero recientemente descubrí que los filtros jinja2 tienen la capacidad de manejar la generación de contraseñas encriptadas. En mi main.yml
estoy generando la contraseña encriptada como:
- name: Creating user "{{ uusername }}" with admin access
user:
name: {{ uusername }}
password: {{ upassword | password_hash(''sha512'') }}
groups: admin append=yes
when: assigned_role == "yes"
- name: Creating users "{{ uusername }}" without admin access
user:
name: {{ uusername }}
password: {{ upassword | password_hash(''sha512'') }}
when: assigned_role == "no"
- name: Expiring password for user "{{ uusername }}"
shell: chage -d 0 "{{ uusername }}"
"uusername" y "upassword" se pasan como --extra-vars
al libro de jugadas y notamos que he usado el filtro jinja2 aquí para encriptar la contraseña aprobada.
He agregado el siguiente tutorial relacionado con esto a mi blog
Puede usar ansible-vault para usar claves secretas en libros de jugadas. Define tu contraseña en yml.
ex. pase: secreto o
user:
pass: secret
name: fake
encripta tu archivo de secretos con:
ansible-vault encrypt /path/to/credential.yml
ansible pedirá una contraseña para encriptarlo. (Explicaré cómo usar ese pase)
Y luego puedes usar tus variables donde quieras. Nadie puede leerlos sin vault-key.
Uso de la clave de Vault:
a través de pasar el argumento al ejecutar el libro de jugadas.
--ask-vault-pass: secret
o puede guardar en un archivo como password.txt y esconderse en algún lugar. (útil para usuarios de CI)
--vault-password-file=/path/to/file.txt
En tu caso: incluye vars yml y usa tus variables.
- include_vars: /path/credential.yml
- name: Add deployment user
action: user name={{user.name}} password={{user.pass}}
Quiero proponer otra solución:
- name: Create madhead user
user:
name: madhead
password: "{{ ''password'' | password_hash(''sha512'') }}"
shell: /bin/zsh
update_password: on_create
register: madhead
- name: Force madhead to change password
shell: chage -d 0 madhead
when: madhead.changed
¿Por qué es mejor? Como ya se ha observado aquí, las jugadas de Ansible deben ser idempotentes. Deberías pensar en ellos no como una secuencia de acciones en estilo imperativo, sino como un estado deseado, estilo declarativo. Como resultado, debería poder ejecutarlo varias veces y obtener el mismo resultado, el mismo estado del servidor.
Todo esto suena genial, pero hay algunos matices. Uno de ellos es administrar usuarios. "Estado deseado" significa que cada vez que ejecuta una jugada que crea un usuario, se actualizará para que coincida exactamente con ese estado. Por "actualizado" quiero decir que su contraseña también será cambiada. Pero lo más probable es que no sea lo que necesitas. Por lo general, necesita crear un usuario, configurar y caducar su contraseña una sola vez, las ejecuciones posteriores no deberían actualizar su contraseña.
Afortunadamente, Ansible tiene el atributo update_password
en user
módulo de user
que resuelve este problema. Al mezclar esto con las variables registradas , también puede caducar su contraseña solo cuando el usuario esté realmente actualizado.
Tenga en cuenta que si cambia el shell del usuario manualmente (supongamos que no le gusta el shell que el malvado administrador forzó en su jugada), el usuario se actualizará, por lo tanto, su contraseña caducará.
También tenga en cuenta cómo puede usar fácilmente las contraseñas iniciales de texto sin formato en las jugadas. No es necesario codificarlos en otro lugar y pegar hashes, puedes usar el filtro Jinja2 para eso. Sin embargo, esto puede ser un defecto de seguridad si alguien ingresa antes de que lo haga inicialmente.
Si desea realizar esto como un comando ad-hoc de Ansible, puede hacer lo siguiente:
$ password=''SomethingSecret!''
$ ansible 192.168.1.10 -i some_inventory -b -m user -a "name=joe_user /
update_password=always password=/"{{ /"$password/" | password_hash(''sha512'') }}/""
Salida del comando anterior:
192.168.1.10 | SUCCESS => {
"append": false,
"changed": true,
"comment": "Joe User",
"group": 999,
"home": "/home/joe_user",
"move_home": false,
"name": "joe_user",
"password": "NOT_LOGGING_PASSWORD",
"shell": "/bin/bash",
"state": "present",
"uid": 999
}
Si lee el manual de Ansible para user
módulo de user
, lo dirigirá al Repo github Ansible-examples para obtener más información sobre cómo usar el parámetro de password
.
Allí verá que su contraseña debe ser hash.
- hosts: all
user: root
vars:
# created with:
# python -c ''import crypt; print crypt.crypt("This is my Password", "$1$SomeSalt$")''
password: $1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.
tasks:
- user: name=tset password={{password}}
Si su libro de jugadas o su línea de comando tiene su contraseña tal como está en texto plano, esto significa que su hash de contraseña registrado en su archivo oculto es incorrecto. Eso significa que cuando intentes autenticarte con tu contraseña, su hash nunca coincidirá.
Además, consulte las FAQ Ansible con respecto a algunos matices del parámetro de contraseña y cómo usarlo correctamente.
Solo para completarlo, publicaré el comando ad-hoc usando ansible, ya que también hay un retén allí.
Primero intente generar una contraseña encriptada usando la utilidad mkpasswd que está disponible en la mayoría de los sistemas Linux:
mkpasswd --method=SHA-512
Luego pruebe el comando ansible ad-hock:
ansible all -m user -a ''name=testuser shell=/bin/bash /
comment="Test User" password=$6$XXXX'' -k -u admin --sudo
Pero asegúrate de:
- El comando está entre comillas simples y NO es doble, de lo contrario su contraseña nunca funcionará
- Lo ejecuta con
--sudo
o termina con un error como (useradd: cannot lock /etc/passwd; try again later
)
prueba así
vars_prompt:
- name: "user_password"
prompt: "Enter a password for the user"
private: yes
encrypt: "md5_crypt" #need to have python-passlib installed in local machine before we can use it
confirm: yes
salt_size: 7
- name: "add new user" user: name="{{user_name}}" comment="{{description_user}}" password="{{user_password}}" home="{{home_dir}}" shell="/bin/bash"