写点什么

如何在 OpenShift 中运行 Collabora Office

用户头像
东风微鸣
关注
发布于: 2021 年 01 月 07 日
如何在 OpenShift 中运行 Collabora Office

前言

近期在尝试 office 文档在线编辑和预览的一些解决方案, 目前在使用 Collabora Office, 但是 Collabora 的 docker 镜像在 OpenShift 中运行不起来, 一直提示Operation not permitted.


Collabora Office 简介

Collabora Office 提供强大的 Office 套件, 使您能够访问文档、编写新内容并协同工作。

  • 可以在自己的服务器上安装套件

  • 可以和其他应用(如:nextcloud owncloud 等)或你自己的应用进行整合

  • i18n 级别的兼容性

  • 协同编辑

  • 可以完美融入进自己的解决方案

分析 - 需要哪些特权


Collabora 的 docker 镜像在 OpenShift 中运行不起来, 一直提示Operation not permitted. 其实原因权限不允许, 它需要做的一些操作在 OpenShift 中是被禁止的(出于企业级安全的考虑). 所以我们将它需要的权限一项一项加上就好了.


要搞清楚它需要哪些权限, 我们可以看一下它的Dockerfile及其相关内容:

FROM ubuntu:16.04
# Environment variablesENV domain localhostENV LC_CTYPE en_US.UTF-8
# Setup scripts for LibreOffice OnlineADD /scripts/install-libreoffice.sh /ADD /scripts/start-libreoffice.sh /RUN bash install-libreoffice.sh
EXPOSE 9980
# Entry pointCMD bash start-libreoffice.sh
复制代码


dockerfile中如上所示, 这个文件虽然简单, 但是我们可以得到 2 个信息:

  1. 没有USER 指令, 那么这个镜像可能是需要root权限才能运行的.

  2. 加入了 2 个脚本. 其中 start-libreoffice.sh是在容器启动的时候运行的, 所以主要来看一下这个脚本的内容:

#!/bin/sh
# Fix domain name resolution from jailscp /etc/resolv.conf /etc/hosts /opt/lool/systemplate/etc/
if test "${DONT_GEN_SSL_CERT-set}" == set; then# Generate new SSL certificate instead of using the defaultmkdir -p /opt/ssl/cd /opt/ssl/mkdir -p certs/caopenssl genrsa -out certs/ca/root.key.pem 2048openssl req -x509 -new -nodes -key certs/ca/root.key.pem -days 9131 -out certs/ca/root.crt.pem -subj "/C=DE/ST=BW/L=Stuttgart/O=Dummy Authority/CN=Dummy Authority"mkdir -p certs/{servers,tmp}mkdir -p "certs/servers/localhost"openssl genrsa -out "certs/servers/localhost/privkey.pem" 2048 -key "certs/servers/localhost/privkey.pem"if test "${cert_domain-set}" == set; thenopenssl req -key "certs/servers/localhost/privkey.pem" -new -sha256 -out "certs/tmp/localhost.csr.pem" -subj "/C=DE/ST=BW/L=Stuttgart/O=Dummy Authority/CN=localhost"elseopenssl req -key "certs/servers/localhost/privkey.pem" -new -sha256 -out "certs/tmp/localhost.csr.pem" -subj "/C=DE/ST=BW/L=Stuttgart/O=Dummy Authority/CN=${cert_domain}"fiopenssl x509 -req -in certs/tmp/localhost.csr.pem -CA certs/ca/root.crt.pem -CAkey certs/ca/root.key.pem -CAcreateserial -out certs/servers/localhost/cert.pem -days 9131mv certs/servers/localhost/privkey.pem /etc/loolwsd/key.pemmv certs/servers/localhost/cert.pem /etc/loolwsd/cert.pemmv certs/ca/root.crt.pem /etc/loolwsd/ca-chain.cert.pemfi
# Replace trusted host and set admin username and passwordperl -pi -e "s/localhost<\/host>/${domain}<\/host>/g" /etc/loolwsd/loolwsd.xmlperl -pi -e "s/<username (.*)>.*<\/username>/<username \1>${username}<\/username>/" /etc/loolwsd/loolwsd.xmlperl -pi -e "s/<password (.*)>.*<\/password>/<password \1>${password}<\/password>/" /etc/loolwsd/loolwsd.xmlperl -pi -e "s/<server_name (.*)>.*<\/server_name>/<server_name \1>${server_name}<\/server_name>/" /etc/loolwsd/loolwsd.xmlperl -pi -e "s/<allowed_languages (.*)>.*<\/allowed_languages>/<allowed_languages \1>${dictionaries:-de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru}<\/allowed_languages>/" /etc/loolwsd/loolwsd.xml
# Restart when /etc/loolwsd/loolwsd.xml changes[ -x /usr/bin/inotifywait -a /usr/bin/killall ] && (/usr/bin/inotifywait -e modify /etc/loolwsd/loolwsd.xmlecho "$(ls -l /etc/loolwsd/loolwsd.xml) modified --> restarting"/usr/bin/killall -1 loolwsd) &
# Start loolwsdsu -c "/usr/bin/loolwsd --version --o:sys_template_path=/opt/lool/systemplate --o:lo_template_path=/opt/collaboraoffice6.0 --o:child_root_path=/opt/lool/child-roots --o:file_server_root_path=/usr/share/loolwsd ${extra_params}" -s /bin/bash lool
复制代码


仔细分析下脚本:


  1. 第一句cp /etc/resolv.conf /etc/hosts /opt/lool/systemplate/etc/ 很明显就是需要root权限的.

  2. 之后会进行生成证书的操作

  3. 然后会进行相关的变量替换操作

  4. 接下来是当/etc/loolwsd/loolwsd.xml这个配置文件发生变化时进行重启, 注意这边又来了好几个特权操作:

a. /usr/bin/inotifywait

b. /usr/bin/killall

  1. 启动loolwsd 又是一个特权操作: su -c

初步总结需要的特权:

  • root 用户

  • inotifywait

  • killall

  • su -c

解决方案


在 OpenShift 中启用容器的 ROOT

📓 备注:

官方 OpenShift 文档: Enable Container Images that Require Root

这里就不详细的一步步介绍了, 具体步骤后续更另一篇文章: OpenShift 企业测试环境应用部署实战


有些容器镜像(如: postgresredis和这次的collabora)需要 root 权限, 并且对卷属于谁有明确期望. 对于这类镜像, 需要给其对应的 service account(服务账户, 一种特殊账户, 用于系统执行某些操作)加上anyuid SCC(Security Context Constraints: 安全上下文约束):

oc adm policy add-scc-to-user anyuid

system:serviceaccount:myproject:mysvcacct

在 OpenShift 中为容器提供其他 Capabilities

📓 备注:

以下内容来自 Docker 官方文档: Runtime privilege and Linux capabilities


默认情况下,Docker 容器是“无特权的”(unprivileged),例如,不能在 Docker 容器内运行 Docker 守护进程。这是因为在默认情况下,容器不允许访问任何设备,但是一个"privileged"(“特权”)容器可以访问所有设备。


除了"privileged"之外,操作员还可以使用--cap-add--cap-drop对 capabilities(功能)进行细粒度控制。默认情况下,Docker 有一个保留的默认 capabilities 列表。下表列出了 Linux capabilities 选项,这些选项是默认允许的。


Capability Key 用途

SETPCAP 修改进程的 capabilities.

MKNOD 通过 mknod 创建特殊(如设备)文件

AUDIT_WRITE 将记录写入内核审计日志。

CHOWN 任意更改文件 UID 和 GID

NET_RAW 使用 RAW 和 PACKET 的 sockets.

DAC_OVERRIDE 绕过文件的读、写和执行权限检查。

FOWNER Bypass permission checks on operations that normally require the file system UID of the process to match the UID of the file.对通常需要进程的文件系统 UID 与文件的 UID 匹配的操作进行绕过权限检查。

FSETID Don’t clear set-user-ID and set-group-ID permission bits when a file is modified.当文件被修改时,不清除 set-user-ID 和 set-group-ID 权限位。

KILL Bypass permission checks for sending signals.绕过发送信号的权限检查。

SETGID 对进程 GID 进行任意操作; 向用户的命名空间中写入 GID 映射

SETUID 对进程 UID 进行任意操作; 向用户的命名空间中写入 UID 映射

NETBINDSERVICE 为低于 1024 以下的端口绑定 sockets

SYS_CHROOT 使用 chroot, 修改 root 目录

SETFCAP 为文件设置任意的 capabilities.


下表显示了默认情况下未授予的功能,可以添加这些功能。


Capability Key 用途

SYS_MODULE 加载和卸载内核 modules.

SYS_RAWIO 执行 I/O port 操作(iopl 和 ioperm).

SYS_PACCT 使用 acct, 开启或关闭进程 accounting

SYS_ADMIN Perform a range of system administration operations. 执行一系列系统管理员操作

SYS_NICE 提高进程的 nice value(nice, setpriority,并改变任意进程的 nice value。

SYS_RESOURCE 覆盖资源数限制

SYS_TIME 设置系统时钟 (settimeofday, stime, adjtimex; 设置 real-time (硬件) clock.

SYSTTYCONFIG 使用 vhangup ;在虚拟终端上使用各种特权 ioctl 操作。

AUDIT_CONTROL 启用和禁用内核审计;更改审计过滤规则;检索审计状态和过滤规则。

MAC_ADMIN Allow MAC configuration or state changes. Implemented for the Smack LSM.

MAC_OVERRIDE Override Mandatory Access Control (MAC). Implemented for the Smack Linux Security Module (LSM).

NET_ADMIN 执行各种网络相关的操作

SYSLOG 执行 privileged syslog 操作.

DACREADSEARCH 绕过文件读权限检查和目录读和执行权限检查。

LINUXIMMUTABLE Set the FSAPPENDFL and FSIMMUTABLE_FL i-node flags.

NET_BROADCAST 启用套接字广播,监听多播。

IPC_LOCK 锁内存 (mlock, mlockall, mmap, shmctl).

IPC_OWNER 对 System V IPC 对象上的操作进行绕过权限检查。

SYS_PTRACE 使用 ptrace 跟踪任意进程。

SYSBOOT 使用 reboot 和 kexecload,重新启动并加载一个新的内核供以后执行。

LEASE 对任意文件建立租约(参见 fcntl)。

WAKE_ALARM 触发唤醒系统。

BLOCK_SUSPEND 使用可以阻止系统挂起的特性。



更多参考资料见: capabilities(7) - Linux man page


📓 备注:

以下内容来自 OpenShift 官方文档: Provide Additional Capabilities


有时候, 镜像会需要 Docker 默认没有提供的 capabilities(功能). 那么你可以在 pod 的描述文件 specification 中请求这些额外的 capabilities, 这些 capabilities 将根据 SCC 进行验证.


❗️ 注意:

这允许镜像以提权后的功能运行,应该仅在必要时使用。不应编辑默认的受限 SCC 以启用其他功能。


当与非根用户一起使用时,还必须确保使用setcap命令为需要附加功能的文件授予 capabilities。例如,在镜像的 Dockerfile 中:


setcap cap_net_raw,cap_net_admin+p /usr/bin/ping


此外,如果 Docker 中默认提供了功能,则不需要修改 pod specification 来请求它。例如,NET_RAW是默认提供的,应该已经在 ping 上设置了此功能,因此运行 ping 不需要特殊的步骤。


要提供额外的功能:

  1. 创建一个新的 SCC

  2. 使用allowedabilities字段添加允许的功能。

  3. 创建 pod 时,在securityContext.capabilities.add中添加请求该功能的字段。

为 Collabora 提供需要的 Capabilities

针对这个 Collabora 镜像, 仔细分析后, 要快速解决, 其实在容器的 spec 中给它授予"privileged" 就可以了. 注意: 之前关于 root 的权限是在deployment下配置的. 这个是在containers下配置的.


具体配置如下:


说明如下:

  • allowPrivilegeEscalation: true - 允许权限提升. 其实就是给了这个容器"privileged".

  • 用 privileged 的 scc,需要相应的 capabilities. 所以又添加了MKNOD这个 capability.

总结

在 OpenShift 中:

  1. 容器需要 root 用户, 给它对应的 deployment 添加 Service Account, 并添加anyuid的 SCC.

  2. 容器需要其他 capabilities, 简单的方式就是给它"privileged" 这个特权

最后顺便吐槽一下, SCC 和 linux capabilities 实在是太难了, 对安全一知半解的我一脸懵逼. 😂😂😂



发布于: 2021 年 01 月 07 日阅读数: 24
用户头像

东风微鸣

关注

资源共享, 天下为公! 2018.11.08 加入

APM行业认证专家, 容器技术认证专家. 现任中国大地保险PAAS平台架构师. 公众号:东风微鸣技术博客

评论

发布
暂无评论
如何在 OpenShift 中运行 Collabora Office