为什么要求在 Kubernetes PodSecurityPolicy 中删除所有功能是多余的,并且非 root + 不允许特权升级?
Why is requiring that all capabilities be dropped in a Kubernetes PodSecurityPolicy redundant with non-root + disallow privilege escalation?
PodSecurityPolicy documentation 中的第二个示例策略包含以下 PodSecurityPolicy 片段
...
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
...
为什么放弃非 root 用户的所有冗余功能 + 禁止权限升级?您可以拥有一个没有特权升级的容器进程,它不是 root 但具有有效的功能,对吗?
Docker似乎无法做到这一点:
$ docker run --cap-add SYS_ADMIN --user 1000 ubuntu grep Cap /proc/self/status
CapInh: 00000000a82425fb
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 00000000a82425fb
CapAmb: 0000000000000000
所有有效的功能都已被删除,即使在尝试显式添加它们时也是如此。但是其他容器运行时可以实现它,所以这个评论只是 Docker 具体吗?
Why is dropping all capabilities redundant for non-root + disallow privilege escalation?
因为您需要权限升级才能使用 'new' 功能,有效的 allowPrivilegeEscalation: false
是在 execve 系统中禁用 setuid阻止使用任何新功能的调用。
也如文档中所示:"Once the bit is set, it is inherited across fork, clone, and execve and cannot be unset"。更多信息 here。
这与 privileged: false
结合使 requiredDropCapabilities: [ALL]
变得多余。
这里等效的 Docker 选项是:
--user=whatever
=> privileged: false
--security-opt=no-new-privileges
=> allowPrivilegeEscalation: false
--cap-drop=all
=> requiredDropCapabilities: [ALL]
It seems like this is not possible with Docker
这就是 Docker 正在做的事情,当您指定非特权用户时,所有有效功能都会被删除 (CapEff: 0000000000000000
),即使您指定 --cap-add SYS_ADMIN
这与 --security-opt=no-new-privileges
作为一个选项相结合,使 --cap-drop=all
变得多余。
请注意,docker 的默认功能掩码似乎包括 SYS_ADMIN
$ docker run --rm ubuntu grep Cap /proc/self/status
CapInh: 00000000a80425fb
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
$ capsh --decode=00000000a82425fb
0x00000000a82425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_sys_admin,cap_mknod,cap_audit_write,cap_setfcap
为什么 00000000a82425fb
在没有指定任何 --cap-add
选项的情况下相同。
But other container runtimes could implement it, so is this comment just Docker specific?
我想,所以你可能会遇到 privileged: false
和 allowPrivilegeEscalation: false
没有有效禁用功能并且可以用 requiredDropCapabilities:
删除的情况(虽然,我不明白为什么另一个运行时会想要更改 Docker 行为)。
你的问题中有多个(好的)子问题。
我想专注于主要问题:
Why is dropping all capabilities redundant for non-root + disallow
privilege escalation?
为了简单起见,我想我们可以关注 disallow privilege escalation 部分并简单地问:
当我们在 PodSecurityPolicy 中设置 allowPrivilegeEscalation: false
时,幕后发生了什么?
从 K8S docs 可以看到“这个布尔值直接控制是否在容器进程上设置 no_new_privs
标志”。
如果设置了这个标志会发生什么?
引自kernel docs:“设置此标志后,execve 承诺不会授予执行任何在没有 execve 调用的情况下无法完成的操作的特权。
例如,setuid 和 setgid 位将不再更改 uid 或 gid;文件功能不会添加到允许集.
换句话说,设置allowPrivilegeEscalation: false
将导致所有能力被丢弃。
这就是为什么添加这部分被认为是多余的:
requiredDropCapabilities:
- ALL
我希望这能简化一些事情。
我认为其他问题的答案在接受的答案中已经很清楚了,我没有什么可以补充的。
注意:如果您是 运行 内核 >= 4.10,那么您可以在 /proc/[pid]/status
文件中看到线程的 no_new_privs
属性的值 - 在功能属性下:
.
.
CapInh: 00000000a82425fb
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 00000000a82425fb
CapAmb: 0000000000000000
NoNewPrivs: 0 <-----
.
.
PodSecurityPolicy documentation 中的第二个示例策略包含以下 PodSecurityPolicy 片段
...
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
...
为什么放弃非 root 用户的所有冗余功能 + 禁止权限升级?您可以拥有一个没有特权升级的容器进程,它不是 root 但具有有效的功能,对吗?
Docker似乎无法做到这一点:
$ docker run --cap-add SYS_ADMIN --user 1000 ubuntu grep Cap /proc/self/status
CapInh: 00000000a82425fb
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 00000000a82425fb
CapAmb: 0000000000000000
所有有效的功能都已被删除,即使在尝试显式添加它们时也是如此。但是其他容器运行时可以实现它,所以这个评论只是 Docker 具体吗?
Why is dropping all capabilities redundant for non-root + disallow privilege escalation?
因为您需要权限升级才能使用 'new' 功能,有效的 allowPrivilegeEscalation: false
是在 execve 系统中禁用 setuid阻止使用任何新功能的调用。
也如文档中所示:"Once the bit is set, it is inherited across fork, clone, and execve and cannot be unset"。更多信息 here。
这与 privileged: false
结合使 requiredDropCapabilities: [ALL]
变得多余。
这里等效的 Docker 选项是:
--user=whatever
=>privileged: false
--security-opt=no-new-privileges
=>allowPrivilegeEscalation: false
--cap-drop=all
=>requiredDropCapabilities: [ALL]
It seems like this is not possible with Docker
这就是 Docker 正在做的事情,当您指定非特权用户时,所有有效功能都会被删除 (CapEff: 0000000000000000
),即使您指定 --cap-add SYS_ADMIN
这与 --security-opt=no-new-privileges
作为一个选项相结合,使 --cap-drop=all
变得多余。
请注意,docker 的默认功能掩码似乎包括 SYS_ADMIN
$ docker run --rm ubuntu grep Cap /proc/self/status
CapInh: 00000000a80425fb
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
$ capsh --decode=00000000a82425fb
0x00000000a82425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_sys_admin,cap_mknod,cap_audit_write,cap_setfcap
为什么 00000000a82425fb
在没有指定任何 --cap-add
选项的情况下相同。
But other container runtimes could implement it, so is this comment just Docker specific?
我想,所以你可能会遇到 privileged: false
和 allowPrivilegeEscalation: false
没有有效禁用功能并且可以用 requiredDropCapabilities:
删除的情况(虽然,我不明白为什么另一个运行时会想要更改 Docker 行为)。
你的问题中有多个(好的)子问题。
我想专注于主要问题:
Why is dropping all capabilities redundant for non-root + disallow privilege escalation?
为了简单起见,我想我们可以关注 disallow privilege escalation 部分并简单地问:
当我们在 PodSecurityPolicy 中设置 allowPrivilegeEscalation: false
时,幕后发生了什么?
从 K8S docs 可以看到“这个布尔值直接控制是否在容器进程上设置 no_new_privs
标志”。
如果设置了这个标志会发生什么?
引自kernel docs:“设置此标志后,execve 承诺不会授予执行任何在没有 execve 调用的情况下无法完成的操作的特权。
例如,setuid 和 setgid 位将不再更改 uid 或 gid;文件功能不会添加到允许集.
换句话说,设置allowPrivilegeEscalation: false
将导致所有能力被丢弃。
这就是为什么添加这部分被认为是多余的:
requiredDropCapabilities:
- ALL
我希望这能简化一些事情。
我认为其他问题的答案在接受的答案中已经很清楚了,我没有什么可以补充的。
注意:如果您是 运行 内核 >= 4.10,那么您可以在 /proc/[pid]/status
文件中看到线程的 no_new_privs
属性的值 - 在功能属性下:
.
.
CapInh: 00000000a82425fb
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 00000000a82425fb
CapAmb: 0000000000000000
NoNewPrivs: 0 <-----
.
.