From 3035e2533323e7ab42c75ed65f77ff2f739323c0 Mon Sep 17 00:00:00 2001 From: Dmitriy Rabotyagov Date: Mon, 2 Jun 2025 21:07:21 +0200 Subject: [PATCH] Add support for generation of SSH keypairs If operator needs to enter guest agent instance for troubleshooting, they need to create a keypair, upload it as Trove user specifically, create a security group and define it's UUID in trove.conf This process is quite cumbersome and time consuming, thus this patch implements mentioned fuctionality and can be enabled with a single variable. Process is alike to what we have and been using for Octavia for a while. Change-Id: I29984c565c808bca79ef39a02e79d9b015a70786 --- defaults/main.yml | 16 ++++ ...trove_ssh_guestagent-c9e0e81358d9280e.yaml | 8 ++ tasks/main.yml | 76 +++++++++---------- tasks/trove_resources.yml | 30 ++++++++ tasks/trove_service_network.yml | 19 +++++ templates/trove.conf.j2 | 8 +- 6 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 releasenotes/notes/trove_ssh_guestagent-c9e0e81358d9280e.yaml diff --git a/defaults/main.yml b/defaults/main.yml index 7e1e972..84cc77f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -256,6 +256,22 @@ trove_guestagent_images: [] trove_guest_auth_url: "{{ keystone_service_publicurl }}" trove_guest_swift_url: "{{ trove_service_publicuri_proto }}://{{ external_lb_vip_address }}:{{ swift_proxy_port }}/v1/AUTH_" +trove_resources_deploy_host: localhost +trove_resources_deploy_python_interpreter: "{{ ansible_playbook_python }}" +trove_guest_ssh_enabled: false +trove_guest_ssh_key_manage: true +trove_guest_ssh_key_name: trove_guestagent_key +trove_guest_ssh_key_dir: "{{ openstack_ssh_keypairs_dir | default(lookup('env', 'HOME') ~ '/.ssh') }}" +trove_guest_ssh_key_comment: "Generated-By-OpenStack-Ansible" +# Options: ssh, pkcs1 and pkcs8 +trove_guest_ssh_key_format: ssh +# Options: rsa, dsa, rsa1, ecdsa, ed25519 +trove_guest_ssh_key_type: rsa +trove_guest_ssh_key_size: 4096 +# Security group which will allow SSH connections +trove_guest_ssh_security_group_name: trove_guest_management +trove_guest_ssh_security_group_extra_rules: [] + trove_swift_enabled: >- {{ (groups['swift_all'] is defined and groups['swift_all'] | length > 0) or diff --git a/releasenotes/notes/trove_ssh_guestagent-c9e0e81358d9280e.yaml b/releasenotes/notes/trove_ssh_guestagent-c9e0e81358d9280e.yaml new file mode 100644 index 0000000..dd246d2 --- /dev/null +++ b/releasenotes/notes/trove_ssh_guestagent-c9e0e81358d9280e.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Implemented SSH keypair generation for Trove Guest Agent. When + ``trove_guest_ssh_enabled`` is set to True, role will perform SSH + keypair generation and upload to Nova. With that, a security group + will be created and added to the ``management_security_groups`` + which will allow SSH traffic on dbaas network. diff --git a/tasks/main.yml b/tasks/main.yml index 8616908..2247638 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -158,6 +158,44 @@ tags: - trove-install +- name: Including osa.service_setup role + ansible.builtin.include_role: + name: openstack.osa.service_setup + apply: + tags: + - trove-install + - common-service + vars: + _project_name: "{{ trove_service_project_name }}" + _project_domain: "{{ trove_service_project_domain_id }}" + _service_adminuri_insecure: "{{ keystone_service_adminuri_insecure }}" + _service_setup_host: "{{ trove_service_setup_host }}" + _service_setup_host_python_interpreter: "{{ trove_service_setup_host_python_interpreter }}" + _service_in_ldap: "{{ trove_service_in_ldap }}" + _service_project_name: "{{ trove_service_project_name }}" + _service_region: "{{ trove_service_region }}" + _service_users: + - name: "{{ trove_service_user_name }}" + password: "{{ trove_service_password }}" + role: "{{ trove_service_admin_role_names }}" + _service_endpoints: + - service: "{{ trove_service_name }}" + interface: "public" + url: "{{ trove_service_publicurl }}" + - service: "{{ trove_service_name }}" + interface: "internal" + url: "{{ trove_service_internalurl }}" + - service: "{{ trove_service_name }}" + interface: "admin" + url: "{{ trove_service_adminurl }}" + _service_catalog: + - name: "{{ trove_service_name }}" + type: "{{ trove_service_type }}" + description: "{{ trove_service_description }}" + when: _trove_is_first_play_host + tags: + - always + - name: Including trove_resources tasks ansible.builtin.include_tasks: trove_resources.yml when: @@ -221,44 +259,6 @@ - trove-config - uwsgi -- name: Including osa.service_setup role - ansible.builtin.include_role: - name: openstack.osa.service_setup - apply: - tags: - - trove-install - - common-service - vars: - _project_name: "{{ trove_service_project_name }}" - _project_domain: "{{ trove_service_project_domain_id }}" - _service_adminuri_insecure: "{{ keystone_service_adminuri_insecure }}" - _service_setup_host: "{{ trove_service_setup_host }}" - _service_setup_host_python_interpreter: "{{ trove_service_setup_host_python_interpreter }}" - _service_in_ldap: "{{ trove_service_in_ldap }}" - _service_project_name: "{{ trove_service_project_name }}" - _service_region: "{{ trove_service_region }}" - _service_users: - - name: "{{ trove_service_user_name }}" - password: "{{ trove_service_password }}" - role: "{{ trove_service_admin_role_names }}" - _service_endpoints: - - service: "{{ trove_service_name }}" - interface: "public" - url: "{{ trove_service_publicurl }}" - - service: "{{ trove_service_name }}" - interface: "internal" - url: "{{ trove_service_internalurl }}" - - service: "{{ trove_service_name }}" - interface: "admin" - url: "{{ trove_service_adminurl }}" - _service_catalog: - - name: "{{ trove_service_name }}" - type: "{{ trove_service_type }}" - description: "{{ trove_service_description }}" - when: _trove_is_first_play_host - tags: - - always - - name: Importing trove_db_sync tasks ansible.builtin.import_tasks: trove_db_sync.yml when: _trove_conductor_is_first_play_host diff --git a/tasks/trove_resources.yml b/tasks/trove_resources.yml index 14578e1..32c95ac 100644 --- a/tasks/trove_resources.yml +++ b/tasks/trove_resources.yml @@ -19,6 +19,23 @@ vars: openstack_resources_setup_host: "{{ trove_service_setup_host }}" openstack_resources_python_interpreter: "{{ trove_service_setup_host_python_interpreter }}" + openstack_resources_deploy_host: "{{ trove_resources_deploy_host }}" + openstack_resources_deploy_python_interpreter: "{{ trove_resources_deploy_python_interpreter }}" + _keypairs: + - name: "{{ trove_guest_ssh_key_name }}" + path: "{{ trove_guest_ssh_key_dir }}/{{ trove_guest_ssh_key_name }}" + state: "{{ (trove_guest_ssh_enabled | bool) | ternary('present', 'absent') }}" + private_key_format: "{{ trove_guest_ssh_key_format }}" + size: "{{ trove_guest_ssh_key_size }}" + comment: "{{ trove_guest_ssh_key_comment }}" + type: "{{ trove_guest_ssh_key_type }}" + auth: + auth_url: "{{ keystone_service_adminurl }}" + username: "{{ trove_service_user_name }}" + password: "{{ trove_service_password }}" + project_name: "{{ trove_service_project_name }}" + user_domain_name: "{{ trove_service_user_domain_id }}" + project_domain_name: "{{ trove_service_project_domain_id }}" _network_resources: - name: "{{ trove_service_net_name }}" network_type: "{{ trove_service_net_type }}" @@ -31,7 +48,20 @@ dhcp: "{{ trove_service_net_dhcp }}" allocation_start: "{{ trove_service_net_allocation_pool_start | default(omit) }}" allocation_end: "{{ trove_service_net_allocation_pool_end | default(omit) }}" + _security_groups: + - name: "{{ trove_guest_ssh_security_group_name }}" + description: "security group for octavia amphora" + project: "{{ trove_service_project_name }}" + security_group_rules: + - protocol: tcp + port_range_min: 22 + port_range_max: 22 + remote_ip_prefix: "{{ trove_service_net_subnet_cidr }}" + openstack_resources_network: networks: "{{ trove_service_net_setup | ternary(_network_resources, []) }}" + security_groups: "{{ (trove_guest_ssh_enabled) | ternary(_security_groups + trove_guest_ssh_security_group_extra_rules, []) }}" openstack_resources_image: images: "{{ _trove_glance_images_compat }}" + openstack_resources_compute: + keypairs: "{{ (trove_guest_ssh_key_manage | bool) | ternary(_keypairs, {}) }}" diff --git a/tasks/trove_service_network.yml b/tasks/trove_service_network.yml index 0220e9f..07b4db2 100644 --- a/tasks/trove_service_network.yml +++ b/tasks/trove_service_network.yml @@ -42,3 +42,22 @@ ansible.builtin.set_fact: trove_service_net_id: "{{ _get_trove_service_net.networks[0].id }}" run_once: true + + + - name: Register created security group + run_once: true + when: + - trove_guest_ssh_enabled + block: + - name: Get trove guestagent SSH security group ID + openstack.cloud.security_group_info: + cloud: default + validate_certs: "{{ trove_service_net_validate_certs }}" + wait: true + endpoint_type: "{{ trove_service_net_endpoint_type }}" + name: "{{ trove_guest_ssh_security_group_name }}" + register: _get_trove_security_group + + - name: Save security group as fact + ansible.builtin.set_fact: + trove_guest_ssh_security_group_id: "{{ _get_trove_security_group.security_groups[0].id | default('') }}" diff --git a/templates/trove.conf.j2 b/templates/trove.conf.j2 index 69a19e9..edd0041 100644 --- a/templates/trove.conf.j2 +++ b/templates/trove.conf.j2 @@ -59,8 +59,12 @@ management_networks = {{ trove_service_net_id }} neutron_endpoint_type = {{ trove_service_neutron_endpoint_type }} neutron_service_type = network -{% if trove_management_security_groups | length > 0 %} -management_security_groups = {{ trove_management_security_groups | join(',') }} +{% set _enabled_security_groups = trove_management_security_groups %} +{% if trove_guest_ssh_enabled %} +{% set _ = _enabled_security_groups.append(trove_guest_ssh_security_group_id) %} +{% endif %} +{% if _enabled_security_groups | length > 0 %} +management_security_groups = {{ _enabled_security_groups | join(',') }} {% endif %} {% if trove_swift_enabled is defined %}