diff --git a/meta-webos/classes/webos_ls2_conf_validate.bbclass b/meta-webos/classes/webos_ls2_conf_validate.bbclass index faa9f56e5..461429807 100644 --- a/meta-webos/classes/webos_ls2_conf_validate.bbclass +++ b/meta-webos/classes/webos_ls2_conf_validate.bbclass @@ -5,6 +5,11 @@ inherit webos_filesystem_paths +WEBOS_LS2_CONF_VALIDATE_ERROR_ON_WARNING ?= "0" +WEBOS_LS2_CONF_VALIDATE_SKIP_GROUP ?= " \ + allowedNames \ +" + # For some reason, using expr directly doesn't work accumulate() { echo $(expr $1 + $2) @@ -125,5 +130,111 @@ fakeroot do_validate_ls2_security_conf() { fi } +fakeroot python do_validate_ls2_acg() { + import os + import json + + # List of group names to skip checking + skip_group = d.getVar("WEBOS_LS2_CONF_VALIDATE_SKIP_GROUP").split() + if len(skip_group) > 0: + bb.debug(1, "WEBOS_LS2_CONF_VALIDATE_SKIP_GROUP:") + for group in skip_group: + bb.debug(1, " %s" % group) + + rootfs_groups_d = d.getVar("IMAGE_ROOTFS") + d.getVar("webos_sysbus_groupsdir") + rootfs_api_perms_d = d.getVar("IMAGE_ROOTFS") + d.getVar("webos_sysbus_apipermissionsdir") + rootfs_clientperms_dir = d.getVar("IMAGE_ROOTFS") + d.getVar("webos_sysbus_permissionsdir") + + # Returns a set of group names defined in 'dir'. + # Json files in 'dir' are expected to have groups as keys. + def read_groups(dir): + bb.debug(1, "Reading groups from %s" % dir) + groups = set() + with os.scandir(dir) as it: + for entry in it: + if entry.is_file(): + bb.debug(1, " %s" % entry.name) + with open(entry.path) as fp: + groups_json = json.load(fp) + groups.update(filter(lambda x: x not in skip_group, groups_json.keys())) + bb.debug(1, "Done reading groups from %s" % dir) + return groups + + # Returns a set of group names used in 'perm_entry' but not in 'groups'. + # 'groups' is a set of group names to match and 'perm_entry' is an + # iterator entry of a file that refers groups in an array form. + def get_missing_groups_in_perm(groups, perm_entry): + bb.debug(1, "Checking groups in %s" % perm_entry.name) + missing_groups = set() + with open(perm_entry.path) as fp: + perm_json = json.load(fp) + for groups_used in perm_json.values(): + for group in groups_used: + if not group in groups: + missing_groups.add(group) + for group in sorted(missing_groups): + bb.debug(1, " %s%s" % (group, " => missing" if not group in groups else "")) + bb.debug(1, "Done checking groups in %s" % perm_entry.name) + return missing_groups + + # First, we build a set of groups defined in "groups.d". + groups_defined = read_groups(rootfs_groups_d) + bb.debug(2, "=== LIST BEGIN: Groups defined in groups.d(%s) ===" % rootfs_groups_d) + for group in sorted(groups_defined): + bb.debug(2, " %s" % group) + bb.debug(2, "=== LIST END ===") + + # Second, get groups from "api-permissions.d". + # Those groups are also considered as valid. + groups_defined2 = read_groups(rootfs_api_perms_d) + bb.debug(2, "=== LIST BEGIN: Groups used in api-permissions.d(%s) ===" % rootfs_api_perms_d) + for group in sorted(groups_defined2): + bb.debug(2, " %s" % group) + bb.debug(2, "=== LIST END ===") + + # Merge groups from "groups.d" and "api-permissions.d" with showing differences. + # Those differences are recommended to define in "groups.d". + groups_defined2.difference_update(groups_defined) + cnt = len(groups_defined2) + if cnt > 0: + bb.warn("Found %d group(s) that appear only in api-permissions.d, consider define them in groups.d" % cnt) + bb.warn("=== LIST BEGIN: Groups used in api-permissions.d but not defined in groups.d ===") + for group in sorted(groups_defined2): + bb.warn(" %s" % group) + bb.warn("=== LIST END ===") + groups_valid = groups_defined.union(groups_defined2) + bb.note("=== LIST BEGIN: Groups considered as valid ===") + for group in sorted(groups_valid): + bb.note(" %s" % group) + bb.note("=== LIST END ===") + + # Iterate files in "client-permissions.d" and list up groups + # which don't appear in the set built above. + groups_missing = {} + with os.scandir(rootfs_clientperms_dir) as it: + for entry in it: + if entry.is_file(): + for group in get_missing_groups_in_perm(groups_valid, entry): + if group not in skip_group: + if group in groups_missing: + groups_missing[group] += [entry.name] + else: + groups_missing[group] = [entry.name] + + # Raise a warning or error(if enabled) if any missing group is found. + cnt = len(groups_missing) + if cnt > 0: + bb.warn("Found %d group(s) used in client-permissions.d but not defined" % cnt) + bb.warn("=== LIST BEGIN ===") + for group in sorted(groups_missing): + bb.warn("'%s' being used in:" % group) + for entry in sorted(groups_missing[group]): + bb.warn(" %s" % entry) + bb.warn("=== LIST END =====") + if d.getVar("WEBOS_LS2_CONF_VALIDATE_ERROR_ON_WARNING") != "0": + bb.fatal("Fatal error while checking groups, aborting!") +} + addtask do_validate_ls2_security_conf after do_rootfs before do_image +addtask do_validate_ls2_acg after do_validate_ls2_security_conf before do_image do_validate_ls2_security_conf[depends] += "libpbnjson-native:do_populate_sysroot"