J'ai une tâche ansible qui crée un nouvel utilisateur sur Ubuntu 12.04;
- name: Add deployment user
action: user name=deployer password=mypassword
il se termine comme prévu, mais lorsque je me connecte en tant qu'utilisateur et que j'essaie d'utiliser Sudo avec le mot de passe que j'ai défini, il indique toujours que c'est incorrect. Qu'est-ce que je fais mal?
Si vous lisez le manuel de Ansible pour le module user
, il vous dirigera vers Ansible-examples github repo pour plus de détails sur l'utilisation du paramètre password
.
Là, vous verrez que votre mot de passe doit être haché.
- 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 votre ligne de commande playbook ou ansible contient votre mot de passe tel quel, cela signifie que le hachage du mot de passe enregistré dans votre fichier shadow est incorrect. Cela signifie que lorsque vous essayez de vous authentifier avec votre mot de passe, son hachage ne correspondra jamais.
De plus, voir Ansible FAQ à propos des nuances du paramètre de mot de passe et de la façon de l’utiliser correctement.
Je suis peut-être trop tard pour répondre à cette question, mais récemment, j’ai découvert que les filtres jinja2 étaient capables de gérer la génération de mots de passe chiffrés. Dans mon main.yml
, je génère le mot de passe crypté sous la forme:
- 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 }}"
"nom d'utilisateur" et "upassword" sont passés en tant que --extra-vars
au playbook et notez que j'ai utilisé le filtre jinja2 ici pour chiffrer le mot de passe transmis.
J'ai ajouté ci-dessous un tutoriel lié à cela sur mon blog
Je veux proposer encore une autre solution:
- 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
Pourquoi c'est mieux? Comme cela a déjà été noté ici, les jeux Ansible devraient être idempotents. Vous devriez les considérer non pas comme une séquence d'actions dans un style impératif, mais comme un état souhaité, un style déclaratif. En conséquence, vous devriez pouvoir l'exécuter plusieurs fois et obtenir le même résultat, le même état de serveur.
Tout cela sonne bien, mais il y a quelques nuances. L'un d'eux est la gestion des utilisateurs. "Etat souhaité" signifie que chaque fois que vous jouez une pièce qui crée un utilisateur, celle-ci sera mise à jour pour correspondre à cet état. Par "mis à jour", je veux dire que son mot de passe sera changé aussi. Mais ce n'est probablement pas ce dont vous avez besoin. Habituellement, vous devez créer un utilisateur, définir et supprimer son mot de passe une seule fois. Les lancements ultérieurs ne doivent pas mettre à jour son mot de passe.
Heureusement, Ansible a l'attribut update_password
dans le module user
qui résout ce problème. En mélangeant ceci avec variables enregistrées vous pouvez également expirer son mot de passe uniquement lorsque l'utilisateur est réellement mis à jour.
Notez que si vous changez le shell de l'utilisateur manuellement (supposez que vous n'aimez pas le shell que l'administrateur du diable a forcé dans son jeu), l'utilisateur sera mis à jour et son mot de passe expirera.
Notez également comment vous pouvez facilement utiliser les mots de passe initiaux en texte brut dans les jeux. Pas besoin de les encoder ailleurs et de coller des hachages, vous pouvez utiliser filtre Jinja2 pour cela. Cependant, cela peut être une faille de sécurité s'il arrive que quelqu'un se connecte avant vous.
Le module "utilisateur" Ansible gère les utilisateurs, de la manière idempotent. Dans le livre de jeu ci-dessous, la première tâche déclare state = present pour l'utilisateur. Notez que 'register: newuser' dans la première action permet à la deuxième action de déterminer si l'utilisateur est nouveau (newuser.changed == True) ou existant (newuser.changed==False
), pour générer le mot de passe une seule fois.
Le playbook Ansible a:
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
essayez comme ça
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"
Le rôle de cette réponse est de générer un mot de passe aléatoire pour new_user_name et d'expirer le mot de passe immédiatement. Le nouveau_nom_utilisateur.__ est requis pour changer le mot de passe lors de sa première connexion.
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
Lorsque vous souhaitez créer un nouvel utilisateur:
ansible-playbook -i hosts.ini create_user.yml --extra-vars "new_user_name=kelvin"
C'est le moyen le plus simple:
---
- 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
Voici comment cela a fonctionné pour moi
- 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
Vous pouvez utiliser ansible-vault pour utiliser des clés secrètes dans les playbooks. Définissez votre mot de passe en yml.
ex. passe: secret .__ ou
user:
pass: secret
name: fake
chiffrer votre fichier de secrets avec:
ansible-vault encrypt /path/to/credential.yml
ansible demandera un mot de passe pour le chiffrer. (Je vais expliquer comment utiliser ce laissez-passer)
Et ensuite, vous pouvez utiliser vos variables où vous voulez. Personne ne peut les lire sans clé de coffre.
Utilisation de la clé de coffre:
en passant l'argument lors de l'exécution de playbook.
--ask-vault-pass: secret
ou vous pouvez enregistrer dans un fichier tel que password.txt et vous cacher quelque part. (utile pour les utilisateurs de CI)
--vault-password-file=/path/to/file.txt
Dans votre cas: Incluez vars yml et utilisez vos variables.
- include_vars: /path/credential.yml
- name: Add deployment user
action: user name={{user.name}} password={{user.pass}}
En combinant quelques solutions précédentes, j'ai créé un livre de jeu générant automatiquement des hachages de mots de passe corrects, basés sur des mots de passe en clair, stockés dans un fichier local et crypté:
---
- 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}}"
Exécutez cette commande en utilisant l’option "--ask-vault-pass" pour déchiffrer votre fichier de coffre (voir ansible-vault pour plus d’informations sur la gestion d’un coffre chiffré).
La définition de tâche du module user doit être différente dans la dernière version d'Ansible.
tasks:
- user: name=test password={{ password }} state=present
Par souci d’exhaustivité, je publierai la commande ad-hoc en utilisant ansible car il ya également un problème.
Commencez par générer un mot de passe chiffré à l'aide de l'utilitaire mkpasswd disponible sur la plupart des systèmes Linux:
mkpasswd --method=SHA-512
Ensuite, essayez la commande ansible ad-hock:
ansible all -m user -a 'name=testuser Shell=/bin/bash \
comment="Test User" password=$6$XXXX' -k -u admin --Sudo
Mais assurez-vous:
--Sudo
ou vous vous retrouvez avec une erreur telle que (useradd: cannot lock /etc/passwd; try again later
)J'ai créé un playbook ansible qui vous permet de créer un compte linux permettant l'authentification par mot de passe.
Voir CreateLinuxAccountWithAnsible .
Le mot de passe haché est généré à l'aide de la commande mkpasswd
. J'ai fourni les moyens d'installer mkpasswd
sur différents systèmes d'exploitation.
Voici les étapes nécessaires pour utiliser mon script:
Remplacez <your_user_name>
et <your_password>
dans run.sh
par le nom d'utilisateur et le mot de passe de votre choix.
Modifiez les informations de connexion dans inventory
afin que ansible puisse se connecter à la machine pour créer un utilisateur.
Exécutez ./run.sh
pour exécuter le script.
La réponse de Mxx est correcte, mais la méthode python crypt.crypt()
n'est pas sans danger lorsque différents systèmes d'exploitation sont impliqués (lié à l'algorithme de hachage glibc utilisé sur votre système)
Par exemple, cela ne fonctionnera pas si vous générez votre hachage à partir de MacOS et exécutez un livre de jeu sur Linux. Dans ce cas, vous pouvez utiliser passlib (pip install passlib
pour installer localement).
from passlib.hash import md5_crypt
python -c 'import crypt; print md5_crypt.encrypt("This is my Password,salt="SomeSalt")'
'$1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.'
Aucune de ces solutions ne fonctionnait directement sur mon Mac contrôlant Ubuntu. Donc, pour le bien des autres, en combinant les réponses Mxx et JoelB, voici la solution actuelle Python 3:
pip3 install passlib
python3 -c 'from passlib.hash import md5_crypt; \
print(md5_crypt.encrypt("This is my Password", salt="SomeSalt"))'
Le résultat sera $1$SomeSalt$UqddPX3r4kH3UL5jq5/ZI.
, comme dans la réponse de Mxx.
Mieux encore, utilisez SHA512 au lieu de MD5:
python3 -c 'from passlib.hash import sha512_crypt; \
print(sha512_crypt.encrypt("This is my Password", salt="SomeSalt"))'
Résultat:
$ 6 $ tours = 656000 $ SomeSalt $ oYpmnpZahIsvn5FK8g4bDFEAmGpEN114Fe6Ko4HvinzFaz5Rq2UXQxoJZ9yQo9zaBo3gBH/FEAov3FBHv48
Générer un mot de passe aléatoire pour l'utilisateur
d'abord besoin de définir les utilisateurs variables puis suivez ci-dessous
les tâches:
- name: Generate Passwords
become: no
local_action: command pwgen -N 1 8
with_items: '{{ users }}'
register: user_passwords
- name: Update User Passwords
user:
name: '{{ item.item }}'
password: "{{ item.stdout | password_hash('sha512')}}"
update_password: on_create
with_items: '{{ user_passwords.results }}'
- name: Save Passwords Locally
become: no
local_action: copy content={{ item.stdout }} dest=./{{ item.item }}.txt
with_items: '{{ user_passwords.results }}'
Comment créer un mot de passe crypté pour passer de la variable password
var à la tâche Ansible user
(à partir du commentaire de @Brendan Wood):
openssl passwd -salt 'some_plain_salt' -1 'some_plain_pass'
Le résultat ressemblera à:
$1$some_pla$lmVKJwdV3Baf.o.F0OOy71
Exemple de tâche user
:
- name: Create user
user: name="my_user" password="$1$some_pla$lmVKJwdV3Baf.o.F0OOy71"
UPD: cryptage utilisant SHA-512 voir ici et ici :
$ python -c "import crypt, getpass, pwd; print crypt.crypt('password', '\$6\$saltsalt\$')"
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
$ Perl -e 'print crypt("password","\$6\$saltsalt\$") . "\n"'
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
$ Ruby -e 'puts "password".crypt("$6$saltsalt$")'
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
Essayé de nombreux utilitaires, y compris mkpasswd, Python etc. Mais il semble qu'il y ait un problème de compatibilité avec Ansible lors de la lecture des valeurs HASH générées par d'autres outils. Alors finalement, cela a fonctionné par # ansible valeur elle-même.
ansible tout -i localhost, -m debug -a "msg = {{'yourpasswd' | password_hash ('sha512', 'mysecretsalt')}}"
Playbook -
- name: User creation
user:
name: username
uid: UID
group: grpname
Shell: /bin/bash
comment: "test user"
password: "$6$mysecretsalt$1SMjoVXjYf.3sJR3a1WUxlDCmdJwC613.SUD4DOf40ASDFASJHASDFCDDDWERWEYbs8G00NHmOg29E0"
Je sais que je suis en retard à la fête, mais il existe une autre solution que j'utilise. Cela pourrait être pratique pour les distributions qui n'ont pas --stdin
dans le binaire passwd.
- hosts: localhost
become: True
tasks:
- name: Change user password
Shell: "yes '{{ item.pass }}' | passwd {{ item.user }}"
loop:
- { pass: 123123, user: foo }
- { pass: asdf, user: bar }
loop_control:
label: "{{ item.user }}"
L'étiquette dans loop_control
est responsable de l'impression seulement nom d'utilisateur. Tout le livre de jeu ou uniquement les variables utilisateur (vous pouvez utiliser vars_files:
) doivent être chiffrés avec ansible-vault.
Ma solution utilise la recherche et génère automatiquement un mot de passe.
---
- hosts: 'all'
remote_user: root
gather_facts: no
vars:
deploy_user: deploy
deploy_password: "{{ lookup('password', '/tmp/password chars=ascii_letters') }}"
tasks:
- name: Create deploy user
user:
name: "{{ deploy_user }}"
password: "{{ deploy_password | password_hash('sha512') }}"
Si vous souhaitez accomplir cela en tant que commande Ansible ad hoc, vous pouvez procéder comme suit:
$ 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') }}\""
Sortie de la commande ci-dessus:
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
}