cryptography - ¿Cómo creo un usuario y establezco una contraseña usando ansible?
pycrypto (8)
El ejemplo de python que se muestra en la documentación depende de la versión de crypt que se ejecuta en el sistema operativo que está utilizando.
Generé la cripta en OS X y el servidor al que estaba apuntando es ubuntu.
Debido a las diferencias en las que el sistema operativo ofrece la implementación de crypt, el resultado es diferente e incompatible.
Use esto en su lugar:
http://pythonhosted.org/passlib/
Passlib es una biblioteca de hashing de contraseñas para Python 2 y 3, que proporciona implementaciones multiplataforma de más de 30 algoritmos de hashing de contraseñas, así como un marco para administrar los hashes de contraseñas existentes. Está diseñado para ser útil para una amplia gama de tareas, desde verificar un hash encontrado en / etc / shadow, hasta proporcionar un hashing de contraseña completo para aplicaciones multiusuario.
>>> # import the hash algorithm
>>> from passlib.hash import sha512_crypt
>>> # generate new salt, and hash a password
>>> hash = sha512_crypt.encrypt("password")
>>> hash
''$ 6 $ redondea = 656000 $ BthPsosdEpqOM7Qd $ l / ln9nyEfxM67ea8Bvb79JoW50pGjf6iM87taIvfSmpjasE4 / wBG1.60pFS6W992T7Q1q2wikMbxYUvMHD1t1''
La documentation nos remite al example github, pero esto es un poco escaso y misterioso.
Dice esto:
# created with:
# crypt.crypt(''This is my Password'', ''$1$SomeSalt'')
password: $1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.
pero crypt.crypt
no emite lo que muestra el ejemplo. También utiliza MD5.
Intenté esto:
# python
import crypt
crypt.crypt(''This is my Password'', ''$6$somereallyniceandbigrandomsalt$'')
>> ''$69LxCegsnIwI''
pero el campo de contraseña del usuario debería obtener algo como esto:
password: $6$somereallyniceandbigrandomsalt$UqddPX3r4kH3UL5jq5/ZI.
que incluye tres delimitadores $ que separan los 6
(lo que significa que es un hash SHA-512), el salt y la contraseña encriptada.
Tenga en cuenta que los crypt.crypt Python no mencionan nada sobre el formato $ N.
Preguntas:
¿
crypt.crypt
supone que la sal, como se suministra acrypt.crypt
, termina con un $ final o está en formato $ N $ SALT ?Los documentos de Python se refieren a DES, pero ¿cómo se llama SHA-512 o MD5 y dónde está la documentación para esto?
¿Se supone que debo tomar la salida de
crypt.crypt
y cortar los primeros $ 6 y hacer $ N $ SALT $ CRYPTED ? ¿Es esto lo que ansible necesita?
Esto ha sido actualizado en los documentos de Ansible . Hay dos formas preferidas:
¿Cómo genero contraseñas encriptadas para el módulo de usuario?
La utilidad mkpasswd que está disponible en la mayoría de los sistemas Linux es una excelente opción:
mkpasswd --method=SHA-512
Si esta utilidad no está instalada en su sistema (por ejemplo, está usando OS X), aún puede generar estas contraseñas fácilmente usando Python. Primero, asegúrese de que la biblioteca de hashing de contraseña Passlib esté instalada.
pip install passlib
Una vez que la biblioteca está lista, los valores de contraseña de SHA512 se pueden generar de la siguiente manera:
python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"
Esto me funcionó (usando Python 2.7.4):
python
>>> import crypt
>>> crypt.crypt(''thisismypassword'', ''$6$Som3S@lt$'')
''$6$Som3S@lt$XGoe9ONI00NaTkYn46CLDr8TSkvkovahinFqy95vrSe5Hzx2999C9mgF76ODFRnXMJHUCWFHLdkYd3c7AB9WV.''
Tengo un vars.yml que se ve así:
---
password: $6$Som3S@lt$XGoe9ONI00NaTkYn46CLDr8TSkvkovahinFqy95vrSe5Hzx2999C9mgF76ODFRnXMJHUCWFHLdkYd3c7AB9WV.
y un playbook.yml como este:
---
- hosts: vagrant
vars_files:
- vars.yml
user: vagrant
tasks:
- name: create artefactual user
user: name=artefactual state=present password={{password}} shell=/bin/bash
Ejecuto mi libro de juegos usando vagrant, vagrant up
, y luego desde otra consola puedo enviar un ssh al vm recién creado usando el usuario artificial creado por ansible, con la contraseña thisismypassword
.
Acabo de copiar la salida de crypt.crypt en la variable ansible llamada contraseña y la utilicé. La salida de cripta que muestra en su pregunta parece demasiado breve, no estoy seguro de por qué lo obtuvo, ¿quizás una versión diferente de python?
Esto necesita pwgen
instalado en el host de destino:
- name: generate linux user password
local_action: shell /usr/bin/pwgen 16 1
register: generated_linux_user_password
Use hosts: localhost
, set_fact
y hostvars, si necesita que la ''variable'' esté disponible globalmente (los hechos se lean solo después de la creación):
{{hostvars[''localhost'']["new_fact"]}}
He estado usando el siguiente comando de shell para establecer la contraseña.
- name: "Set user password: someuser"
command: ''echo "somepassword"| passwd --stdin "someuser"''
sudo: yes
Puede usar los filtros jinja2 que tienen la capacidad de manejar la generación de contraseñas encriptadas. Aquí hay un ejemplo de trabajo para crear el usuario de Linux con la contraseña proporcionada:
- name: Creating Linux User
user:
name: "{{ myuser }}"
password: "{{ mypassword | password_hash(''sha512'') }}"
Espero que esto te ayude a ti y a los demás.
Tomé la respuesta de @ felix y la convertí en un guión que podría incluir en un proyecto docker en el que estoy trabajando. Sé que muchos desarrolladores utilizan macOS / OSX y que no hay mkpasswd
en esa plataforma, así que les estoy guardando el Google.
He añadido las siguientes opciones:
- PROCESS_TIME (booleano)
- Habilita la segunda línea de salida con número de rondas y tiempo de CPU
- RONDAS (entero)
- Anula el valor de default_rounds que está sintonizado para tomar ~ 300 ms en un sistema "promedio". Desea un mínimo de 100 ms, pero debe ser lo mejor que pueda pagar.
#!/usr/bin/env python3
# Because OSX doesn''t have mkpasswd...
# Based on https://.com/a/17992126/117471
# python3 -c "from passlib.hash import sha512_crypt; print(sha512_crypt.encrypt(input()))" <<< bruno # NOQA
# Usage:
#
# $ ./mkpasswd.py
# Password:
# $6$rounds=656000$pfFmQISGcjWHOCxW$rBptiSK.tqSPnUiq6KiSHzz6LvvW/x1SjkkWFwxWB9Dt75NLNBs0N3OyGV4K5ejjBs/u.o3jtigvUKbmmwVQP.
#
# $ PROCESS_TIME=1 ./mkpasswd.py
# Password:
# $6$rounds=656000$e0OGrad82DBrUo9T$ldqtOdN54gmXI6nb0D.Y5mm5ih.LIQm/Ep/bkNL76.3hE65FqXA9wyZ.M5YOrv6dSvwhPAktXGJ6LJT0Fgd4x.
# 656000 rounds in 1.008705 seconds of cpu time
#
# $ ROUNDS=1280000 PROCESS_TIME=1 ./mkpasswd.py <<< bruno
# $6$rounds=1280000$QO5FSyw5rQpiY6PI$0zRMJ4RzCbH61XxIdpsUm/79.VZ13Mm9TBN9GvJwt1LI1U5FVzakrLya5VJsXlTou3p5ZeWmo29bIUjubRuc31
# 1280000 rounds in 1.9206560000000001 seconds of cpu time
import os
import sys
import time
from getpass import getpass
from passlib.hash import sha512_crypt
rounds = os.environ.get(''ROUNDS'')
if not rounds:
rounds = sha512_crypt.default_rounds
passwd = input() if not sys.stdin.isatty() else getpass()
proc = sha512_crypt.using(rounds=rounds)
start = time.process_time()
out = proc.encrypt(passwd)
end = time.process_time()
print(out)
if os.environ.get(''PROCESS_TIME''):
print(''{} rounds in {} seconds of cpu time''.format(rounds, end-start))
prueba de esta manera
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"