Support running without root privileges

We shouldn't need root if all of our dependencies are already installed
and the config directories are all writeable by our user.

Depends-On: https://review.opendev.org/c/openstack/kolla-ansible/+/920294
Change-Id: I96633904fc54355b51abfc7ea5c85480df8beb76
This commit is contained in:
Will Szumski
2024-07-03 16:46:09 +01:00
parent f0609a8386
commit 7fd3f6bdc7
12 changed files with 138 additions and 25 deletions

View File

@@ -70,3 +70,8 @@ kayobe_ansible_setup_filter: "{{ omit }}"
# Gather subset to apply to the setup module when gathering facts. Default is
# to not specify a gather subset.
kayobe_ansible_setup_gather_subset: "{{ omit }}"
# Whether or not we should try and escalate privileges on the control host.
# This allows us to install packages and create arbitrary directories that our
# user would not normally have permission to create. Default is true.
kayobe_control_host_become: true

View File

@@ -496,6 +496,10 @@ kolla_ansible_group: kolla
# Ansible.
kolla_ansible_become: false
# Whether to use privilege escalation for operations on the control host.
# Default is {{ kayobe_control_host_become }}.
kolla_ansible_control_host_become: "{{ kayobe_control_host_become | bool }}"
# Whether to create a user account, configure passwordless sudo and authorise
# an SSH key for Kolla Ansible. Default is 'true'.
kolla_ansible_create_user: true

View File

@@ -86,6 +86,7 @@
- import_role:
name: kolla-ansible
vars:
kolla_ansible_control_host_become: "{{ kayobe_control_host_become | bool }}"
kolla_ansible_install_epel: "{{ dnf_install_epel }}"
kolla_external_fqdn_cert: "{{ kolla_config_path }}/certificates/haproxy.pem"
kolla_internal_fqdn_cert: "{{ kolla_config_path }}/certificates/haproxy-internal.pem"

View File

@@ -1,14 +1,49 @@
---
- block:
- name: Testing privilege escalation
raw: "true"
become: true
failed_when: false
changed_when: false
register: privilege_escalation_result
- name: Assert that we can escalate privileges
assert:
that:
- privilege_escalation_result is success
- '"password is required" not in privilege_escalation_result.stderr'
fail_msg: >-
Could not escalate privileges. You can either: set kayobe_control_host_become: true,
set ansible_become_password, or set up passwordless sudo.
when: kayobe_control_host_become | bool
- name: Include OS family-specific variables
include_vars: "{{ ansible_facts.os_family }}.yml"
- name: Ensure required packages are installed
package:
name: "{{ bootstrap_package_dependencies }}"
state: present
cache_valid_time: "{{ apt_cache_valid_time if ansible_facts.os_family == 'Debian' else omit }}"
update_cache: "{{ True if ansible_facts.os_family == 'Debian' else omit }}"
become: True
- name: Gather the package facts
ansible.builtin.package_facts:
manager: auto
- block:
- name: Assert that all packages are installed if not using privilege escalation
assert:
that: missing_packages is falsy
fail_msg: >-
The following packages are missing from your system: {{ missing_packages | join(', ') }} and
privilege escalation is disabled. Please get your system administator to install these packages
or enable kayobe_control_host_become.
when: not kayobe_control_host_become | bool
- name: Ensure required packages are installed
package:
name: "{{ bootstrap_package_dependencies }}"
state: present
cache_valid_time: "{{ apt_cache_valid_time if ansible_facts.os_family == 'Debian' else omit }}"
update_cache: "{{ True if ansible_facts.os_family == 'Debian' else omit }}"
become: True
when: missing_packages is truthy
vars:
missing_packages: "{{ bootstrap_package_dependencies | difference(ansible_facts.packages.keys()) }}"
- name: Check whether an SSH key exists
stat:

View File

@@ -1,5 +1,7 @@
---
# List of package dependencies to install.
# NOTE(wszusmki): meta packages are not supported in this list since we cannot
# determine if they are installed via ansible facts.
bootstrap_package_dependencies:
- git
- vim
- vim-enhanced

View File

@@ -77,6 +77,9 @@ kolla_ansible_group: kolla
# Ansible.
kolla_ansible_become: false
# Whether to use privilege escalation for operations on the control host.
kolla_ansible_control_host_become: true
###############################################################################
# Kolla-ansible inventory configuration.

View File

@@ -33,7 +33,7 @@
owner: "{{ ansible_facts.user_uid }}"
group: "{{ ansible_facts.user_gid }}"
mode: 0750
become: True
become: "{{ kolla_ansible_control_host_become | bool }}"
with_items:
- "{{ kolla_config_path }}"
- "{{ kolla_seed_inventory_path }}"

View File

@@ -2,27 +2,57 @@
- name: Include OS family-specific variables
include_vars: "{{ ansible_facts.os_family }}.yml"
- name: Ensure EPEL repo is installed
package:
name: epel-release
state: present
become: True
- name: Gather the package facts
ansible.builtin.package_facts:
manager: auto
- block:
- name: Assert that epel-release package is installed if not using privilege escalation
assert:
that: "'epel-release' in ansible_facts.packages.keys()"
fail_msg: >-
The following packages are missing from your system: epel-release and
privilege escalation is disabled. Please get your system administator
to install these packages or enable kolla_ansible_control_host_become.
when:
- not kolla_ansible_control_host_become | bool
- name: Ensure EPEL repo is installed
package:
name: epel-release
state: present
become: True
when: "'epel-release' not in ansible_facts.packages.keys()"
vars:
ansible_python_interpreter: /usr/bin/python3
when:
- ansible_facts.os_family == 'RedHat'
- kolla_ansible_install_epel | bool
- name: Ensure required packages are installed
package:
# NOTE(mgoddard): select non-empty packages.
name: "{{ kolla_ansible_package_dependencies | select | list }}"
state: present
cache_valid_time: "{{ apt_cache_valid_time if ansible_facts.os_family == 'Debian' else omit }}"
update_cache: "{{ True if ansible_facts.os_family == 'Debian' else omit }}"
- block:
- name: Assert that all packages are installed if not using privilege escalation
assert:
that: missing_packages is falsy
fail_msg: >-
The following packages are missing from your system:
{{ missing_packages | join(', ') }} and privilege escalation is disabled. Please get
your system administator to install these packages or enable
kolla_ansible_control_host_become.
when: not kolla_ansible_control_host_become | bool
- name: Ensure required packages are installed
package:
name: "{{ packages }}"
state: present
cache_valid_time: "{{ apt_cache_valid_time if ansible_facts.os_family == 'Debian' else omit }}"
update_cache: "{{ True if ansible_facts.os_family == 'Debian' else omit }}"
become: True
when: missing_packages is truthy
vars:
# NOTE(mgoddard): select non-empty packages.
ansible_python_interpreter: /usr/bin/python3
become: True
packages: "{{ kolla_ansible_package_dependencies | select | list }}"
missing_packages: "{{ packages | difference(ansible_facts.packages.keys()) }}"
- name: Ensure source code checkout parent directory exists
file:
@@ -30,7 +60,7 @@
state: directory
owner: "{{ ansible_facts.user_uid }}"
group: "{{ ansible_facts.user_gid }}"
become: True
become: "{{ kolla_ansible_control_host_become | bool }}"
when: kolla_ansible_ctl_install_type == 'source'
- name: Ensure Kolla Ansible source code checkout exists
@@ -44,7 +74,7 @@
file:
path: "{{ kolla_ansible_venv }}"
state: absent
become: True
become: "{{ kolla_ansible_control_host_become | bool }}"
when:
- kolla_ansible_venv is not none
- (kolla_ansible_venv ~ '/bin/python') | realpath != kolla_ansible_venv_python | realpath
@@ -55,7 +85,7 @@
state: directory
owner: "{{ ansible_facts.user_uid }}"
group: "{{ ansible_facts.user_gid }}"
become: True
become: "{{ kolla_ansible_control_host_become | bool }}"
when: kolla_ansible_venv is not none
- name: Ensure the latest version of pip is installed

View File

@@ -83,3 +83,19 @@ which can be used to improve visibility into changes that would be made on
target systems. The Kayobe CLI supports the ``--check`` argument, and since
11.0.0, the ``--diff`` argument. Note that these modes are not always
guaranteed to work, when some tasks are dependent on earlier ones.
Avoiding privilege escalation on the control host
-------------------------------------------------
.. note::
This means that kayobe will not be able to install OS packages or use paths
that are not writable for your user.
It is possible to avoid privilege escalation on the control host. To use this feature set
the following config option:
.. code-block:: yaml
:caption: ``$KAYOBE_CONFIG_PATH/globals.yml``
kayobe_control_host_become: false

View File

@@ -68,6 +68,11 @@
# equivalent to a value of 100.
#kayobe_max_fail_percentage:
# Whether or not we should try and escalate privileges on the control host.
# This allows us to install packages and create arbitrary directories that our
# user would not normally have permission to create. Default is true.
#kayobe_control_host_become:
###############################################################################
# Dummy variable to allow Ansible to accept this file.
workaround_ansible_issue_8743: yes

View File

@@ -267,6 +267,10 @@
# Primary group of Kolla SSH user. Default is 'kolla'.
#kolla_ansible_group:
# Whether to use privilege escalation for operations on the control host.
# Default is {{ kayobe_control_host_become }}.
#kolla_ansible_control_host_become:
# Whether to use privilege escalation for all operations performed via Kolla
# Ansible. Default is 'false'.
#kolla_ansible_become:

View File

@@ -0,0 +1,8 @@
---
features:
- |
Allows running without root privileges, provided that all Kayobe package
dependencies are installed and all configured paths are writable for the
current user, e.g. Python virtualenvs and output directories. To use
this feature set ``kayobe_control_host_become`` to ``false`` in
``$KAYOBE_CONFIG_PATH/globals.yml``.