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

Je peux le faire avec shell en utilisant la combinaison de getent et awk comme ceci:

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

Pour la 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 fait home_<user name>.

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

53
demandé sur myrdd 2015-10-26 13:16:14

8 réponses

Ansible (à partir de la version 1.4) révèle déjà des variables d'environnement pour ansible_env variable.

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

Vous pouvez également accéder aux variables d'environnement à l'aide d'une recherche sur env:

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

Malheureusement, vous ne pouvez apparemment l'utiliser que pour obtenir des variables d'environnement pour l'utilisateur connecté comme le montre ce playbook et la 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 avec N'importe quoi dans Ansible, si vous ne pouvez pas obtenir un module pour vous donner ce que vous voulez, vous êtes toujours libre de shell out (bien que cela devrait être utilisé avec parcimonie car il peut être fragile et sera 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 pourrait bien y avoir une façon plus propre de le faire et je suis un peu surpris que l'utilisation become_user passer à l'utilisateur spécifié ne semble pas affecter la recherche env mais cela devrait vous donner ce que vous voulez.

52
répondu ydaetskcoR 2018-05-30 23:50:40

Le Problème

Les méthodes lookup() ou ENV var pour trouver la maison d'un utilisateur arbitraire ne fonctionneront malheureusement pas de manière fiable avec Ansible car elles fonctionnent comme l'utilisateur spécifié avec --user=REMOTE_USER, et éventuellement avec sudo (Si {[5] } dans playbook ou --sudo passé). Ces deux modes d'exécution (sudo ou no sudo) modifieront L'environnement shell dans lequel Ansible s'exécute, et même dans ce cas, vous serez limité à l'utilisateur spécifié comme -u REMOTE_USER ou root.

Vous pouvez essayer d'utiliser sudo: yes, et sudo_user: myarbitraryuser ensemble... cependant, en raison d'un bogue dans certaines versions de Ansible, vous pouvez voir qu'il ne se comporte pas comme il le devrait. Si vous êtes sur Ansible >= 1.9, vous pouvez utiliser become: true, et become_user: myarbitraryuser à la place. Cependant, cela signifie que les playbooks et les rôles que vous écrivez ne fonctionneront pas sur les versions précédentes D'Ansible.

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

Ansible getent Exemple

Créer un simple playbook 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"
16
répondu TrinitronX 2015-11-18 19:34:09

Ansible 1.8 introduit l'getent module. Il enregistre le résultat getent comme un fait hôte-dans ce cas, c'est getent_passwd.

Exemples:

Imprimer le dossier d'accueil pour un user donné:

---

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

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

Accumuler une table de recherche (user_homes), en tirant parti de 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]}) }}"

Serait mieux avec un module de fait personnalisé cependant.

12
répondu masu 2018-09-03 20:32:48

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

# The `webserver_user` value will usually be provided by a distro 
# specific vars file. But for the purposes of demonstration, let's
# hard code it to something...

- set_fact:
    webserver_user: www-data
  when: ansible_os_family is 'Debian'

Ensuite, utilisez le module utilisateur ansible pour vous assurer que l'utilisateur est présent et lisez l'attribut dans une variable enregistrée pour une utilisation ultérieure.

- user:
    name: "{{ webserver_user }}"
    state: present
  register: webserver_user_registered

Nous pouvons donc utiliser debug pour afficher les valeurs de cette var, 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 ça;

- file:
    name: "{{ webserver_user_registered.home }}/.wp-cli"
    state: directory
8
répondu Tom H 2018-06-19 20:33:05

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

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

Sur les systèmes Linux (ou Unix), le signe tilde pointe vers le répertoire personnel des utilisateurs.

2
répondu Matti 2017-05-04 09:10:06

Chaque réponse mentionne comment imprimer les détails du répertoire personnel lors de l'exécution du playbook et de l'afficher à l'écran en utilisant debug et var.

Adaptation à @ TrinitronX réponse

Une information supplémentaire sur l'utilisation de ces informations pour une nouvelle tâche.

J'ai une liste d'utilisateurs dont le répertoire personnel 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 parcourra toute la liste des utilisateurs et enregistrez ces détails sur user_home. Et ce sera sous la forme d'un tableau.

Ensuite, l'étape suivante consiste à utiliser ces informations pour une nouvelle tâche, c'est-à-dire par exemple l'approvisionnement d'un fichier dans le profil bash. C'est juste un exemple et peut être n'importe quel scénario, mais la méthode reste 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 mis un fait pour java_dir à /usr/java/latest dans le même playbook.

Tableau user_home.les résultats contiendront les détails de la tâche Get home directory. Maintenant, nous bouclons ce tableau et retirez la valeur stdout qui contient le chemin du répertoire personnel.

J'ai mis loop_control pour imprimer le répertoire personnel seulement, sinon il imprimera le tableau entier.

Par ce processus, nous pouvons nous assurer que si n nombre d'utilisateurs sont là, nous pouvons suivre cette méthode et tout sera pris en charge.

Note: j'ai commencé à apprendre L'Ansible, au cas où une terminologie que j'ai utilisée serait fausse, veuillez excuser. J'ai passé un peu de temps pour comprendre sur comment faire cela et pensé à partager la même chose.

2
répondu nirmalraj17 2018-09-04 14:09:19

Il N'y a pas de moyen facile de le faire dans Ansible en ce moment et c'est pourquoi vous ajouter votre voix à cette question

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

While vous pouvez utiliser cette solution de contournement: https://stackoverflow.com/a/33343455/99834 vous ne devez pas oublier d'envoyer les commentaires que vous voulez que ce soit facile à utiliser.

1
répondu sorin 2017-05-23 11:47:19

Vous pouvez utiliser expanduser.

Par exemple, lors d'une boucle sur 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
1
répondu leucos 2016-08-09 14:04:46