web-dev-qa-db-fra.com

Comment obtenir le répertoire de base d'un utilisateur distant arbitraire dans Ansible?

Je peux le faire avec Shell en combinant getent et awk comme ceci:

getent passwd $user | awk -F: '{ print $6 }'

Pour référence, dans Puppet, je peux utiliser un fait personnalisé, comme ceci:

require 'etc'

Etc.passwd { |user|

   Facter.add("home_#{user.name}") do
      setcode do
         user.dir
      end
   end

}

qui rend le répertoire personnel de l'utilisateur disponible en tant que home_<user name> fait.

Comment obtenir le répertoire personnel d'un utilisateur distant arbitraire ?

60
Adam Ryczkowski

Ansible (à partir de la version 1.4) révèle déjà les variables d’environnement pour l’utilisateur sous le ansible_env variable.

- hosts: all
  tasks:
    - name: debug through ansible.env
      debug: var=ansible_env.HOME

Alternativement, vous pouvez accéder aux variables d'environnement en utilisant un lookup on env:

- hosts: all
  tasks:
    - name: debug through lookup on env
      debug: var=lookup('env','HOME')

Malheureusement, vous ne pouvez apparemment utiliser ceci que pour obtenir des variables d'environnement pour l'utilisateur connecté, comme le montre ce livret et cette sortie:

- hosts: all
  tasks:
    - name: debug specified user's home dir through ansible.env
      debug: var=ansible_env.HOME
      become: true
      become_user: "{{ user }}"

    - name: debug specified user's home dir through lookup on env
      debug: var=lookup('env','HOME')
      become: true
      become_user: "{{ user }}"

[~ # ~] sortie [~ # ~] :

vagrant@Test-01:~$ ansible-playbook -i "inventory/vagrant" env_vars.yml -e "user=testuser"

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.30]

TASK: [debug specified user's home dir through ansible.env] *******************
ok: [192.168.0.30] => {
    "var": {
        "/home/vagrant": "/home/vagrant"
    }
}

TASK: [debug specified user's home dir through lookup on env] *****************
ok: [192.168.0.30] => {
    "var": {
        "/home/vagrant": "/home/vagrant"
    }
}

PLAY RECAP ********************************************************************
192.168.0.30               : ok=3    changed=0    unreachable=0    failed=0

Comme pour tout ce qui est dans Ansible, si vous ne pouvez pas obtenir un module qui vous donne ce que vous voulez, vous êtes toujours libre de Shell out moins descriptif) en utilisant quelque chose comme ceci:

- hosts: all
  tasks:
    - name: grep and register
      Shell: >
              egrep "^{{ user }}:" /etc/passwd | awk -F: '{ print $6 }'
      changed_when: false
      register: user_home

    - name: debug output
      debug: var=user_home.stdout

Il y a peut-être une façon plus propre de faire cela et je suis un peu surpris que l'utilisation de become_user le passage à l'utilisateur spécifié ne semble pas affecter la recherche env, mais cela devrait vous donner ce que vous voulez.

56
ydaetskcoR

Ansible 1.8 a introduit le module getent . Il enregistre le résultat de getent en tant que fait de l'hôte. Dans ce cas, il s'agit de getent_passwd.

exemples:

Imprimer le dossier de départ pour un user donné:

---

- getent:
    database: passwd
    key: "{{ user }}"
    split: ":"

- debug:
    msg: "{{ getent_passwd[user][4] }}"

Accumuler une table de recherche (user_homes), En utilisant set_fact et le Jinja2 combine() filtre :

---

- assert:
    that:
      - user_name is defined

- when: user_homes is undefined or user_name not in user_homes
  block:
    - name: getent
      become: yes
      getent:
        database: passwd
        key: "{{ user_name }}"
        split: ":"

    - name: set fact
      set_fact:
        "user_homes": "{{ user_homes | d({}) | combine({user_name: getent_passwd[user_name][4]}) }}"

Ce serait mieux avec un module de faits personnalisé cependant.

19
masu

Le problème

Les méthodes lookup() ou ENV var pour trouver le domicile d'un utilisateur arbitraire ne fonctionneront malheureusement pas de manière fiable avec Ansible car elles s'exécutent sous le nom d'utilisateur spécifié avec --user=REMOTE_USER, et éventuellement avec Sudo (si Sudo: yes dans le livre de jeu ou --Sudo passé). Ces deux modes d’exécution (Sudo ou non Sudo) modifieront l’environnement Shell dans lequel Ansible est exécuté, et même dans ce cas, vous serez limité à l’utilisateur spécifié en tant que -u REMOTE_USER ou root.

Vous pouvez essayer d'utiliser Sudo: yes, et Sudo_user: myarbitraryuser ensemble ... cependant, à cause d'un bogue dans certaines versions de Ansible , vous constaterez qu'il ne se comporte pas comme il se doit. Si vous êtes sur Ansible> = 1.9, vous pouvez utiliser become: true, et become_user: myarbitraryuser au lieu. Cependant, cela signifie que les playbooks et les rôles que vous écrivez ne fonctionneront pas avec les versions précédentes d'Ansible.

Si vous recherchez un moyen portable d'obtenir le répertoire personnel d'un utilisateur qui fonctionne également avec LDAP ou un autre service d'annuaire, utilisez getent.

Exemple de getent

Créez un livre de lecture simple nommé: playbooks/ad-hoc/get-user-homedir.yml

- hosts: all
  tasks:
    - name:
      Shell: >
        getent passwd {{ user }} | cut -d: -f6
      changed_when: false
      register: user_home

    - name: debug output
      debug: var=user_home.stdout

Exécutez-le avec:

ansible-playbook -i inventory/racktables.py playbooks/ad-hoc/get-user-homedir.yml -e "user=someuser"
15
TrinitronX

Je pense qu'il y a plusieurs réponses données ici qui pourraient marcher, mais je pensais montrer que vous pouvez l'obtenir à partir du module ansible user , en l'enregistrant en tant que variable.

- user:
    name: www-data
    state: present
  register: webserver_user_registered

Note: cela créera l'utilisateur s'il n'existe pas ...

Nous pouvons donc utiliser debug pour afficher les valeurs de cette variable, y compris le chemin ...

- debug:
    var: webserver_user_registered

TASK [wordpress : debug] ******************
ok: [wordpresssite.org] => {
    "webserver_user_registered": {
        "append": false,
        "changed": false,
        "comment": "www-data",
        "failed": false,
        "group": 33,
        "home": "/var/www",      <<------ this is the user home dir
        "move_home": false,
        "name": "www-data",
        "Shell": "/usr/sbin/nologin",
        "state": "present",
        "uid": 33
    }
}

Et vous pouvez utiliser ces propriétés dans d'autres modules comme celui-ci;

- file:
    name: "{{ webserver_user_registered.home }}/.wp-cli"
    state: directory
14
Tom H

Je sais que c'est un fil assez ancien, mais je pense que c'est un moyen un peu plus simple d'obtenir le répertoire de base des utilisateurs

- name: Get users homedir
  local_action: command echo ~
  register: homedir

Sur les systèmes Linux (ou Unix), le signe-tilde indique le répertoire de base de l'utilisateur.

3
Matti

Chaque réponse mentionne comment imprimer les détails du répertoire de base lors de l'exécution du playbook et de son affichage à l'écran à l'aide de debug et var .

S'adapter à @TrinitronX réponse

Informations supplémentaires sur l'utilisation de ces informations pour une nouvelle tâche.

J'ai une liste d'utilisateurs dont le répertoire de base doit être extrait. J'ai donc ajouté les détails de l'utilisateur à une liste

- name: Get home directory
  Shell: >
         getent passwd {{ item.user }} | cut -d: -f6
  changed_when: false
  with_items:
   - "{{Java}}"
  register: user_home

Ici, cette étape va parcourir toute la liste des utilisateurs et va enregistrer ces détails dans user_home. Et ce sera sous la forme d'un tableau.

La prochaine étape consiste à utiliser ces informations pour une nouvelle tâche, par exemple, la création d’un fichier dans un profil bash. Ceci est juste un exemple et peut être n'importe quel scénario, mais la méthode restera la même.

- name: Set Java home in .bash_profile
  lineinfile: path="{{ item.stdout }}/.bash_profile" regexp='^source "{{ Java_dir }}/.bash_profile_Java"' line='source "{{ Java_dir }}/.bash_profile_Java"' state=present
  with_items:
   - "{{ user_home.results }}"
  loop_control:
    label: "{{ item.stdout }}"

J'ai défini un fait pour Java_dir sur/usr/Java/latest dans le même livre de lecture.

Le tableau user_home.results contiendra les détails de la tâche Obtenir le répertoire de base. Maintenant, nous parcourons ce tableau et prenons la valeur stdout qui contient le chemin du répertoire de base.

J'ai mis loop_control pour l'impression du répertoire de base uniquement, sinon il affichera tout le tableau.

Grâce à ce processus, nous pouvons nous assurer que si n nombre d’utilisateurs sont présents, nous pouvons suivre cette méthode et que tous seront pris en charge.

Remarque: j'ai commencé à apprendre le Ansible, au cas où une terminologie que j'aurais utilisée serait mauvaise, veuillez l'excuser. J'ai passé du temps à comprendre comment faire cela et à penser à partager la même chose.

2
nirmalraj17

Vous pouvez utiliser expanduser.

Par exemple, en parcourant une liste d'utilisateurs:

- name: Deploys .bashrc
  template:
    src: bashrc.j2
    dest: "{{ '~' + item | expanduser }}/.bashrc"
    mode: 0640
    owner: "{{ item }}"
    group: "{{ item }}"
  with_items: user_list
2
leucos

Il n'y a pas de moyen facile de faire cela dans Ansible en ce moment et c'est pourquoi vous devriez ajouter vos votes à cette question

https://github.com/ansible/ansible/issues/15901

Bien que vous puissiez utiliser cette solution de contournement: https://stackoverflow.com/a/33343455/99834 vous ne devez pas oublier d’envoyer les commentaires voulant qu’ils soient faciles à utiliser.

1
sorin