| Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 1 | # SPDX-FileCopyrightText: Huawei Inc. | 
|  | 2 | # | 
|  | 3 | # SPDX-License-Identifier: MIT | 
|  | 4 |  | 
|  | 5 | import os | 
|  | 6 | import oe | 
|  | 7 | import unittest | 
|  | 8 | from oeqa.selftest.case import OESelftestTestCase | 
|  | 9 | from oeqa.utils.commands import bitbake, get_bb_vars | 
|  | 10 |  | 
|  | 11 | class ShadowUtilsTidyFiles(OESelftestTestCase): | 
|  | 12 | """ | 
|  | 13 | Check if shadow image rootfs files are tidy. | 
|  | 14 |  | 
|  | 15 | The tests are focused on testing the functionality provided by the | 
|  | 16 | 'tidy_shadowutils_files' rootfs postprocess command (via | 
|  | 17 | SORT_PASSWD_POSTPROCESS_COMMAND). | 
|  | 18 | """ | 
|  | 19 |  | 
|  | 20 | def sysconf_build(self): | 
|  | 21 | """ | 
|  | 22 | Verify if shadow tidy files tests are to be run and if yes, build a | 
|  | 23 | test image and return its sysconf rootfs path. | 
|  | 24 | """ | 
|  | 25 |  | 
|  | 26 | test_image = "core-image-minimal" | 
|  | 27 |  | 
|  | 28 | config = 'IMAGE_CLASSES += "extrausers"\n' | 
|  | 29 | config += 'EXTRA_USERS_PARAMS = "groupadd -g 1000 oeqatester; "\n' | 
|  | 30 | config += 'EXTRA_USERS_PARAMS += "useradd -p \'\' -u 1000 -N -g 1000 oeqatester; "\n' | 
|  | 31 | self.write_config(config) | 
|  | 32 |  | 
|  | 33 | vars = get_bb_vars(("IMAGE_ROOTFS", "SORT_PASSWD_POSTPROCESS_COMMAND", "sysconfdir"), | 
|  | 34 | test_image) | 
|  | 35 | passwd_postprocess_cmd = vars["SORT_PASSWD_POSTPROCESS_COMMAND"] | 
|  | 36 | self.assertIsNotNone(passwd_postprocess_cmd) | 
|  | 37 | if (passwd_postprocess_cmd.strip() != 'tidy_shadowutils_files;'): | 
|  | 38 | raise unittest.SkipTest("Testcase skipped as 'tidy_shadowutils_files' " | 
|  | 39 | "rootfs post process command is not the set SORT_PASSWD_POSTPROCESS_COMMAND.") | 
|  | 40 |  | 
|  | 41 | rootfs = vars["IMAGE_ROOTFS"] | 
|  | 42 | self.assertIsNotNone(rootfs) | 
|  | 43 | sysconfdir = vars["sysconfdir"] | 
|  | 44 | bitbake(test_image) | 
|  | 45 | self.assertIsNotNone(sysconfdir) | 
|  | 46 |  | 
|  | 47 | return oe.path.join(rootfs, sysconfdir) | 
|  | 48 |  | 
|  | 49 | def test_shadowutils_backup_files(self): | 
|  | 50 | """ | 
|  | 51 | Test that the rootfs doesn't include any known shadow backup files. | 
|  | 52 | """ | 
|  | 53 |  | 
|  | 54 | backup_files = ( | 
|  | 55 | 'group-', | 
|  | 56 | 'gshadow-', | 
|  | 57 | 'passwd-', | 
|  | 58 | 'shadow-', | 
|  | 59 | 'subgid-', | 
|  | 60 | 'subuid-', | 
|  | 61 | ) | 
|  | 62 |  | 
|  | 63 | rootfs_sysconfdir = self.sysconf_build() | 
|  | 64 | found = [] | 
|  | 65 | for backup_file in backup_files: | 
|  | 66 | backup_filepath = oe.path.join(rootfs_sysconfdir, backup_file) | 
|  | 67 | if os.path.exists(backup_filepath): | 
|  | 68 | found.append(backup_file) | 
|  | 69 | if (found): | 
|  | 70 | raise Exception('The following shadow backup files were found in ' | 
|  | 71 | 'the rootfs: %s' % found) | 
|  | 72 |  | 
|  | 73 | def test_shadowutils_sorted_files(self): | 
|  | 74 | """ | 
|  | 75 | Test that the 'passwd' and the 'group' shadow utils files are ordered | 
|  | 76 | by ID. | 
|  | 77 | """ | 
|  | 78 |  | 
|  | 79 | files = ( | 
|  | 80 | 'passwd', | 
|  | 81 | 'group', | 
|  | 82 | ) | 
|  | 83 |  | 
|  | 84 | rootfs_sysconfdir = self.sysconf_build() | 
|  | 85 | unsorted = [] | 
|  | 86 | for file in files: | 
|  | 87 | filepath = oe.path.join(rootfs_sysconfdir, file) | 
|  | 88 | with open(filepath, 'rb') as f: | 
|  | 89 | ids = [] | 
|  | 90 | lines = f.readlines() | 
|  | 91 | for line in lines: | 
|  | 92 | entries = line.split(b':') | 
|  | 93 | ids.append(int(entries[2])) | 
|  | 94 | if (ids != sorted(ids)): | 
|  | 95 | unsorted.append(file) | 
|  | 96 | if (unsorted): | 
|  | 97 | raise Exception("The following files were not sorted by ID as expected: %s" % unsorted) |