From 30e1c09384655e44acd6e25e2c1cf08fc6734685 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:45:27 -0500 Subject: [PATCH 1/4] Bump productmd from 1.40 to 1.41 (#16857) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 73a0cd0694a..e0faa294a3c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ fauxfactory==3.1.1 jinja2==3.1.4 manifester==0.2.8 navmazing==1.2.2 -productmd==1.40 +productmd==1.41 pyotp==2.9.0 python-box==7.2.0 pytest==8.3.3 From 50806c858180615cee44855abac3421633056cee Mon Sep 17 00:00:00 2001 From: rmynar <64528205+rmynar@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:04:56 +0100 Subject: [PATCH 2/4] Fix test_positive_mismatched_satellite_fqdn (#16796) don't use nameservers to simulate mismatched hostname --- tests/foreman/destructive/test_installer.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/foreman/destructive/test_installer.py b/tests/foreman/destructive/test_installer.py index 80a84786acc..aadd2bc9214 100644 --- a/tests/foreman/destructive/test_installer.py +++ b/tests/foreman/destructive/test_installer.py @@ -28,10 +28,15 @@ def set_random_fqdn(target_sat): shortname = gen_string('alpha') new_domain = gen_domain() target_sat.execute( - f'echo "search {new_domain}" >> /etc/resolv.conf; hostnamectl set-hostname {shortname}' + 'mv -f /etc/resolv.conf /etc/resolv.conf.bak; ' + f'echo "search {new_domain}" > /etc/resolv.conf; ' + f'hostnamectl set-hostname {shortname}' ) yield shortname, new_domain - target_sat.execute(f'hostnamectl set-hostname {target_sat.hostname}') + target_sat.execute( + 'mv -f /etc/resolv.conf.bak /etc/resolv.conf; ' + f'hostnamectl set-hostname {target_sat.hostname}' + ) def test_installer_sat_pub_directory_accessibility(target_sat): From ac827002e67bbd8a2f2768ceca8e4d02cb1f8fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hellebrandt?= Date: Tue, 5 Nov 2024 11:33:00 +0100 Subject: [PATCH 3/4] Refactor IPA users and groups, make the data structure make sense (#16536) * Refactor IPA users and groups, make the data structure make sense * Use admin for the test, admin is in both groups --- conf/ipa.yaml.template | 10 ++-- pytest_fixtures/component/satellite_auth.py | 2 +- robottelo/config/validators.py | 6 +- robottelo/hosts.py | 2 +- tests/foreman/ui/test_ldap_authentication.py | 60 +++++++++++--------- 5 files changed, 44 insertions(+), 36 deletions(-) diff --git a/conf/ipa.yaml.template b/conf/ipa.yaml.template index a8a15add1f2..88c13a90c54 100755 --- a/conf/ipa.yaml.template +++ b/conf/ipa.yaml.template @@ -9,10 +9,10 @@ IPA: OTP_USER: otp_user TIME_BASED_SECRET: # update the time based token secret DISABLED_IPA_USER: disabled_user - GROUP_USERS: - - satadmin_01 - - satuser_01 + USERS: + USER: satuser_01 + ADMIN: satadmin_01 GROUPS: - - satadmins - - satusers + USERS: satusers + ADMINS: satadmins KEYTAB_URL: diff --git a/pytest_fixtures/component/satellite_auth.py b/pytest_fixtures/component/satellite_auth.py index ef69fcc822c..9468eba15d1 100644 --- a/pytest_fixtures/component/satellite_auth.py +++ b/pytest_fixtures/component/satellite_auth.py @@ -87,7 +87,7 @@ def ipa_data(): 'ldap_hostname': settings.ipa.hostname, 'time_based_secret': settings.ipa.time_based_secret, 'disabled_user_ipa': settings.ipa.disabled_ipa_user, - 'group_users': settings.ipa.group_users, + 'users': settings.ipa.users, 'groups': settings.ipa.groups, } diff --git a/robottelo/config/validators.py b/robottelo/config/validators.py index 1d057ee1744..d3f254499d7 100644 --- a/robottelo/config/validators.py +++ b/robottelo/config/validators.py @@ -172,8 +172,12 @@ 'ipa.user', 'ipa.otp_user', 'ipa.disabled_ipa_user', - 'ipa.group_users', + 'ipa.users', + 'ipa.users.user', + 'ipa.users.admin', 'ipa.groups', + 'ipa.groups.users', + 'ipa.groups.admins', 'ipa.keytab_url', 'ipa.time_based_secret', must_exist=True, diff --git a/robottelo/hosts.py b/robottelo/hosts.py index f7e30b718af..5e38a640b68 100644 --- a/robottelo/hosts.py +++ b/robottelo/hosts.py @@ -2581,7 +2581,7 @@ def __init__(self, sat_obj, **kwargs): 'base_dn': settings.ipa.basedn, 'disabled_user_ipa': settings.ipa.disabled_ipa_user, 'group_base_dn': settings.ipa.grpbasedn, - 'group_users': settings.ipa.group_users, + 'users': settings.ipa.users, 'groups': settings.ipa.groups, 'ipa_otp_username': settings.ipa.otp_user, 'ldap_user_cn': settings.ipa.username, diff --git a/tests/foreman/ui/test_ldap_authentication.py b/tests/foreman/ui/test_ldap_authentication.py index 1992c92a618..1339fdda23d 100644 --- a/tests/foreman/ui/test_ldap_authentication.py +++ b/tests/foreman/ui/test_ldap_authentication.py @@ -103,16 +103,6 @@ def rhsso_groups_teardown(default_sso_host): default_sso_host.delete_rhsso_group(group_name) -@pytest.fixture -def multigroup_setting_cleanup(default_ipa_host): - """Adding and removing the user to/from ipa group""" - sat_users = settings.ipa.groups - idm_users = settings.ipa.group_users - default_ipa_host.add_user_to_usergroup(idm_users[1], sat_users[0]) - yield - default_ipa_host.remove_user_from_usergroup(idm_users[1], sat_users[0]) - - @pytest.fixture def ipa_add_user(default_ipa_host): """Create an IPA user and delete it""" @@ -1163,7 +1153,13 @@ def test_login_failure_if_internal_user_exist( @pytest.mark.tier2 def test_userlist_with_external_admin( - session, auth_source_ipa, ldap_tear_down, groups_teardown, target_sat + session, + auth_source_ipa, + ldap_tear_down, + groups_teardown, + target_sat, + module_org, + module_location, ): """All the external users should be displayed to all LDAP admins (internal and external). @@ -1190,8 +1186,10 @@ def test_userlist_with_external_admin( into Satellite as a local or remote admin. """ # step 1, 2, 3 are already done from IDM and gather the data from settings - sat_admins, sat_users = settings.ipa.groups - idm_admin, idm_user = settings.ipa.group_users + idm_groups_users = settings.ipa.groups.users + idm_groups_admins = settings.ipa.groups.admins + idm_users_user = settings.ipa.users.user + idm_users_admin = settings.ipa.users.admin auth_source_name = f'LDAP-{auth_source_ipa.name}' user_permissions = {'Katello::ActivationKey': PERMISSIONS['Katello::ActivationKey']} @@ -1202,7 +1200,7 @@ def test_userlist_with_external_admin( { 'usergroup.name': 'sat_users', 'roles.resources.assigned': [katello_role.name], - 'external_groups.name': sat_users, + 'external_groups.name': idm_groups_users, 'external_groups.auth_source': auth_source_name, } ) @@ -1210,24 +1208,32 @@ def test_userlist_with_external_admin( { 'usergroup.name': 'sat_admins', 'roles.admin': True, - 'external_groups.name': sat_admins, + 'external_groups.name': idm_groups_admins, 'external_groups.auth_source': auth_source_name, } ) - with target_sat.ui_session(user=idm_user, password=settings.server.ssh_password) as ldapsession: - assert idm_user in ldapsession.task.read_all()['current_user'] + # create AK to read a current user in the next session + ak_name = gen_string('alpha') + session.activationkey.create({'name': ak_name}) + with target_sat.ui_session(user=idm_users_user, password=settings.ipa.password) as ldapsession: + current_user = ldapsession.activationkey.read(ak_name, 'current_user')['current_user'] + assert idm_users_user in current_user # verify the users count with local admin and remote/external admin with ( target_sat.ui_session( - user=idm_admin, password=settings.server.ssh_password + user=idm_users_admin, password=settings.ipa.password ) as remote_admin_session, target_sat.ui_session( user=settings.server.admin_username, password=settings.server.admin_password ) as local_admin_session, ): - assert local_admin_session.user.search(idm_user)[0]['Username'] == idm_user - assert remote_admin_session.user.search(idm_user)[0]['Username'] == idm_user + local_admin_session.organization.select(module_org.name) + local_admin_session.location.select(module_location.name) + remote_admin_session.organization.select(module_org.name) + remote_admin_session.location.select(module_location.name) + assert local_admin_session.user.search(idm_users_user)[0]['Username'] == idm_users_user + assert remote_admin_session.user.search(idm_users_user)[0]['Username'] == idm_users_user @pytest.mark.tier2 @@ -1284,7 +1290,6 @@ def test_positive_group_sync_open_ldap_authsource( def test_verify_group_permissions( session, auth_source_ipa, - multigroup_setting_cleanup, groups_teardown, ldap_tear_down, target_sat, @@ -1303,8 +1308,9 @@ def test_verify_group_permissions( :expectedresults: Group with higher permission is applied on the user """ - sat_users = settings.ipa.groups - idm_users = settings.ipa.group_users + idm_groups_users = settings.ipa.groups.users + idm_groups_admins = settings.ipa.groups.admins + idm_users_admin = settings.ipa.users.admin auth_source_name = f'LDAP-{auth_source_ipa.name}' user_permissions = {None: ['access_dashboard']} katello_role = target_sat.api.Role().create() @@ -1314,7 +1320,7 @@ def test_verify_group_permissions( { 'usergroup.name': 'sat_users', 'roles.resources.assigned': [katello_role.name], - 'external_groups.name': sat_users[0], + 'external_groups.name': idm_groups_users, 'external_groups.auth_source': auth_source_name, } ) @@ -1322,14 +1328,12 @@ def test_verify_group_permissions( { 'usergroup.name': 'sat_admins', 'roles.admin': True, - 'external_groups.name': sat_users[1], + 'external_groups.name': idm_groups_admins, 'external_groups.auth_source': auth_source_name, } ) location_name = gen_string('alpha') - with target_sat.ui_session( - user=idm_users[1], password=settings.server.ssh_password - ) as ldapsession: + with target_sat.ui_session(user=idm_users_admin, password=settings.ipa.password) as ldapsession: ldapsession.location.create({'name': location_name}) location = target_sat.api.Location().search(query={'search': f'name="{location_name}"'})[0] assert location.name == location_name From 34308879e63c81ae7d3b113b43f4cd64bc5edbc8 Mon Sep 17 00:00:00 2001 From: Gaurav Talreja Date: Tue, 5 Nov 2024 18:45:48 +0530 Subject: [PATCH 4/4] Add test for baremetal secureboot provisioning (#15735) * Add test for baremetal secureboot provisioning Signed-off-by: Gaurav Talreja * Update provisioning_vmware_host fixture to use Broker contextmanager Signed-off-by: Gaurav Talreja --------- Signed-off-by: Gaurav Talreja --- pytest_fixtures/component/provision_pxe.py | 1 + pytest_fixtures/component/provision_vmware.py | 31 +++-- .../api/test_computeresource_vmware.py | 7 +- tests/foreman/api/test_provisioning.py | 108 ++++++++++++++++++ 4 files changed, 132 insertions(+), 15 deletions(-) diff --git a/pytest_fixtures/component/provision_pxe.py b/pytest_fixtures/component/provision_pxe.py index 8cef98f3dec..6ab04d036e1 100644 --- a/pytest_fixtures/component/provision_pxe.py +++ b/pytest_fixtures/component/provision_pxe.py @@ -287,6 +287,7 @@ def pxe_loader(request): 'uefi': {'vm_firmware': 'uefi', 'pxe_loader': 'Grub2 UEFI'}, 'ipxe': {'vm_firmware': 'bios', 'pxe_loader': 'iPXE Embedded'}, 'http_uefi': {'vm_firmware': 'uefi', 'pxe_loader': 'Grub2 UEFI HTTP'}, + 'secureboot': {'vm_firmware': 'uefi_secureboot', 'pxe_loader': 'Grub2 UEFI SecureBoot'}, } return Box(PXE_LOADER_MAP[getattr(request, 'param', 'bios')]) diff --git a/pytest_fixtures/component/provision_vmware.py b/pytest_fixtures/component/provision_vmware.py index 83bea95c77f..4ba5b4cf27e 100644 --- a/pytest_fixtures/component/provision_vmware.py +++ b/pytest_fixtures/component/provision_vmware.py @@ -5,6 +5,7 @@ from wrapanapi.systems.virtualcenter import VMWareVirtualMachine from robottelo.config import settings +from robottelo.hosts import ContentHost @pytest.fixture(scope='module') @@ -112,18 +113,24 @@ def module_vmware_image( @pytest.fixture -def provisioning_vmware_host(pxe_loader, vmwareclient): +def provisioning_vmware_host(pxe_loader, vmwareclient, module_ssh_key_file): """Fixture to check out blank VM on VMware""" - vm_boot_firmware = 'efi' if pxe_loader.vm_firmware == 'uefi' else 'bios' - provisioning_host = Broker( + vm_boot_firmware = 'efi' if pxe_loader.vm_firmware.startswith('uefi') else 'bios' + vm_secure_boot = 'true' if pxe_loader.vm_firmware == 'uefi_secureboot' else 'false' + vlan_id = settings.provisioning.vlan_id + with Broker( workflow='deploy-blank-vm-vcenter', - artifacts='last', - vm_network=settings.provisioning.vlan_id, + host_class=ContentHost, + vm_network=vlan_id, vm_boot_firmware=vm_boot_firmware, - ).execute() - yield provisioning_host - # delete the host - vmware_host = VMWareVirtualMachine(vmwareclient, name=provisioning_host['name']) - vmware_host.delete() - # check if vm is deleted from VMware - assert vmwareclient.does_vm_exist(provisioning_host['name']) is False + vm_secure_boot=vm_secure_boot, + auth=module_ssh_key_file, + blank=True, + _skip_context_checkin=True, + ) as provisioning_host: + yield provisioning_host + # Delete the host + vmware_host = VMWareVirtualMachine(vmwareclient, name=provisioning_host.name) + vmware_host.delete() + # Verify host is deleted from VMware + assert vmwareclient.does_vm_exist(provisioning_host.name) is False diff --git a/tests/foreman/api/test_computeresource_vmware.py b/tests/foreman/api/test_computeresource_vmware.py index f1dbeb4b543..ecce37cc883 100644 --- a/tests/foreman/api/test_computeresource_vmware.py +++ b/tests/foreman/api/test_computeresource_vmware.py @@ -154,12 +154,13 @@ def test_positive_provision_vmware_pxe_discovery( 2. Provision the host :expectedresults: Host should be provisioned successfully - """ - mac = provisioning_vmware_host['provisioning_nic_mac_addr'] + mac = provisioning_vmware_host._broker_args['provisioning_nic_mac_addr'] sat = module_discovery_sat.sat # start the provisioning host - vmware_host = VMWareVirtualMachine(vmwareclient, name=provisioning_vmware_host['name']) + vmware_host = VMWareVirtualMachine( + vmwareclient, name=provisioning_vmware_host._broker_args['name'] + ) vmware_host.start() wait_for( lambda: sat.api.DiscoveredHost().search(query={'mac': mac}) != [], diff --git a/tests/foreman/api/test_provisioning.py b/tests/foreman/api/test_provisioning.py index f03a4b51f50..84d4b87aa1c 100644 --- a/tests/foreman/api/test_provisioning.py +++ b/tests/foreman/api/test_provisioning.py @@ -17,8 +17,10 @@ from fauxfactory import gen_string import pytest from wait_for import TimedOutError, wait_for +from wrapanapi.systems.virtualcenter import VMWareVirtualMachine from robottelo.config import settings +from robottelo.hosts import get_sat_rhel_version from robottelo.logging import logger from robottelo.utils.installer import InstallerCommand from robottelo.utils.issue_handlers import is_open @@ -592,6 +594,112 @@ def test_rhel_pxe_provisioning_fips_enabled( assert provisioning_host.subscribed, 'Host is not subscribed' +@pytest.mark.e2e +@pytest.mark.upgrade +@pytest.mark.on_premises_provisioning +@pytest.mark.parametrize('pxe_loader', ['secureboot'], indirect=True) +@pytest.mark.rhel_ver_match([get_sat_rhel_version().major]) +def test_rhel_pxe_provisioning_secureboot_enabled( + request, + module_provisioning_sat, + vmwareclient, + provisioning_vmware_host, + pxe_loader, + module_sca_manifest_org, + module_location, + module_provisioning_rhel_content, + provisioning_hostgroup, +): + """Simulate Secureboot baremetal provisioning of a RHEL system via PXE on vCenter provider + + :id: 8b33f545-c4a8-428d-8fd8-a5e402c8cd23 + + :steps: + 1. Provision RHEL system via PXE on vCenter provider + 2. Check that resulting host is registered to Satellite + 3. Check host is subscribed to Satellite + + :expectedresults: + 1. Host installs right version of RHEL + 2. Host is registered to Satellite and subscription status is 'Success' + 3. Secureboot is enabled on the host + + :Verifies: SAT-25809 + + :customerscenario: true + + :parametrized: yes + """ + host_mac_addr = provisioning_vmware_host._broker_args['provisioning_nic_mac_addr'] + sat = module_provisioning_sat.sat + host = sat.api.Host( + hostgroup=provisioning_hostgroup, + organization=module_sca_manifest_org, + location=module_location, + name=gen_string('alpha').lower(), + mac=host_mac_addr, + build=True, # put the host in build mode + ).create(create_missing=False) + # Clean up the host to free IP leases on Satellite. + # broker should do that as a part of the teardown, putting here just to make sure. + request.addfinalizer(lambda: sat.provisioning_cleanup(host.name)) + + # start the provisioning host on VMware, do not ensure that we can connect to SSHD + vmware_host = VMWareVirtualMachine( + vmwareclient, name=provisioning_vmware_host._broker_args['name'] + ) + vmware_host.start() + + # TODO: Implement Satellite log capturing logic to verify that + # all the events are captured in the logs. + # Host should do call back to the Satellite reporting + # the result of the installation. Wait until Satellite reports that the host is installed. + wait_for( + lambda: host.read().build_status_label != 'Pending installation', + timeout=1500, + delay=10, + ) + host = host.read() + assert host.build_status_label == 'Installed' + + # Change the hostname of the host as we know it already. + # In the current infra environment we do not support + # addressing hosts using FQDNs, falling back to IP. + provisioning_vmware_host.hostname = host.ip + # Host is not blank anymore + provisioning_vmware_host.blank = False + + # Wait for the host to be rebooted and SSH daemon to be started. + provisioning_vmware_host.wait_for_connection() + + # Perform version check and check if root password is properly updated + host_os = host.operatingsystem.read() + expected_rhel_version = f'{host_os.major}.{host_os.minor}' + + if int(host_os.major) >= 9: + assert ( + provisioning_vmware_host.execute( + 'echo -e "\nPermitRootLogin yes" >> /etc/ssh/sshd_config; systemctl restart sshd' + ).status + == 0 + ) + host_ssh_os = sat.execute( + f'sshpass -p {settings.provisioning.host_root_password} ' + 'ssh -o StrictHostKeyChecking=no -o PubkeyAuthentication=no -o PasswordAuthentication=yes ' + f'-o UserKnownHostsFile=/dev/null root@{provisioning_vmware_host.hostname} cat /etc/redhat-release' + ) + assert host_ssh_os.status == 0 + assert ( + expected_rhel_version in host_ssh_os.stdout + ), 'Different than the expected OS version was installed' + + # Verify host is subscribed and consumes subsctiption provided by the activation key + assert provisioning_vmware_host.subscribed, 'Host is not subscribed' + + # Verify SecureBoot is enabled on host after provisioning is completed sucessfully + assert 'SecureBoot enabled' in provisioning_vmware_host.execute('mokutil --sb-state').stdout + + @pytest.mark.e2e @pytest.mark.parametrize('pxe_loader', ['bios', 'uefi'], indirect=True) @pytest.mark.skip(reason='Skipping till we have destructive support')