LDAP playbook simplification and cleanup

The scenario where a new subcloud is added to a DC after the execution
of "manage_local_ldap_account.yml" playbook is not being supported in
the current implementation, because the openrc file of the new Keystone
user is created in each cloud by the playbook and the new subcloud will
not have this file. The solution for this is the openrc file to be
created by the subcloud itself and not by the playbook.
Besides the problem of openrc file creation, the current implementation
of "manage_local_ldap_account.yml" playbook has other problems, like
trying to add the new LDAP user to linux groups locally in each cloud
(this is unnecessary and wrong).
To deal with these issues, all non-essentials actions of
"manage_local_ldap_account.yml" playbook were removed.
The "manage_local_ldap_account.yml" playbook, before this commit, did
the following actions: it created a LDAP user, created a Keystone user,
created an openrc file in every cloud's active controller (in central
cloud and subclouds for DC environments, in the standalone cloud for
standalone environments) and verified that the created Keystone user
is propagated to every subcloud (in DC environments).
After this commit, the "manage_local_ldap_account.yml" playbook will do
fewer actions: it will just create a LDAP user and a Keystone user. The
openrc file will be created by the user (see
https://review.opendev.org/c/starlingx/utilities/+/887117).
In DC environments, the "manage_local_ldap_account.yml" playbook will no
longer check if the created Keystone user propagated to managed
subclouds, as it is handled by DC orchestration. It will be added in the
documentation that, for already managed and synced subclouds, it may
take up to two minutes to get the Keystone user propagated to all
subclouds.

Test Plan:

PASS: Successfully create 2 environments: a DC with 1 AIO-SX subcloud
and a standalone AIO-DX, both using an image containing this change.
PASS: In the DC central cloud and in the AIO-DX, successfully create a
user using the command "ansible-playbook --inventory inventory.txt
--extra-vars='user_id=user5 mode=create'
/usr/share/ansible/stx-ansible/playbooks/manage_local_ldap_account.yml".
Targeting each cloud (central cloud, subcloud and AIO-DX), execute a SSH
using the new user, execute 'source local_starlingxrc', provide Keystone
password and execute 'system host-list' with no errors.
PASS: In the DC central cloud and in the AIO-DX, successfully delete
"user5" (created in the previous test) using
"manage_local_ldap_account.yml" playbook with 'mode=delete'. Targeting
each cloud (central cloud, subcloud and AIO-DX), try to SSH using the
deleted user and verify that it fails. Check that the Keystone user was
removed from each cloud using the command "openstack user list".
PASS: In the DC subcloud, try to create a new user with
"manage_local_ldap_account.yml" playbook and check that it fails with a
message saying the playbook should not run on subclouds.
PASS: In the DC central cloud, create a LDAP user called "user10" using
command "ldapusersetup", then try to create the same user using
"manage_local_ldap_account.yml" playbook and check that it fails with a
message saying the LDAP user already exists.
PASS: In the DC central cloud, successfully delete the LDAP user
"user10" (created in previous test) using
"manage_local_ldap_account.yml" playbook with 'mode=delete'.
PASS: In the DC central cloud, create a Keystone user called "user15"
using command "openstack user create", then try to create the same user
using "manage_local_ldap_account.yml" playbook and check that it fails
with a message saying the Keystone user already exists.
PASS: In the DC central cloud, successfully delete the Keystone user
"user15" (created in previous test) using
"manage_local_ldap_account.yml" playbook with 'mode=delete'.

Partial-Bug: 2024627
Depends-On: https://review.opendev.org/c/starlingx/utilities/+/887117
Signed-off-by: Joao Victor Portal <Joao.VictorPortal@windriver.com>
Change-Id: I7ebd570ca7fc7a6d53d3b2ab42d3e5083e83949c
This commit is contained in:
Joao Victor Portal 2023-06-20 17:13:04 -03:00
parent 47a3a4826f
commit 5bd1246be7
9 changed files with 102 additions and 287 deletions

View File

@ -3,31 +3,32 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# Create a new LDAP user with keystone account and sudo access. The playbook
# uses the openrc-template.j2 file as a template for the keystone account
# openrc file.
# Create new LDAP and Keystone users with same username. In DC environments,
# should be executed in the central cloud to allow the propagation of created
# Keystone user to the subclouds.
#
# Users will be prompted for the following parameters:
# - user_id : id for the new account
# The operator will be prompted for the following parameters:
# - user_password : password for the new account.
# The parameters below use a default value if they are not defined:
# - mode : controls if the user should be created or deleted.
# The valid values are 'create' and 'delete'.
# (default: 'create')
# - password_change_period : number of days before needing to change password
# (default: 90)
# - password_warning_period : number of days to warn about changing the password
# (default: 2)
# - sudo_permission : give sudo capabilities to new user to execute
# commands with root privileges (default: no)
# - user_role : role for the new user as 'admin'/'member'/'reader'
# (default: 'admin')
# - sys_protected : is used to add the new user to the group
# "sys_protected". (default: no)
#
# The inventory file contains the password of system controller
# Do not add any subclouds to the inventory file. The list of subclouds
# will be dynamically added to the inventory by the playbook itself.
# The parameters below should be provided, otherwise the playbook either fails
# or uses the default value.
# - user_id : the username to be used. Should always be
# provided.
# - mode : controls if the users should be created or
# deleted. The valid values are 'create' and
# 'delete' (default: 'create').
# - password_change_period : number of days before needing to change LDAP
# password (default: 90).
# - password_warning_period : number of days to warn about changing the LDAP
# password (default: 2).
# - sudo_permission : give sudo capabilities to new LDAP user to execute
# commands with root privileges (default: no).
# - user_role : role for the new Keystone user as
# 'admin'/'member'/'reader' (default: 'admin').
# - sys_protected : is used to add the new LDAP user to the group
# "sys_protected" (default: no).
#
# The inventory file contains the system controller IP, user and password.
#
# Example to add user 'na-admin' (mode=create is default):
# ansible-playbook --inventory inventory --extra-vars='user_id=na-admin' \
@ -45,12 +46,10 @@
- hosts: systemcontroller
gather_facts: no
vars_prompt:
- name: user_id
prompt: "What is the name of the user account?"
private: no
vars:
ssh_internal_args: -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
pre_tasks:
tasks:
- set_fact:
in_user_id: "{{ user_id if user_id is defined else ''}}"
@ -111,6 +110,48 @@
msg: "The sys_protected must be 'yes' or 'no'."
when: "in_sys_protected not in [true, false]"
- name: Get distributed cloud role
import_role:
name: manage-local-ldap-account/common/get-distributed-role
# This playbook should not run on subclouds because the Keystone user would not propagate to other clouds.
- name: Fail if running on subcloud
fail:
msg: "This playbook should run on the central cloud, not in subclouds."
when: is_dc_subcloud
- name: Get LDAP user data
command: ldapsearch -x -LLL uid={{ in_user_id }}
register: ldap_user_output_reg
- name: Store info about LDAP user existence
set_fact:
ldap_user_exists: "{{ true if ldap_user_output_reg.stdout != '' else false }}"
- name: Validate that informed LDAP user doesn't exist when mode is create
fail:
msg: "The LDAP user {{ in_user_id }} already exists.
Run this playbook with mode=delete to remove it first."
when: in_mode == 'create' and ldap_user_exists
- name: Get Keystone user data
shell: source /etc/platform/openrc; openstack user list | grep -w {{ in_user_id }} | wc -l
register: openstack_user_output_reg
- name: Store info about Keystone user existence
set_fact:
openstack_user_exists: "{{ true if openstack_user_output_reg.stdout != '0' else false }}"
- name: Validate that informed Keystone user doesn't exist when mode is create
fail:
msg: "The Keystone user {{ in_user_id }} already exists.
Run this playbook with mode=delete to remove it first."
when: in_mode == 'create' and openstack_user_exists
- name: Set os_param_region_name if system is a DC systemcontroller
set_fact:
os_param_region_name: "{{ '--os-region-name SystemController' if is_dc_systemcontroller == true else '' }}"
- block:
- pause:
prompt: "What is the password for the user account?"
@ -126,35 +167,28 @@
when: "in_user_password is not defined or in_user_password ==''"
when: in_mode == 'create'
- name: Create LDAP and Keystone user {{ in_user_id }}
block:
- hosts: systemcontroller
gather_facts: no
vars:
ssh_internal_args: -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
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'
name: manage-local-ldap-account/create-keystone-account
- hosts: all
gather_facts: no
when: in_mode == 'create'
vars:
ssh_internal_args: -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
- name: Delete LDAP and Keystone user {{ in_user_id }}
block:
tasks:
- name: Manage keystone user {{ in_user_id }}
block:
- include_role:
name: manage-local-ldap-account/create-keystone-account
when: in_mode == 'create'
- name: Delete LDAP user {{ in_user_id }} if it exists
command: ldapdeleteuser {{ in_user_id }}
become: yes
when: ldap_user_exists
- include_role:
name: manage-local-ldap-account/delete-keystone-account
when: in_mode == 'delete'
- name: Delete the Keystone user {{ in_user_id }} if it exists
shell: >-
source /etc/platform/openrc; openstack {{ os_param_region_name }} user delete {{ in_user_id }}
when: openstack_user_exists
when: in_mode == 'delete'

View File

@ -1,18 +0,0 @@
---
# Copyright (c) 2022-2023 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 }}"
in_sudo_permission: "{{ in_sudo_permission }}"
in_sys_protected: "{{ in_sys_protected }}"
in_mode: "{{ in_mode }}"
in_user_password: "{{ in_user_password if in_mode == 'create' else '' }}"
in_user_role: "{{ in_user_role if in_mode == 'create' else '' }}"

View File

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

View File

@ -1,28 +0,0 @@
---
# 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,16 +3,10 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# 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.
# Create LDAP user and set password.
#
- name: Check if LDAP user exists
shell: ldapsearch -x -LLL uid={{ in_user_id }}
register: in_user_id_check
become: yes
- name: Create LDAP user only if it does not already exist
- name: Create LDAP user
block:
- name: Set sudo_param if external variable sudo_permission is true
set_fact:
@ -30,7 +24,7 @@
# In the following task, the string "LDAP Password" is found only in CentOS,
# while the string "Current Password" is found only in Debian.
- name: Change LDAP user initial password and create home directory
- name: Change LDAP user initial password
expect:
command: ssh {{ ssh_internal_args }} {{ in_user_id }}@localhost
responses:
@ -48,7 +42,7 @@
- name: Handle initial password change errors
block:
- name: Delete ldap user
- name: Delete ldap user if initial password change was not successful
shell: ldapdeleteuser {{ in_user_id }}
become: yes
@ -57,20 +51,3 @@
msg: " {{ change_password.stdout }} \n\nFailed to change initial password, check the log above for more details."
when: change_password.rc != 0
when: in_user_id_check.stdout == ""
- name: Get distributed cloud 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

@ -3,11 +3,10 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# Tasks to create both keystone and LDAP user account inside the system
# controller, and subclouds as well for distributed systems with specific
# admin role.
# Create Keystone user, set password and assign its role.
#
- name: Create keystone user on System Controller
- name: Create Keystone user
block:
- name: Create the keystone user {{ in_user_id }}
expect:
@ -18,82 +17,7 @@
Password: '{{ in_user_password }}'
"\\~\\$": exit
- name: Add keystone user to the {{ in_user_role }} role
- name: Add Keystone user to the {{ in_user_role }} role
shell: |
source /etc/platform/openrc
openstack {{ os_param_region_name }} role add --user {{ in_user_id }} --project admin {{ in_user_role }}
when: ('systemcontroller' in group_names)
- 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
- name: Create LDAP user 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
when: ('systemcontroller' not in group_names)
- name: Retrieve region name
shell: source /etc/platform/openrc; system show | grep region_name | awk '{ print $4 }'
register: region_name
- 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: 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: Add LDAP user to 'root' group
command: usermod -a -G root {{ in_user_id }}
become: yes
when: in_sudo_permission
- name: Add LDAP user to 'sys_protected' group
command: usermod -a -G sys_protected {{ in_user_id }}
become: yes
when: in_sys_protected
- name: Retrieve LDAP user groups
command: groups {{ in_user_id }}
register: user_groups
- name: Set array of user groups to check
set_fact:
user_group_array: ['users']
- 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: Update array of user groups to include sys_protected group if sys_protected permission is granted
set_fact:
user_group_array: "{{ user_group_array }} + ['sys_protected']"
when: in_sys_protected
- 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

@ -1,23 +0,0 @@
unset OS_SERVICE_TOKEN
export OS_ENDPOINT_TYPE=internalURL
export CINDER_ENDPOINT_TYPE=internalURL
export OS_USERNAME={{ in_user_id }}
export OS_PASSWORD='{{ in_user_password }}'
export OS_AUTH_TYPE=password
export OS_AUTH_URL=http://{{ management_floating_ip.stdout | ipwrap }}:5000/v3
export OS_PROJECT_NAME=admin
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default
export OS_IDENTITY_API_VERSION=3
export OS_REGION_NAME={{ region_name.stdout }}
export OS_INTERFACE=internal
if [ ! -z "${OS_PASSWORD}" ]; then
export PS1='[\u@\h \W(keystone_$OS_USERNAME)]\$ '
else
echo 'Openstack Admin credentials can only be loaded from the active controller.'
export PS1='\h:\w\$ '
fi

View File

@ -1,33 +0,0 @@
---
# 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

@ -1,23 +0,0 @@
---
# 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)