Add mode to delete LDAP users

Create a new parameter mode to remove LDAP user with keystone account
and sudo access if exists. The playbook run a set of tasks to remove
the user in all subclouds.

The objective of the playbook is to remove the specified ldap account
to disallow future ssh connects to the system using the account.
The playbook works for stand-alone as well as Distributed Cloud
systems.

Test Plan:
  PASS: Create user with mode 'create' and then delete the
        same user using mode 'delete'.
  PASS: Verify the user deleted can not connect using SSH to all
        subclouds
  PASS: Verify the script can run in stand-alone system
  PASS: Verify the script can run in distributed cloud

Story: 2009759
Task: 44537

Signed-off-by: Alexandre Horst <alexandre.horst@windriver.com>
Change-Id: I7271d77b2daa5beb5d55052ad7c9c2f0c4f36719
This commit is contained in:
Alexandre Horst 2022-02-23 11:12:43 -03:00
parent e849974678
commit 25370ed25e
10 changed files with 295 additions and 168 deletions

View File

@ -32,8 +32,12 @@
# ansible-playbook --inventory inventory-secure --ask-vault-pass \
# --extra-vars='user_id=JohnDoo sudo_permission=yes' \
# /usr/share/ansible/stx-ansible/playbooks/manage_local_ldap_account.yml
#
# If you wish to delete an existing user account (e.g. na-admin):
#
# ansible-playbook --inventory inventory --extra-vars='user_id=na-admin \
# mode=delete' /usr/share/ansible/stx-ansible/playbooks/manage_local_ldap_account.yml
#
[all:vars]
ansible_user=sysadmin

View File

@ -32,10 +32,18 @@
# playbook enables this option while the user account creation is progressing
# and disables it when complete.
#
# Example command:
# Example to add user 'na-admin' (mode=create is default):
# ansible-playbook --inventory inventory --extra-vars='user_id=na-admin' \
# /usr/share/ansible/stx-ansible/playbooks/manage_local_ldap_account.yml
#
# Example to add user 'na-admin' with the use of variable mode=create:
# ansible-playbook --inventory inventory --extra-vars='user_id=na-admin mode=create' \
# /usr/share/ansible/stx-ansible/playbooks/manage_local_ldap_account.yml
#
# Example to delete user 'na-admin':
# ansible-playbook --inventory inventory --extra-vars='user_id=na-admin \
# mode=delete' /usr/share/ansible/stx-ansible/playbooks/manage_local_ldap_account.yml
#
- hosts: systemcontroller
gather_facts: no
@ -45,24 +53,44 @@
prompt: "What is the name of the user account?"
private: no
- name: user_password
prompt: "What is the password for the user account?"
private: yes
unsafe: yes
pre_tasks:
- set_fact:
password_change_period: 90
password_warning_period: 2
in_mode: "{{ mode }}"
when: mode is defined
- name: Validate in_mode
fail:
msg: "The mode must be 'create' or 'delete'."
when: "in_mode not in ['create', 'delete']"
- name: Validate user_id
fail:
msg: "The user account cannot be empty. Please provide a valid user account."
when: user_id == ''
- name: Validate user_password
fail:
msg: "The password cannot be empty. Please provide a valid password for the user account."
when: user_password == ''
- name: Default to create if mode is not specified
set_fact:
in_mode: "create"
when: "in_mode is not defined"
- block:
- pause:
prompt: "What is the password for the user account?"
echo: no
register: prompt
no_log: no
- set_fact:
in_user_password: "{{ prompt.user_input }}"
no_log: no
- name: Validate user_password
fail:
msg: "The password cannot be empty. Please provide a valid password for the user account."
when: "in_mode == 'create' and ( in_user_password is not defined and in_user_password == '' )"
when: in_mode == 'create'
- set_fact:
password_change_period: 90
password_warning_period: 2
# The user id and password variables need to be explicitly set here.
# Otherwise, there would be undefined variable errors in subsequent
@ -70,7 +98,6 @@
- name: Set the user id and password facts for subsequent plays
set_fact:
in_user_id: "{{ user_id }}"
in_user_password: "{{ user_password }}"
- name: Set sudo_permission flag fact upfront
set_fact:
@ -82,8 +109,14 @@
vars:
ssh_internal_args: -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
roles:
- manage-local-ldap-account/create-account
tasks:
- include_role:
name: manage-local-ldap-account/create-account
when: in_mode == 'create'
- include_role:
name: manage-local-ldap-account/delete-account
when: in_mode == 'delete'
- hosts: all
gather_facts: no
@ -91,5 +124,45 @@
vars:
ssh_internal_args: -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
roles:
- manage-local-ldap-account/create-keystone-account
tasks:
- name: Enable AllowTcpForwarding setting in ssh config
lineinfile:
regexp: ^[ \t]*AllowTcpForwarding([ \t]+.*)$
line: AllowTcpForwarding yes
dest: /etc/ssh/sshd_config
validate: sshd -t -f %s
notify:
- reload sshd
become: yes
when: ('systemcontroller' in group_names)
- meta: flush_handlers
- name: Manage keystone user {{ in_user_id }}
block:
- include_role:
name: manage-local-ldap-account/create-keystone-account
when: in_mode == 'create'
- include_role:
name: manage-local-ldap-account/delete-keystone-account
when: in_mode == 'delete'
always:
- name: Disable AllowTcpForwarding setting in ssh config
lineinfile:
regexp: ^[ \t]*AllowTcpForwarding([ \t]+.*)$
line: AllowTcpForwarding no
dest: /etc/ssh/sshd_config
validate: sshd -t -f %s
notify:
- reload sshd
when: ('systemcontroller' in group_names)
become: yes
handlers:
- name: reload sshd
service:
name: sshd
state: reloaded
become: true

View File

@ -0,0 +1,18 @@
---
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Tasks to populate the inventory with managed subclouds.
- name: Populate inventory with subclouds
add_host:
name: "{{ in_item }}"
groups: "subclouds"
in_user_id: "{{ in_user_id }}"
ssh_internal_args: "{{ ssh_internal_args }}"
ansible_ssh_common_args:
'-o ProxyCommand="sshpass -p {{ ansible_password }} ssh -W [%h]:%p -q {{ ansible_user }}@{{ ansible_host }}"'
in_sudo_permission: "{{ in_sudo_permission }}"
in_mode: "{{ in_mode }}"
in_user_password: "{{ in_user_password if in_mode == 'create' else '' }}"

View File

@ -0,0 +1,16 @@
---
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# The file has tasks to get/set some flags related to distributed cloud.
- name: Get distributed_cloud role
shell: |
source /etc/platform/openrc
system show | grep distributed_cloud_role | awk '{ print $4 }'
register: distributed_cloud_role
- name: Set if system is a DC
set_fact:
is_dc: "{{ true if distributed_cloud_role.stdout == 'systemcontroller' else false }}"

View File

@ -0,0 +1,28 @@
---
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# The file has tasks to get/set some flags related to subclouds from
# central system controller. This role also builds the list of subclouds
# that are currently online and managed to be used in the next play.
- name: Set os_param_region_name if system is a DC
set_fact:
os_param_region_name: "{{ '--os-region-name SystemController' if is_dc | bool else '' }}"
- name: Tasks for distributed cloud
block:
- name: Get subcloud list
shell: |
source /etc/platform/openrc
dcmanager subcloud list --format yaml
register: subcloud_list_result
- name: Set a list for subclouds
set_fact:
subcloud_list: "{{ subcloud_list | default([]) + [ item.name ] }}"
when: (item.management == "managed" and item.availability == "online")
loop: "{{ subcloud_list_result.stdout | from_yaml if subcloud_list_result.stdout else [] }}"
when: is_dc | bool

View File

@ -3,10 +3,9 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# Tasks to check LDAP user existence, to create LDAP users and to set new
# initial password and to create home directory. If the system is distributed
# cloud, this role also builds the list of subclouds that are currently online
# and managed to be used in the next play.
# Tasks to check LDAP user existence, to create LDAP users and set a new
# initial password, and to create the home directory. If the system is
# distributed cloud, it dynamically adds subclouds to the target host list.
- name: Check if LDAP user exists
shell: ldapsearch -x -LLL uid={{ in_user_id }}
@ -38,46 +37,18 @@
no_log: true
when: in_user_id_check.stdout == ""
- name: Get distributed_cloud role
shell: |
source /etc/platform/openrc
system show | grep distributed_cloud_role | awk '{ print $4 }'
register: distributed_cloud_role
- name: Get distributed cloud role
include_role:
name: manage-local-ldap-account/common/get-distributed-role
- name: Set if system is a DC
set_fact:
is_dc: "{{ true if distributed_cloud_role.stdout == 'systemcontroller' else false }}"
- name: Tasks for distributed cloud
block:
- name: Get subcloud list
shell: |
source /etc/platform/openrc
dcmanager subcloud list --format yaml
register: subcloud_list_result
- name: Set a list for subclouds
set_fact:
subcloud_list: "{{ subcloud_list | default([]) + [ item.name ] }}"
when: (item.management == "managed" and item.availability == "online")
loop: "{{ subcloud_list_result.stdout | from_yaml if subcloud_list_result.stdout else [] }}"
- name: Populate inventory with subclouds
add_host:
name: "{{ item }}"
groups: "subclouds"
in_user_id: "{{ in_user_id }}"
in_user_password: "{{ in_user_password }}"
password_change_period: "{{ password_change_period }}"
password_warning_period: "{{ password_warning_period }}"
ssh_internal_args: "{{ ssh_internal_args }}"
ansible_ssh_common_args:
'-o ProxyCommand="sshpass -p {{ ansible_password }} ssh -W [%h]:%p -q {{ ansible_user }}@{{ ansible_host }}"'
in_sudo_permission: "{{ in_sudo_permission }}"
loop: "{{ subcloud_list }}"
- name: Get online subclouds
include_role:
name: manage-local-ldap-account/common/get-online-subclouds
- name: Populate inventory with subclouds
include_role:
name: manage-local-ldap-account/common/add-hosts
vars:
in_item: "{{ item }}"
loop: "{{ subcloud_list }}"
when: is_dc | bool
- name: Set os_param_region_name if system is a DC
set_fact:
os_param_region_name: "{{ '--os-region-name SystemController' if is_dc | bool else '' }}"

View File

@ -1,12 +0,0 @@
---
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Handler to reload sshd service
- name: reload sshd
service:
name: sshd
state: reloaded
become: true

View File

@ -7,110 +7,83 @@
# controller, and subclouds as well for distributed systems with specific
# admin role.
- name: Create keystone user {{ in_user_id }}
- name: Create keystone user on System Controller
block:
- name: Enable AllowTcpForwarding setting in ssh config
lineinfile:
regexp: ^[ \t]*AllowTcpForwarding([ \t]+.*)$
line: AllowTcpForwarding yes
dest: /etc/ssh/sshd_config
validate: sshd -t -f %s
notify:
- reload sshd
become: yes
when: ('systemcontroller' in group_names)
- name: Create the keystone user {{ in_user_id }}
expect:
command: >-
/bin/sh -c 'source /etc/platform/openrc; openstack {{ os_param_region_name }} user create --project
admin --password-prompt {{ in_user_id }}'
responses:
Password: '{{ in_user_password }}'
"\\~\\$": exit
- meta: flush_handlers
- name: Add keystone user to the admin role
shell: |
source /etc/platform/openrc
openstack {{ os_param_region_name }} role add --user {{ in_user_id }} --project admin admin
- name: Create keystone user on System Controller
block:
- name: Create the keystone user {{ in_user_id }}
expect:
command: >-
/bin/sh -c 'source /etc/platform/openrc; openstack {{ os_param_region_name }} user create --project
admin --password-prompt {{ in_user_id }}'
responses:
Password: '{{ in_user_password }}'
"\\~\\$": exit
when: ('systemcontroller' in group_names)
- name: Add keystone user to the admin role
shell: |
source /etc/platform/openrc
openstack {{ os_param_region_name }} role add --user {{ in_user_id }} --project admin admin
- name: Complete keystone user creation on the subcloud
block:
- name: Wait for keystone user to propagate to all subclouds
shell: source /etc/platform/openrc; openstack user show {{ in_user_id }}
register: user_output
until: user_output.rc == 0
retries: 12
delay: 10
when: ('systemcontroller' in group_names)
- name: Create LDAP user keystone-account home directory on the subcloud
expect:
command: ssh {{ ssh_internal_args }} {{ in_user_id }}@localhost
responses:
s password: "{{ in_user_password }}"
"\\~\\$": exit
# do not show passwords in the logs
no_log: true
- name: Complete keystone user creation on the subcloud
block:
- name: Wait for keystone user to propagate to all subclouds
shell: source /etc/platform/openrc; openstack user show {{ in_user_id }}
register: user_output
until: user_output.rc == 0
retries: 12
delay: 10
when: ('systemcontroller' not in group_names)
- name: Create LDAP user keystone-account home directory on the subcloud
expect:
command: ssh {{ ssh_internal_args }} {{ in_user_id }}@localhost
responses:
s password: "{{ in_user_password }}"
"\\~\\$": exit
# do not show passwords in the logs
no_log: true
- name: Retrieve region name
shell: source /etc/platform/openrc; system show | grep region_name | awk '{ print $4 }'
register: region_name
when: ('systemcontroller' not in group_names)
- name: Retrieve management network floating IP
shell: >-
source /etc/platform/openrc; system addrpool-list --nowrap |
awk -F \| '$3 ~ / management / { gsub(/ /,"",$8); print $8 }'
register: management_floating_ip
- name: Retrieve region name
shell: source /etc/platform/openrc; system show | grep region_name | awk '{ print $4 }'
register: region_name
- name: Generate keystone user credentials file
template:
src: openrc-template.j2
dest: /home/{{ in_user_id }}/{{ in_user_id }}-openrc
owner: "{{ in_user_id }}"
group: users
mode: 0600
become: yes
- name: Retrieve management network floating IP
shell: >-
source /etc/platform/openrc; system addrpool-list --nowrap |
awk -F \| '$3 ~ / management / { gsub(/ /,"",$8); print $8 }'
register: management_floating_ip
- name: Add LDAP user to 'root' group
command: usermod -a -G root {{ in_user_id }}
become: yes
when: in_sudo_permission
- name: Generate keystone user credentials file
template:
src: openrc-template.j2
dest: /home/{{ in_user_id }}/{{ in_user_id }}-openrc
owner: "{{ in_user_id }}"
group: users
mode: 0600
become: yes
- name: Retrieve LDAP user groups
command: groups {{ in_user_id }}
register: user_groups
- name: Add LDAP user to 'root' group
command: usermod -a -G root {{ in_user_id }}
become: yes
when: in_sudo_permission
- name: Set array of user groups to check
set_fact:
user_group_array: ['users', 'sys_protected']
- name: Retrieve LDAP user groups
command: groups {{ in_user_id }}
register: user_groups
- name: Update array of user groups to include root group if sudo permission is granted
set_fact:
user_group_array: "{{ user_group_array }} + ['root']"
when: in_sudo_permission
- name: Set array of user groups to check
set_fact:
user_group_array: ['users', 'sys_protected']
- name: Update array of user groups to include root group if sudo permission is granted
set_fact:
user_group_array: "{{ user_group_array }} + ['root']"
when: in_sudo_permission
- name: Verify LDAP user groups
fail:
msg: "{{ in_user_id }} is not part of group {{ item }}"
when: item not in user_groups.stdout
loop: "{{ user_group_array }}"
always:
- name: Disable AllowTcpForwarding setting in ssh config
lineinfile:
regexp: ^[ \t]*AllowTcpForwarding([ \t]+.*)$
line: AllowTcpForwarding no
dest: /etc/ssh/sshd_config
validate: sshd -t -f %s
notify:
- reload sshd
when: ('systemcontroller' in group_names)
become: yes
- name: Verify LDAP user groups
fail:
msg: "{{ in_user_id }} is not part of group {{ item }}"
when: item not in user_groups.stdout
loop: "{{ user_group_array }}"

View File

@ -0,0 +1,33 @@
---
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Tasks to check LDAP user existence, to delete LDAP account. If the system is
# distributed cloud, it dynamically adds subclouds to the target host list.
- name: Check if LDAP user exists
command: ldapsearch -x -LLL uid={{ in_user_id }}
register: in_user_id_check
become: yes
- name: Delete LDAP user {{ in_user_id }} only if it exists
command: ldapdeleteuser {{ in_user_id }}
become: yes
when: in_user_id_check.stdout | length != 0
- name: Get distributed role
include_role:
name: manage-local-ldap-account/common/get-distributed-role
- name: Get online subclouds
include_role:
name: manage-local-ldap-account/common/get-online-subclouds
- name: Populate inventory with subclouds
include_role:
name: manage-local-ldap-account/common/add-hosts
vars:
in_item: "{{ item }}"
loop: "{{ subcloud_list }}"
when: is_dc | bool

View File

@ -0,0 +1,23 @@
---
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Tasks to delete both keystone and LDAP user account inside the system
# controller, and subclouds as well for distributed systems.
- name: Delete keystone user on System Controller
block:
- name: Delete the keystone user {{ in_user_id }}
shell: >-
source /etc/platform/openrc; openstack {{ os_param_region_name }} user delete {{ in_user_id }}
when: ('systemcontroller' in group_names)
- name: Wait for keystone user to be deleted in all subclouds
shell: source /etc/platform/openrc; ! openstack user show {{ in_user_id }}
register: user_output
until: user_output.rc == 0
retries: 12
delay: 10
when: ('systemcontroller' not in group_names)