Ansible — удалить пользователя из группы x, если он уже находится в другой группе

Я ищу самый простой способ удалить пользователей из группы x, когда они уже находятся в группе google-sudo. Я храню пользователей в групповых переменных в такой комбинации списка и словаря:

user_account:
  - name: jenny
    authorized_keys:
      - jenny_01
    groups:
      - "{% if not googlesudo.stat.exists %}sudo{% else %}google-sudo{% endif %}"

  - name: jerry
    authorized_keys:
      - jerry_01
    groups: 
      - "{% if not googlesudo.stat.exists %}sudo{% else %}google-sudo{% endif %}"
...

Это задачи, которые я уже создал:

- name: Check if google-sudo file exists
  stat:
    path: /etc/sudoers.d/google_sudo
  register: googlesudo
  tags:
    - add_user_group
    - remove_from_x

- debug: var=googlesudo verbosity=2
  tags:
    - add_user_group
    - remove_from_x

- debug:
    msg: "User account to create: {{ item.name }}"
  with_items: "{{ user_account }}"

- name: "Creating user"
  user:
    name: "{{ item.name }}"
    group: users
    shell: /bin/bash
  with_items: "{{ user_account }}"

- name: Add user to additional groups
  user:
    name: "{{ item.0.name }}"
    groups: "{{ item.1 }}"
    append: yes
  with_subelements:
    - "{{ user_account }}"
    - groups
  tags:
    - remove_from_x

- name: Check if user already in google-sudo
  command: "groups {{ item.name }}"
  with_items:
    - "{{ user_account }}"
  register: root_users
  tags:
    - remove_from_x

- name: View root users
  debug:
    msg: "{{ item }}"
    verbosity: 2
  with_items:
    - "{{ root_users }}"
  tags:
    - remove_from_x

- name: Save state
  set_fact:
    is_in_googlesudo: "{{ root_users.results.0.stdout_lines }}"
  tags:
     - remove_from_x

- name: List
  debug: msg='{{ user_account |json_query("[?groups==`google-sudo`]")}}'
  tags:
    - remove_from_x

- name: Remove from x group
  shell: "deluser {{ item.name }} x"
  with_items:
    - "{{ user_account }}"
  when: "'x in is_in_googlesudo' and 'google-sudo in is_in_googlesudo'"
  tags:
    - remove_from_x

Я тестировал json_query для извлечения имени пользователя, если он находится в группе google-sudo и x, но безуспешно. Пытался перечислить пользователей, когда группа определена, однако я получаю пустой вывод, используя это:

msg='{{ user_account |json_query("[?groups==`google-sudo`]")}}'

Интересно, есть ли более короткий способ удалить пользователей из группы x после проверки на сервере (используя, например, команду groups) или в user_account -> group, если он уже в google-sudo.

Возможно, есть какой-то красивый и элегантный способ написать этот код, я буду признателен за любые идеи, как с этим справиться.


person Brzozova    schedule 19.04.2021    source источник


Ответы (1)


Давайте упростим данные, например.

  vars:
    my_group: "{{ googlesudo.stat.exists|ternary('google-sudo', 'sudo') }}"
    user_account:
      - name: jenny
        groups: "{{ my_group }}"
      - name: jerry
        groups: "{{ my_group }}"

Код работает так, как ожидалось, например.

    - stat:
        path: /tmp/google_sudo
      register: googlesudo
    - debug:
        var: user_account
    - debug:
        msg: '{{ user_account|json_query("[?groups==`google-sudo`].name") }}'

дает, если /tmp/google_sudo существует

  user_account:
  - groups: google-sudo
    name: jenny
  - groups: google-sudo
    name: jerry

  msg:
  - jenny
  - jerry

в противном случае

  user_account:
  - groups: sudo
    name: jenny
  - groups: sudo
    name: jerry

  msg: []

В: Удалить пользователя из группы x, если он уже состоит в другой группе.

О: Используйте getent для получения списка пользователей в группе. Например, чтобы перечислить пользователей в группе sudo

    - getent:
        database: group
    - debug:
        var: getent_group.sudo.2

Проверка действия, если пользователь является членом группы sudo, например.

    - debug:
        msg: "Remove user {{ item.name }} from group x"
      loop: "{{ user_account }}"
      when: item.name in getent_group.sudo.2

В: Создавайте группы в виде списка. (Возможно, мне следует использовать функцию contains.)

О: Да. Используйте содержит, например, учитывая списки

  vars:
    user_account:
      - name: jenny
        groups: [google-sudo, group2]
      - name: jerry
        groups: [google-sudo, group3]

задание

    - debug:
        msg: "{{ user_account|json_query('[?contains(groups, `group2`)].name') }}"

дает

  msg:
  - jenny
person Vladimir Botka    schedule 20.04.2021
comment
Да, это работает! Спасибо, Владимир, вы снова меня выручаете. :) - person Brzozova; 20.04.2021
comment
Еще кое-что. Мне нужно, чтобы группы были указаны в виде списка для каждого пользователя, а не в виде словаря. Как тогда должен выглядеть json_query -> {{ user_account|json_query("[?groups==google-sudo`].name) }}' Собственно, вопрос в том, могу ли я использовать json_query для этой комбинации или должен использовать другое решение. - person Brzozova; 20.04.2021
comment
Возможно, мне следует использовать функцию contains. - person Brzozova; 20.04.2021
comment
Ок, я уже разобрался. Это работает с группами в списке -> '{{ user_account|json_query([?groups[0]==google-sudo].name) }}' - person Brzozova; 20.04.2021
comment
Я обновил ответ. Откройте новые вопросы, если у вас есть дополнительные вопросы. - person Vladimir Botka; 20.04.2021