web-dev-qa-db-fra.com

Créer un nouvel utilisateur et mot de passe avec Ansible

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?

77
raphael_turtle

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.

81
Mxx

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

118
thinkingmonster

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. 

36
madhead

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
10
bbaassssiiee

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"
9
Artem Feofanov

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"
5
McKelvin

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
3
Lightmed

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
3
hecbuma

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}}
2
pmoksuz

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é).

2
Steve Midgley

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
2
Christian Berendt

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:

  1. La commande est entre guillemets simples et PAS double sinon votre mot de passe ne fonctionnera jamais
  2. Vous l'exécutez avec --Sudo ou vous vous retrouvez avec une erreur telle que (useradd: cannot lock /etc/passwd; try again later)
2
pgaref

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:

  1. Remplacez <your_user_name> et <your_password> dans run.sh par le nom d'utilisateur et le mot de passe de votre choix.

  2. Modifiez les informations de connexion dans inventory afin que ansible puisse se connecter à la machine pour créer un utilisateur.

  3. Exécutez ./run.sh pour exécuter le script.

1
Brian

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.'
1
Joel B

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

1
texnic

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 }}'
1
Apuri Srikanth

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

$ 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/

Rubis

$ Ruby -e 'puts "password".crypt("$6$saltsalt$")'

$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
1
Dmitriy

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"
0
DjangoChained

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.

0
Alex Baranowski

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') }}"
0
alex naumov

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
}
0
slm