构建采用 组件自申明、集成时赋权 策略管理组件生成的文件,该策略要求组件生成的文件都由一个permissions.ini文件申明需要的权限,由构建系统在组件集成环节解析permissions.ini文件完成文件赋权。
为什么要使用组件自申明、集成时赋权策略
一个产品往往包含开源、平台、芯片、自研软件等各种软件,实践表明产品权限管理存在漏赋权、重复赋权、管理困难等,为此产生了“赋权不一定要准确,可以忽略错误”的做法,最终导致很多漏到后端测试。
Openubmc所有权限由组件自主申明,赋权文件会强制检查所有赋权操作是否正确执行,按错误即失败原则处理,实现左移。
WARNING
openubmc要求赋权100%准确,会检测每一条命令执行结果,如遇失败即报错退出。 有授权记录但无被授权文件的会报构建失败;对有文件但无授权记录的由测试团队的脚本检查并提单。
如何操作
组件的制品权限管理包含四种方式:
- 静态配置权限:构建任意场景都会生成的文件由代码仓打包的permissions.ini文件描述。
- 动态配置权限:构建时按特性选项生成的文件由conanfile.py动态生成permissions.ini文件。
- 组件定制化配置权限:组件构建时不生成,产品集成时由组件定制化脚本生成的文件由定制化脚本赋权。
- 产品定制化配置权限:产品对通用权限有不同要求的由产品定制化脚本赋权。
静态配置权限
组件源码目录存储一个静态permissions.ini文件,每一行记录一个文件/文件夹权限,格式要求为name type mode uid gid,支持对指定文件、指定目录、递归指定目录下的文件、递归指定目录下的目录赋权,下面是iam模块的示例。
# syntax documentation
# format: name type mode uid gid
# name is the path to the file you want to create/modify
# type is the type of the file, being one of:
# f: a regular file
# d: a directory
# r: a directory recursively
# rd: a directory recursively, only subdirectory effectivity
# mode are the usual permissions settings (only numerical values are allowed)
# name is the path to the file you want to create/modify
opt/bmc/apps/iam rd 550 0 0
opt/bmc/apps/iam r 440 0 0
etc/systemd/system/iam.service f 640 0 0
etc/rc.d/rc.start/init_user.sh f 550 0 0
etc/weakdictionary f 640 0 0TIP
组件构建时打包源码目录下的permissions.ini文件至打包目录。
动态配置权限
静态配置的permissions.ini文件只适配于必然会生成和打包的文件,实际应用中可能因为特性开关状态产生不同的文件,此时就需要动态生成permissions.ini文件。 conan的特性控制是由options完成,一个典型的应用示例是在组件的conanfile.py的build方法中判断是否使能或关闭某个特性并将动态赋权内容追加到permissions.ini文件。
以下示例演示了gcov选项未使能时向permissions.ini文件追加了opt/bmc/apps/example/yy f 550 0 0赋权内容。
class IamConan(ConanBase):
def build(self):
super().build()
if not self.options.gcov:
with open("permissions.ini", "a+") as fp:
fp.write("\nopt/bmc/apps/example/yy f 550 0 0")TIP
示例仅演进功能,赋权内容要跟构建制品逻辑100%匹配,请以实际特性状态和文件生成逻辑为准。
组件定制化配置
某些场景组件对其它组件/平台提供的文件有权限述求的,如果这种述求与组件存在100%关联,即组件存在,该文件必须存在且权限满足要求的,可以使用组件定制化配置权限。
该方式依赖组件定制化功能,该功能为组件提供了在特定阶段注入一段python代码的能力,其基础原理是由组件管理一个build/customization.py文件,构建时打包到include目录,产品构建时会搜索该文件并执行。
当前支持组件在三个阶段进行定制化, 按照执行阶段顺序分为post_image -> post_rootfs -> post_hpm,组件按需配置各个阶段的定制化。
post_image- 所有组件合并为组件镜像后执行,其中定制化脚本类rootfs_path参数为组件镜像目录。使用场景:对组件镜像的文件进行软链接、权限设置或其他定制化操作。post_rootfs- 组件镜像和rtos、sdk合并为rootfs镜像后执行,其中定制化脚本类rootfs_path参数为rootfs镜像目录。使用场景:对非组件的文件(rtos自带文件)进行定制化操作(软链接、权限设置、删除、更改内容等)。post_hpm- 制作hpm前执行,其中定制化脚本类rootfs_path参数为hpm包制作目录。一般组件不涉及,属于特殊场景。
以下示例用于演示了一种场景:某一组件要求/etc/passwd文件权限必须为600,该文件实际由rtos带入,为确保权限正确性,需要组件在post_rootfs(rootfs制作完成后)执行一段定制化脚本完成赋权。
import sub——process
# 定制化脚本,由manifest构建时调用
class Customization(object):
def __init__(self, board_name, rootfs_path):
self.board_name = board_name
self.rootfs_path = rootfs_path
def post_rootfs(self):
sub——process.run(['/usr/bin/sudo', '/usr/bin/ch——mod', '600', '/etc/passwd'], check=True)[!attention]
- 定制化配置请一定集成到版本构建中验证完成再上库。
- 在
build/customization.py脚本中不要import bmcgo相关代码,避免引起依赖。
产品定制化配置
如果组件提供的默认权限不符合极个别产品定制化要求,可以由产品定制化脚本自主完成权限控制。
该方式依赖产品manifest.yml文件记录的customization定制化脚本,该脚本会在多个阶段执行,一般权限定制放在rootfs_cust阶段即可,以下示例为产品定制化脚本动态创建data/opt/bmc/web/custom目录并赋权的示例:
class Customization(BaseCustomization):
def rootfs_cust(self, rootfs_path):
self.work.run_command("mkdir -p data/opt/bmc/web/custom", sudo=True)
self.work.run_command("sudo chmod 750 data/opt/bmc/web/custom", sudo=True)[!attention] 定制化配置请一定验证存在性及权限正确后再上库
定制化验证步骤:
- 初步验证:构建
hpm包完成后,在temp目录下,使用find命令去查找生成的文件或者修改权限的文件,如下
[11:28:08 root(1110):/home/workspace/codehome/manifest]# find . -name custom | grep extern
./temp/build_Openubmc_debug_dev/tmp_root/opt/bmc/web/htdocs/extern/custom
./temp/build_Openubmc_debug_dev/buildimg/rtos_with_driver/rootfs/opt/bmc/web/htdocs/extern/custom
[11:28:12 root(1110):/home/workspace/codehome/manifest]# find . -name custom | grep extern | xargs ls -la
lrwxrwxrwx 1 root root 24 4月 1 10:47 ./temp/build_Openubmc_debug_dev/buildimg/rtos_with_driver/rootfs/opt/bmc/web/htdocs/extern/custom -> /data/opt/bmc/web/custom
lrwxrwxrwx 1 root root 24 4月 1 10:47 ./temp/build_Openubmc_debug_dev/tmp_root/opt/bmc/web/htdocs/extern/custom -> /data/opt/bmc/web/custom
[11:47:52 root(1110):/home/workspace/codehome/manifest]#- 环境验证(开发者自行验证,不做示例):再初步验证成功后,将
hpm包升级到环境中,检查对应路径下的文件是否存在或符合预期权限要求 - 版本验证(开发者自行验证,不做示例):需求完成后,上库并出版本以后,将版本包升级到环境,再次检查对应路径下文件是否存在或者符合预期权限要求