Skip to content

Commit

Permalink
webos_ls2_conf_validate.bbclass: Check ACG groups used but not defined
Browse files Browse the repository at this point in the history
:Release Notes:
Add a new task do_validate_ls2_acg that checks ACG groups used in files
under client-permissions.d but defined neither in groups.d nor
api-permissions.d.

:Detailed Notes:
The idea is that all valid ACG group names are defined either in
groups.d or api-permissions.d. Anything not listed there is invalid and
supposed to be denied by the bus. The default action on such case is to
show warnings but it can be treated as a fatal error by setting
WEBOS_LS2_CONF_VALIDATE_ERROR_ON_WARNING later.
WEBOS_LS2_CONF_VALIDATE_SKIP_GROUP would be useful if you want to add
some exceptions on checking valid group names.

:Testing Performed:
bitbake <image> -c do_validate_ls2_acg

:QA Notes:

:Issues Addressed:
[WRQ-2124] CCC: Add a new task do_validate_ls2_acg that checks ACG
           groups from image built
[WRQ-1154] Check ACG groups used but not defined at buildtime

Cherry-picked-from-commit: 81df500
Cherry-picked-from-branch:
  • Loading branch information
jaeyoonjung authored and ywbyun0815 committed Nov 10, 2023
1 parent debc919 commit 8ff37b5
Showing 1 changed file with 111 additions and 0 deletions.
111 changes: 111 additions & 0 deletions meta-webos/classes/webos_ls2_conf_validate.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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"

0 comments on commit 8ff37b5

Please sign in to comment.