ipa/client: Combine operations on the IPA server
The reason for this is to avoid having to do the same or similar things over and over again for each host in the play, especially since these operations are delegated to the IPA server, i.e. had to run sequentially host after host in order to avoid race conditions. To achieve this, the IPA client related group variables are prepared in suitable structures in `prepare-ipa-info.yml` and consumed by `common.yml`, `hbac.yml` and `sudo.yml`, which do most operations in one go per e.g. host group on the affected IPA server(s). Additionally: - Remove compat for legacy `fas_client_groups`, only check for its presence and warn. - Remove the prepared but masked out task to manage password-less sudo access. - Make yamllint a little happier on the changed files. Signed-off-by: Nils Philippsen <nils@redhat.com>
This commit is contained in:
parent
fdcd55c176
commit
3d1c5218f7
6 changed files with 248 additions and 78 deletions
|
@ -1,3 +1,4 @@
|
|||
---
|
||||
# REMOVEME: As soon as all (affected) hosts have been migrated over from fas_client, 2fa_client to
|
||||
# ipa/client, this can go away.
|
||||
#
|
||||
|
|
|
@ -1,22 +1,38 @@
|
|||
---
|
||||
## This will only run once per play (as per `main.yml`), so needs to consider all affected hosts.
|
||||
|
||||
## Cluster-wide rules
|
||||
|
||||
- name: Check that sysadmin-main group exists
|
||||
command: "getent group sysadmin-main"
|
||||
changed_when: False
|
||||
# This is supposed to fail if a configured group doesn't exist. In this case, either add the group
|
||||
# manually or remove the reference from configuration.
|
||||
|
||||
- name: Check that sysadmin-main and referenced groups exist on IPA server(s)
|
||||
delegate_to: "{{ item[0] }}"
|
||||
command: "getent group {{ item[1] }}"
|
||||
changed_when: false
|
||||
loop: >-
|
||||
{{
|
||||
ipa_server_user_groups
|
||||
+ (ipa_server_all_groups_hosts_dict | list | product(['sysadmin-main']) | list)
|
||||
}}
|
||||
|
||||
## Rules specific to hosts, host groups
|
||||
|
||||
- name: Ensure IPA host group exists
|
||||
- name: Ensure IPA host groups exist on IPA server(s)
|
||||
delegate_to: "{{ item[0] }}"
|
||||
ipahostgroup:
|
||||
name: "{{ ipa_host_group }}"
|
||||
description: "{{ ipa_host_group_desc | default(omit) }}"
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
name: "{{ item[1] }}"
|
||||
description: "{{ ipa_server_host_groups_dict[item[1]].desc | default(omit) }}"
|
||||
ipaadmin_password: "{{ ipa_server_admin_passwords[item[0]] }}"
|
||||
state: present
|
||||
loop: "{{ ipa_server_host_groups }}"
|
||||
|
||||
- name: Ensure host is in IPA host group
|
||||
- name: Ensure hosts are in IPA host groups
|
||||
delegate_to: "{{ item[0] }}"
|
||||
ipahostgroup:
|
||||
name: "{{ ipa_host_group }}"
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
name: "{{ item[1] }}"
|
||||
ipaadmin_password: "{{ ipa_server_admin_passwords[item[0]] }}"
|
||||
action: member
|
||||
state: present
|
||||
host: "{{ inventory_hostname }}"
|
||||
host: "{{ item[2] | list }}"
|
||||
loop: "{{ ipa_server_host_groups_hosts }}"
|
||||
|
|
|
@ -1,80 +1,101 @@
|
|||
---
|
||||
## This will only run once per play (as per `main.yml`), so needs to consider all affected hosts.
|
||||
|
||||
## Cluster-wide rules
|
||||
|
||||
- name: "Give members of group sysadmin-main access to anything, anywhere"
|
||||
delegate_to: "{{ item.key }}"
|
||||
ipahbacrule:
|
||||
name: "usergroup/sysadmin-main"
|
||||
description: "Give members of group sysadmin-main access to anything, anywhere"
|
||||
hostcategory: "all"
|
||||
servicecategory: "all"
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
ipaadmin_password: "{{ item.value }}"
|
||||
state: present
|
||||
group:
|
||||
- sysadmin-main
|
||||
loop: "{{ ipa_server_admin_passwords | dict2items }}"
|
||||
|
||||
- name: "Enable usergroup/sysadmin-main HBAC rule"
|
||||
delegate_to: "{{ item.key }}"
|
||||
ipahbacrule:
|
||||
name: "usergroup/sysadmin-main"
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
ipaadmin_password: "{{ item.value }}"
|
||||
state: enabled
|
||||
loop: "{{ ipa_server_admin_passwords | dict2items }}"
|
||||
|
||||
- name: "Disable allow_all HBAC rule"
|
||||
delegate_to: "{{ item.key }}"
|
||||
ipahbacrule:
|
||||
name: allow_all
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
ipaadmin_password: "{{ item.value }}"
|
||||
state: disabled
|
||||
loop: "{{ ipa_server_admin_passwords | dict2items }}"
|
||||
|
||||
- name: "Let everybody run sudo"
|
||||
delegate_to: "{{ item.key }}"
|
||||
ipahbacrule:
|
||||
name: "all-users/sudo"
|
||||
description: "Allow all users to execute the sudo command"
|
||||
state: present
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
ipaadmin_password: "{{ item.value }}"
|
||||
hostcategory: "all"
|
||||
usercategory: "all"
|
||||
hbacsvcgroup:
|
||||
- Sudo
|
||||
loop: "{{ ipa_server_admin_passwords | dict2items }}"
|
||||
|
||||
## Host-specific rules
|
||||
- name: Add the sshd HBAC service in IPA
|
||||
delegate_to: "{{ item.key }}"
|
||||
ipahbacsvc:
|
||||
name: sshd
|
||||
description: SSH daemon
|
||||
ipaadmin_password: "{{ item.value }}"
|
||||
loop: "{{ ipa_server_admin_passwords | dict2items }}"
|
||||
|
||||
- name: Add the shell-access service group in IPA
|
||||
delegate_to: "{{ item.key }}"
|
||||
ipahbacsvcgroup:
|
||||
name: shell-access
|
||||
description: Group of shell access services
|
||||
ipaadmin_password: "{{ item.value }}"
|
||||
hbacsvc:
|
||||
- sshd
|
||||
loop: "{{ ipa_server_admin_passwords | dict2items }}"
|
||||
|
||||
## Host group- & host-specific rules
|
||||
|
||||
# shell access
|
||||
|
||||
- name: "Warn if `fas_client_groups` is set"
|
||||
fail:
|
||||
msg: "`fas_client_groups` is defined, should be converted to a list and named `ipa_client_shell_groups`"
|
||||
msg: >-
|
||||
`fas_client_groups` is defined, please convert to a (group var) list named
|
||||
`ipa_client_shell_groups`
|
||||
ignore_errors: true
|
||||
when: fas_client_groups is defined
|
||||
|
||||
- name: "Convert `fas_client_groups` string to `ipa_client_shell_groups` list if missing"
|
||||
set_fact:
|
||||
ipa_client_shell_groups: "{{ fas_client_groups.split(',') | list }}"
|
||||
when: fas_client_groups is defined and ipa_client_shell_groups is not defined
|
||||
- name: "Warn if IPA client variables are unset"
|
||||
fail:
|
||||
msg: "`{{ item }}` is not defined"
|
||||
ignore_errors: true
|
||||
when: lookup('vars', item, default="<undefined-sentinel>") == "<undefined-sentinel>"
|
||||
loop:
|
||||
- ipa_host_group
|
||||
- ipa_host_group_desc
|
||||
- ipa_client_shell_groups
|
||||
- ipa_client_sudo_groups
|
||||
|
||||
- name: Add the sshd HBAC service in IPA
|
||||
ipahbacsvc:
|
||||
name: sshd
|
||||
description: SSH daemon
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
|
||||
- name: Add the shell-access service group in IPA
|
||||
ipahbacsvcgroup:
|
||||
name: shell-access
|
||||
description: Group of shell access services
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
hbacsvc:
|
||||
- sshd
|
||||
|
||||
- name: Check that shell access user groups exist
|
||||
command: "getent group {{ item }}"
|
||||
changed_when: False
|
||||
loop: "{{ (ipa_client_shell_groups | default([])) | list }}"
|
||||
|
||||
- name: "Give certain groups shell access on host group {{ ipa_host_group }}"
|
||||
- name: Give certain groups shell access per host group
|
||||
delegate_to: "{{ item[0] }}"
|
||||
ipahbacrule:
|
||||
name: "hostgroup/{{ ipa_host_group }}/shell-access"
|
||||
description: "Give certain groups shell access on host group {{ ipa_host_group }}"
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
name: "hostgroup/{{ item[1] }}/shell-access"
|
||||
description: "Grant shell access on host group {{ item[1] }}"
|
||||
ipaadmin_password: "{{ ipa_server_admin_passwords[item[0]] }}"
|
||||
action: member
|
||||
hbacsvcgroup:
|
||||
- shell-access
|
||||
state: present
|
||||
group: "{{ ipa_client_shell_groups | default([]) | list }}"
|
||||
hostgroup: "{{ ipa_host_group }}"
|
||||
group: "{{ ipa_server_host_groups_dict[item[0]][item[1]]['shell_groups'] }}"
|
||||
hostgroup: "{{ item[1] }}"
|
||||
loop: "{{ ipa_server_host_groups }}"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
---
|
||||
- name: Install IPA client packages
|
||||
package:
|
||||
name:
|
||||
|
@ -29,15 +30,23 @@
|
|||
- ipa/client
|
||||
- fas-client-cleanup
|
||||
|
||||
- name: Basic configuration for client on IPA cluster
|
||||
delegate_to: "{{ ipa_server }}"
|
||||
- name: Prepare IPA-related information to make the following more efficient
|
||||
delegate_to: localhost
|
||||
import_tasks: prepare-ipa-info.yml
|
||||
tags:
|
||||
- ipa/client
|
||||
- config
|
||||
run_once: yes
|
||||
|
||||
- name: Basic configuration for clients on IPA cluster
|
||||
delegate_to: localhost
|
||||
import_tasks: common.yml
|
||||
# don't muck with prod for now
|
||||
when: env == 'staging'
|
||||
tags:
|
||||
- ipa/client
|
||||
- config
|
||||
throttle: 1
|
||||
run_once: yes
|
||||
|
||||
- name: Configure HBAC on IPA cluster
|
||||
delegate_to: "{{ ipa_server }}"
|
||||
|
@ -47,7 +56,7 @@
|
|||
tags:
|
||||
- ipa/client
|
||||
- config
|
||||
throttle: 1
|
||||
run_once: yes
|
||||
|
||||
- name: Configure sudo on IPA cluster
|
||||
delegate_to: "{{ ipa_server }}"
|
||||
|
@ -57,4 +66,4 @@
|
|||
tags:
|
||||
- ipa/client
|
||||
- config
|
||||
throttle: 1
|
||||
run_once: yes
|
||||
|
|
137
roles/ipa/client/tasks/prepare-ipa-info.yml
Normal file
137
roles/ipa/client/tasks/prepare-ipa-info.yml
Normal file
|
@ -0,0 +1,137 @@
|
|||
---
|
||||
# NOTE: configuration is based on host groups, i.e. set the ipa_* vars only in group_vars
|
||||
|
||||
# Thanks to having two environments, staging and prod, this has to deal with the "responsible" IPA
|
||||
# server for individual hosts.
|
||||
|
||||
# ipa_server_host_groups_dict ->
|
||||
# {
|
||||
# "ipa_server_1": {
|
||||
# "host_group_1": {
|
||||
# "shell_groups": [...],
|
||||
# "sudo_groups": [...],
|
||||
# "hosts": { # <-- This could be a list with Ansible >= 2.10
|
||||
# "host_1": true,
|
||||
# ...,
|
||||
# }
|
||||
# }, ...
|
||||
# }, ...
|
||||
# }
|
||||
#
|
||||
# ipa_server_all_groups_hosts_dict ->
|
||||
# {
|
||||
# "ipa_server_1": {
|
||||
# groups: [...],
|
||||
# hosts: {
|
||||
# "host_1": true,
|
||||
# ...,
|
||||
# }
|
||||
# }, ...
|
||||
# }
|
||||
#
|
||||
# ipa_server_passwords: ->
|
||||
# {
|
||||
# "ipa_server_1": "ipa_password_1",
|
||||
# "ipa_server_2": "ipa_password_2",
|
||||
# ...
|
||||
# }
|
||||
- name: Create dictionary about IPA servers, host groups, their IPA vars and contained hosts
|
||||
set_fact:
|
||||
ipa_server_host_groups_dict: >-
|
||||
{{
|
||||
ipa_server_host_groups_dict | default({}) | combine(
|
||||
{
|
||||
hostvars[item]['ipa_server']: {
|
||||
hostvars[item]['ipa_host_group']: {
|
||||
'desc': hostvars[item]['ipa_host_group_desc'] | default(omit),
|
||||
'shell_groups': hostvars[item]['ipa_client_shell_groups'] | default(omit),
|
||||
'sudo_groups': hostvars[item]['ipa_client_sudo_groups'] | default(omit),
|
||||
'hosts': {item: true},
|
||||
}
|
||||
}
|
||||
},
|
||||
recursive=True
|
||||
)
|
||||
}}
|
||||
ipa_server_all_groups_hosts_dict: >-
|
||||
{{
|
||||
(ipa_server_all_groups_hosts_dict | default({})) | combine(
|
||||
{
|
||||
hostvars[item]['ipa_server']: {
|
||||
'groups': hostvars[item]['ipa_client_shell_groups'] | default([]) | union(
|
||||
hostvars[item]['ipa_client_sudo_groups'] | default([])
|
||||
),
|
||||
'hosts': {item: True},
|
||||
}
|
||||
},
|
||||
recursive=True
|
||||
)
|
||||
}}
|
||||
ipa_server_admin_passwords: >-
|
||||
{{
|
||||
(ipa_server_admin_passwords | default({})) | combine(
|
||||
{hostvars[item]['ipa_server']: hostvars[item]['ipa_admin_password']}
|
||||
)
|
||||
}}
|
||||
loop: "{{ ansible_play_hosts }}"
|
||||
when: hostvars[item]['ipa_server'] is defined and hostvars[item]['ipa_host_group'] is defined
|
||||
|
||||
# ipa_server_host_groups ->
|
||||
# [
|
||||
# ["ipa_server_1", "host_group_1"],
|
||||
# ["ipa_server_1", "host_group_2"],
|
||||
# ...
|
||||
# ["ipa_server_2", "host_group_1"],
|
||||
# ...
|
||||
# ]
|
||||
- name: Transform ipa_server_host_groups_dict into an iterable list
|
||||
set_fact:
|
||||
ipa_server_host_groups: >-
|
||||
{{
|
||||
(ipa_server_host_groups | default([]))
|
||||
+ ([item.key] | product(item.value | list) | list)
|
||||
}}
|
||||
loop: "{{ ipa_server_host_groups_dict | dict2items }}"
|
||||
|
||||
# ipa_server_host_user_groups_hosts ->
|
||||
# [
|
||||
# [
|
||||
# "ipa_server_1",
|
||||
# "host_group_1",
|
||||
# ["user_group_1", ...], # <-- shell access user groups
|
||||
# ["user_group_2", ...], # <-- sudo access user groups
|
||||
# ["host_1", ...],
|
||||
# ],
|
||||
# [
|
||||
# "ipa_server_1",
|
||||
# "host_group_2",
|
||||
# ["user_group_3", ...],
|
||||
# ["user_group_4", ...],
|
||||
# ["host_2", ...],
|
||||
# ],
|
||||
# ...
|
||||
# [
|
||||
# "ipa_server_2",
|
||||
# "host_group_1",
|
||||
# ["user_group_5", ...],
|
||||
# ["user_group_6", ...],
|
||||
# ["host_3", ...],
|
||||
# ],
|
||||
# ...
|
||||
# ]
|
||||
- name: Make semi-flat list of IPA servers, host groups and the user groups and hosts contained
|
||||
set_fact:
|
||||
ipa_server_host_user_groups_hosts: >-
|
||||
{{
|
||||
ipa_server_host_user_groups_hosts | default([])
|
||||
+ [
|
||||
[
|
||||
item[0],
|
||||
item[1],
|
||||
ipa_server_host_groups_dict[item[0]][item[1]]['shell_groups'],
|
||||
ipa_server_host_groups_dict[item[0]][item[1]]['sudo_groups'],
|
||||
ipa_server_host_groups_dict[item[0]][item[1]]['hosts'] | list,
|
||||
]
|
||||
]
|
||||
}}
|
||||
loop: "{{ ipa_server_host_groups }}"
|
|
@ -1,13 +1,12 @@
|
|||
- name: Check that configured sudo groups exist
|
||||
command: "getent group {{ item }}"
|
||||
changed_when: False
|
||||
loop: "{{ (ipa_client_sudo_groups | default([])) + (ipa_client_sudo_nopasswd_groups | default([])) | list }}"
|
||||
---
|
||||
## This will only run once per play (as per `main.yml`), so needs to consider all affected hosts.
|
||||
|
||||
- name: "Give members of `sysadmin-main` sudo access to anything, anywhere"
|
||||
delegate_to: "{{ item.key }}"
|
||||
ipasudorule:
|
||||
name: "usergroup/sysadmin-main"
|
||||
description: "Allow members of `sysadmin-main` to use sudo to do anything, anywhere"
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
ipaadmin_password: "{{ item.value }}"
|
||||
state: present
|
||||
cmdcategory: "all"
|
||||
hostcategory: "all"
|
||||
|
@ -15,31 +14,18 @@
|
|||
runasgroupcategory: "all"
|
||||
group:
|
||||
- sysadmin-main
|
||||
loop: "{{ ipa_server_admin_passwords | dict2items }}"
|
||||
|
||||
- name: "Give certain groups sudo access to anything on host group {{ ipa_host_group }}"
|
||||
- name: Give certain groups sudo access to anything per host group
|
||||
delegate_to: "{{ item[0] }}"
|
||||
ipasudorule:
|
||||
name: "hostgroup/{{ ipa_host_group }}"
|
||||
description: "Give members of groups sudo access to anything on host group {{ ipa_host_group }}"
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
name: "hostgroup/{{ item[1] }}"
|
||||
description: "Grant sudo access to anything on host group {{ item[1] }}"
|
||||
ipaadmin_password: "{{ ipa_server_admin_passwords[item[0]] }}"
|
||||
state: present
|
||||
group: "{{ ipa_client_sudo_groups | list }}"
|
||||
hostgroup: "{{ ipa_host_group }}"
|
||||
group: "{{ ipa_server_host_groups_dict[item[0]][item[1]]['sudo_groups'] }}"
|
||||
hostgroup: "{{ item[1] }}"
|
||||
cmdcategory: "all"
|
||||
runasusercategory: "all"
|
||||
runasgroupcategory: "all"
|
||||
when: ipa_client_sudo_groups is defined and ipa_client_sudo_groups | length > 0
|
||||
|
||||
## Disabled: Remove "False and" from when: to re-enable
|
||||
- name: "Give certain groups password-less sudo access to anything on host group {{ ipa_host_group }}"
|
||||
ipasudorule:
|
||||
name: "hostgroup/{{ ipa_host_group }}/nopasswd"
|
||||
description: "Give members of groups password-less sudo access to anything on host group {{ ipa_host_group }}"
|
||||
ipaadmin_password: "{{ ipa_admin_password }}"
|
||||
state: present
|
||||
group: "{{ ipa_client_sudo_groups_nopasswd | list }}"
|
||||
hostgroup: "{{ ipa_host_group }}"
|
||||
cmdcategory: "all"
|
||||
runasusercategory: "all"
|
||||
runasgroupcategory: "all"
|
||||
options: "!authenticate"
|
||||
when: False and ipa_client_sudo_groups_nopasswd is defined and ipa_client_sudo_groups_nopasswd | length > 0
|
||||
loop: "{{ ipa_server_host_groups }}"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue