# # Copyright (C) 2018 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # from io import StringIO import shutil import tempfile import unittest from pylorax import get_buildarch from pylorax.api.compose import add_customizations, get_extra_pkgs from pylorax.api.config import configure, make_dnf_dirs from pylorax.api.dnfbase import get_base_object from pylorax.api.recipes import recipe_from_toml BASE_RECIPE = """name = "test-cases" description = "Used for testing" version = "0.0.1" """ HOSTNAME = BASE_RECIPE + """[customizations] hostname = "testhostname" """ SSHKEY = BASE_RECIPE + """[[customizations.sshkey]] user = "root" key = "ROOT SSH KEY" """ USER = BASE_RECIPE + """[[customizations.user]] name = "tester" """ ROOT_USER = BASE_RECIPE + """[[customizations.user]] name = "root" """ USER_KEY = """ key = "A SSH KEY FOR THE USER" """ USER_DESC = """ description = "a test user account" """ USER_CRYPT = """ password = "$6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1" """ USER_PLAIN = """ password = "plainpassword" """ USER_HOME = """ home = "/opt/users/tester/" """ USER_SHELL = """ shell = "/usr/bin/zsh" """ USER_UID = """ uid = 1013 """ USER_GID = """ gid = 4242 """ USER_GROUPS = """ groups = ["wheel", "users"] """ USER_ALL = USER + USER_KEY + USER_DESC + USER_CRYPT + USER_HOME + USER_SHELL + USER_UID + USER_GID GROUP = BASE_RECIPE + """[[customizations.group]] name = "testgroup" """ GROUP_GID = GROUP + """ gid = 1011 """ USER_GROUP = USER + """[[customizations.group]] name = "tester" """ KS_USER_ALL = '''sshkey --user tester "A SSH KEY FOR THE USER" user --name tester --homedir /opt/users/tester/ --iscrypted --password "$6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1" --shell /usr/bin/zsh --uid 1013 --gid 4242 --gecos "a test user account" rootpw --lock ''' # ROOT TESTS ROOT_CRYPT = ROOT_USER + USER_CRYPT ROOT_PLAIN = ROOT_USER + USER_PLAIN ROOT_CRYPT_KEY = ROOT_USER + USER_CRYPT + USER_KEY ROOT_PLAIN_KEY = ROOT_USER + USER_PLAIN + USER_KEY ROOT_KEY = ROOT_USER + USER_KEY class CustomizationsTestCase(unittest.TestCase): def assertCustomization(self, test, result): r = recipe_from_toml(test) f = StringIO() add_customizations(f, r) self.assertTrue(result in f.getvalue(), f.getvalue()) def assertNotCustomization(self, test, result): r = recipe_from_toml(test) f = StringIO() add_customizations(f, r) self.assertTrue(result not in f.getvalue(), f.getvalue()) def test_no_customizations(self): """Test not setting any customizations""" self.assertCustomization(BASE_RECIPE, "rootpw --lock") def test_set_hostname(self): """Test setting the hostname""" self.assertCustomization(HOSTNAME, "network --hostname=testhostname") self.assertCustomization(HOSTNAME, "rootpw --lock") def test_set_sshkey(self): """Test setting sshkey without user""" self.assertCustomization(SSHKEY, 'sshkey --user root "ROOT SSH KEY"') def test_sshkey_only(self): """Test adding a sshkey to an existing user account""" self.assertCustomization(USER + USER_KEY, 'sshkey --user tester "A SSH KEY FOR THE USER"') self.assertCustomization(USER + USER_KEY, "rootpw --lock") def test_create_user(self): """Test creating a user with no options""" self.assertCustomization(USER, "user --name tester") self.assertCustomization(USER, "rootpw --lock") def test_create_user_desc(self): """Test creating a user with a description""" self.assertCustomization(USER + USER_DESC, '--gecos "a test user account"') self.assertCustomization(USER + USER_DESC, "rootpw --lock") def test_create_user_crypt(self): """Test creating a user with a pre-crypted password""" self.assertCustomization(USER + USER_CRYPT, '--password "$6$CHO2$3r') self.assertCustomization(USER + USER_CRYPT, "rootpw --lock") def test_create_user_plain(self): """Test creating a user with a plaintext password""" self.assertCustomization(USER + USER_PLAIN, '--password "plainpassword"') self.assertCustomization(USER + USER_PLAIN, "rootpw --lock") def test_create_user_home(self): """Test creating user with a home directory""" self.assertCustomization(USER + USER_HOME, "--homedir /opt/users/tester/") self.assertCustomization(USER + USER_HOME, "rootpw --lock") def test_create_user_shell(self): """Test creating user with shell set""" self.assertCustomization(USER + USER_SHELL, "--shell /usr/bin/zsh") self.assertCustomization(USER + USER_SHELL, "rootpw --lock") def test_create_user_uid(self): """Test creating user with uid set""" self.assertCustomization(USER + USER_UID, "--uid 1013") self.assertCustomization(USER + USER_UID, "rootpw --lock") def test_create_user_gid(self): """Test creating user with gid set""" self.assertCustomization(USER + USER_GID, "--gid 4242") self.assertCustomization(USER + USER_GID, "rootpw --lock") def test_create_user_groups(self): """Test creating user with group membership""" self.assertCustomization(USER + USER_GROUPS, "--groups wheel,users") self.assertCustomization(USER + USER_GROUPS, "rootpw --lock") def test_user_same_group(self): """Test creating a group with the same name as a user""" # Creating a group with the same name should skip the group creation self.assertCustomization(USER_GROUP, "user --name tester") self.assertNotCustomization(USER_GROUP, "group --name tester") self.assertCustomization(USER_GROUP, "rootpw --lock") def test_create_user_all(self): """Test creating user with all settings""" r = recipe_from_toml(USER_ALL) f = StringIO() add_customizations(f, r) self.assertEqual(KS_USER_ALL, f.getvalue()) def test_create_group(self): """Test creating group without gid set""" self.assertCustomization(GROUP, "group --name testgroup") self.assertCustomization(GROUP, "rootpw --lock") def test_create_group_gid(self): """Test creating group with gid set""" self.assertCustomization(GROUP_GID, "group --name testgroup --gid 1011") self.assertCustomization(GROUP_GID, "rootpw --lock") def test_root_crypt(self): self.assertCustomization(ROOT_CRYPT, 'rootpw --iscrypted "$6$CHO2$3r') self.assertNotCustomization(ROOT_CRYPT, "rootpw --lock") def test_root_plain(self): self.assertCustomization(ROOT_PLAIN, 'rootpw --plaintext "plainpassword"') self.assertNotCustomization(ROOT_PLAIN, "rootpw --lock") def test_root_crypt_key(self): self.assertCustomization(ROOT_CRYPT_KEY, 'rootpw --iscrypted "$6$CHO2$3r') self.assertCustomization(ROOT_CRYPT_KEY, 'sshkey --user root "A SSH KEY FOR THE USER"') self.assertNotCustomization(ROOT_CRYPT_KEY, "rootpw --lock") def test_root_plain_key(self): self.assertCustomization(ROOT_PLAIN_KEY, 'rootpw --plaintext "plainpassword"') self.assertCustomization(ROOT_PLAIN_KEY, 'sshkey --user root "A SSH KEY FOR THE USER"') self.assertNotCustomization(ROOT_PLAIN_KEY, "rootpw --lock") class ExtraPkgsTest(unittest.TestCase): @classmethod def setUpClass(self): self.tmp_dir = tempfile.mkdtemp(prefix="lorax.test.repo.") self.config = configure(root_dir=self.tmp_dir, test_config=True) make_dnf_dirs(self.config) self.dbo = get_base_object(self.config) @classmethod def tearDownClass(self): shutil.rmtree(self.tmp_dir) def test_live_install(self): """Check that live-install.tmpl is parsed correctly""" # A package for each arch to test for arch_pkg = { "aarch64": "shim-aa64", "arm": "grub2-efi-arm-cdboot", "armhfp": "grub2-efi-arm-cdboot", "x86_64": "shim-x64", "i386": "memtest86+", "ppc64le": "powerpc-utils", "s390x": "s390utils-base" } extra_pkgs = get_extra_pkgs(self.dbo, "./share/", "live-iso") self.assertTrue(len(extra_pkgs) > 0) # Results depend on arch arch = get_buildarch(self.dbo) self.assertTrue(arch_pkg[arch] in extra_pkgs) def test_other_install(self): """Test that non-live doesn't parse live-install.tmpl""" extra_pkgs = get_extra_pkgs(self.dbo, "./share/", "qcow2") self.assertEqual(extra_pkgs, [])