From ffc7435a0c21ddea868670bd5f7e7cdb6ba239d0 Mon Sep 17 00:00:00 2001 From: "huanqing.shao" Date: Fri, 4 Oct 2019 16:57:09 +0800 Subject: [PATCH] security context --- .vuepress/config.js | 9 +- .../learning/sec-ctx/security-context-1.yaml | 21 ++++ .../learning/sec-ctx/security-context-2.yaml | 14 +++ .../learning/sec-ctx/security-context-3.yaml | 9 ++ .../learning/sec-ctx/security-context-4.yaml | 12 ++ docker-compose.yaml | 2 +- .../config/sec-ctx/con-cap.md | 105 +++++++++++++++++- .../config/sec-ctx/con-sel.md | 16 ++- .../k8s-intermediate/config/sec-ctx/con.md | 38 ++++++- .../k8s-intermediate/config/sec-ctx/index.md | 6 +- .../k8s-intermediate/config/sec-ctx/pod.md | 76 ++++++++++++- .../config/sec-ctx/volumes.md | 18 +++ support/index.md | 4 +- 13 files changed, 310 insertions(+), 20 deletions(-) create mode 100644 .vuepress/public/statics/learning/sec-ctx/security-context-1.yaml create mode 100644 .vuepress/public/statics/learning/sec-ctx/security-context-2.yaml create mode 100644 .vuepress/public/statics/learning/sec-ctx/security-context-3.yaml create mode 100644 .vuepress/public/statics/learning/sec-ctx/security-context-4.yaml create mode 100644 learning/k8s-intermediate/config/sec-ctx/volumes.md diff --git a/.vuepress/config.js b/.vuepress/config.js index f37a3ff..242742a 100644 --- a/.vuepress/config.js +++ b/.vuepress/config.js @@ -322,10 +322,11 @@ module.exports = { collapsable: true, children: [ 'k8s-intermediate/config/sec-ctx/', - // 'k8s-intermediate/config/sec-ctx/pod', - // 'k8s-intermediate/config/sec-ctx/con', - // 'k8s-intermediate/config/sec-ctx/con-cap', - // 'k8s-intermediate/config/sec-ctx/con-sel', + 'k8s-intermediate/config/sec-ctx/pod', + 'k8s-intermediate/config/sec-ctx/con', + 'k8s-intermediate/config/sec-ctx/con-cap', + 'k8s-intermediate/config/sec-ctx/con-sel', + 'k8s-intermediate/config/sec-ctx/volumes', ] }, ] diff --git a/.vuepress/public/statics/learning/sec-ctx/security-context-1.yaml b/.vuepress/public/statics/learning/sec-ctx/security-context-1.yaml new file mode 100644 index 0000000..35cb1ee --- /dev/null +++ b/.vuepress/public/statics/learning/sec-ctx/security-context-1.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo +spec: + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 + volumes: + - name: sec-ctx-vol + emptyDir: {} + containers: + - name: sec-ctx-demo + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + volumeMounts: + - name: sec-ctx-vol + mountPath: /data/demo + securityContext: + allowPrivilegeEscalation: false diff --git a/.vuepress/public/statics/learning/sec-ctx/security-context-2.yaml b/.vuepress/public/statics/learning/sec-ctx/security-context-2.yaml new file mode 100644 index 0000000..89db18d --- /dev/null +++ b/.vuepress/public/statics/learning/sec-ctx/security-context-2.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo-2 +spec: + securityContext: + runAsUser: 1000 + containers: + - name: sec-ctx-demo-2 + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + securityContext: + runAsUser: 2000 + allowPrivilegeEscalation: false diff --git a/.vuepress/public/statics/learning/sec-ctx/security-context-3.yaml b/.vuepress/public/statics/learning/sec-ctx/security-context-3.yaml new file mode 100644 index 0000000..25fbe11 --- /dev/null +++ b/.vuepress/public/statics/learning/sec-ctx/security-context-3.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo-3 +spec: + containers: + - name: sec-ctx-demo-3 + image: busybox + command: [ "sh", "-c", "sleep 1h" ] diff --git a/.vuepress/public/statics/learning/sec-ctx/security-context-4.yaml b/.vuepress/public/statics/learning/sec-ctx/security-context-4.yaml new file mode 100644 index 0000000..c8e2d2e --- /dev/null +++ b/.vuepress/public/statics/learning/sec-ctx/security-context-4.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo-4 +spec: + containers: + - name: sec-ctx-demo-4 + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + securityContext: + capabilities: + add: ["NET_ADMIN", "SYS_TIME"] diff --git a/docker-compose.yaml b/docker-compose.yaml index 548e0e7..2d2cef7 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -12,7 +12,7 @@ services: restart_policy: condition: on-failure ports: - - "9080:80" + - "8081:80" volumes: - ./docs:/usr/share/nginx/html networks: diff --git a/learning/k8s-intermediate/config/sec-ctx/con-cap.md b/learning/k8s-intermediate/config/sec-ctx/con-cap.md index 065ff34..e2bf1b0 100644 --- a/learning/k8s-intermediate/config/sec-ctx/con-cap.md +++ b/learning/k8s-intermediate/config/sec-ctx/con-cap.md @@ -1,7 +1,7 @@ --- -# vssueId: 64 +vssueId: 111 layout: LearningLayout -description: Kubernetes教程_为Pod容器组或Container容器配置Security Context安全上下文 +description: Kubernetes教程_为Pod容器组或Container容器配置Security Context安全上下文的 Linux Capabilities。使用 Linux Capabilities 可以为容器内的进程授予某些特定的权限(而不是 root 用户的所有权限)。在容器定义的 securityContext 中添加 capabilities 字段,可以向容器添加或删除 Linux Capability。 meta: - name: keywords content: Kubernetes教程,K8S教程,Security Context,SecurityContext @@ -9,4 +9,103 @@ meta: # 为容器设置Linux Capabilities -正在撰写... +使用 [Linux Capabilities](http://man7.org/linux/man-pages/man7/capabilities.7.html) 可以为容器内的进程授予某些特定的权限(而不是 root 用户的所有权限)。在容器定义的 `securityContext` 中添加 `capabilities` 字段,可以向容器添加或删除 Linux Capability。 + +本文后续章节中,先运行一个不包含 `capabilities` 字段的容器,观察容器内进程的 linux capabilities 位图的情况;然后在运行一个包含 `capabilities` 字段的容器,比较其 linux capabilities 位图与前者的不同。 + +## 无capabilities字段时 + +我们先确认在没有 `capabilities` 字段时,容器的行为是怎样的。下面的例子中包含一个容器,我们没有为其添加或删除任何 Linux capability。 + +<<< @/.vuepress/public/statics/learning/sec-ctx/security-context-3.yaml + +* 执行命令以创建 Pod + ``` sh + kubectl apply -f https://kuboard.cn/statics/learning/sec-ctx/security-context-3.yaml + ``` +* 执行命令以验证容器正在运行 + ``` sh + kubectl get pod security-context-demo-3 + ``` +* 执行命令以进入容器的命令行界面 + ``` sh + kubectl exec -it security-context-demo-3 -- sh + ``` +* 在容器的命令行界面中查看正在运行的进程 + ``` sh + ps aux + ``` + 输出结果中展示了容器中进程的 process ID(PID),如下所示: + ``` + PID USER TIME COMMAND + 1 root 0:00 sleep 1h + 6 root 0:00 sh + 11 root 0:00 ps aux + ``` +* 在容器的命令行界面中查看 process 1 的状态 + ``` sh + cd /proc/1 + cat status + ``` + 输出结果中展示了该进程 Linux Capabilities 的位图,如下所示: + ``` {2,3} + ... + CapPrm: 00000000a80425fb + CapEff: 00000000a80425fb + ... + ``` +* 记录下该进程的位图,然后执行命令 `exit` 退出重启的命令行界面 + +## 有capabilities字段时 + +接下来,我们运行同样的一个容器,不同的是,这次为其设置了 `capabilities` 字段。下面是 yaml 配置文件,该配置中为进程添加了两个 Linux Capability: `CAP_NET_ADMIN` 和 `CAP_SYS_TIME`: + +<<< @/.vuepress/public/statics/learning/sec-ctx/security-context-4.yaml + +* 执行命令以创建 Pod + ``` sh + kubectl apply -f https://kuboard.cn/statics/learning/sec-ctx/security-context-4.yaml + ``` +* 执行命令以验证容器正在运行 + ``` sh + kubectl get pod security-context-demo-4 + ``` +* 执行命令以进入容器的命令行界面 + ``` sh + kubectl exec -it security-context-demo-4 -- sh + ``` +* 在容器的命令行界面中查看正在运行的进程 + ``` sh + ps aux + ``` + 输出结果中展示了容器中进程的 process ID(PID),如下所示: + ``` + PID USER TIME COMMAND + 1 root 0:00 sleep 1h + 6 root 0:00 sh + 11 root 0:00 ps aux + ``` +* 在容器的命令行界面中查看 process 1 的状态 + ``` sh + cd /proc/1 + cat status + ``` + 输出结果中展示了该进程 Linux Capabilities 的位图,如下所示: + ``` {2,3} + ... + CapPrm: 00000000aa0435fb + CapEff: 00000000aa0435fb + ... + ``` +* 记录下该进程的位图,然后执行命令 `exit` 退出重启的命令行界面 + +* 比较两次运行,进程的 Linux Capabilities 位图的差异: + ``` + 第一次运行:00000000a80425fb + 第二次运行:00000000aa0435fb + ``` + 第一次运行时,位图的 12 位和 25 为是 0。第二次运行时,12 位和 25 位是 1.查看 Linux Capabilities 的常量定义文件 [capability.h](https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h) 可知:12 位代表 `CAP_NET_ADMIN`,25 位代表 `CAP_SYS_TIME`。 + +::: tip LinuxCapability常量 +Linux Capabilities 常量格式为 `CAP_XXX`。然而,在容器定义中添加或删除 Linux Capabilities 时,必须去除常量的前缀 `CAP_`。例如:向容器中添加 `CAP_SYS_TIME` 时,只需要填写 `SYS_TIME`。 +::: diff --git a/learning/k8s-intermediate/config/sec-ctx/con-sel.md b/learning/k8s-intermediate/config/sec-ctx/con-sel.md index d6ebe88..330f4de 100644 --- a/learning/k8s-intermediate/config/sec-ctx/con-sel.md +++ b/learning/k8s-intermediate/config/sec-ctx/con-sel.md @@ -1,7 +1,7 @@ --- -# vssueId: 64 +vssueId: 112 layout: LearningLayout -description: Kubernetes教程_为Pod容器组或Container容器配置Security Context安全上下文 +description: Kubernetes教程_为Pod容器组或Container容器配置Security Context安全上下文的_seLinuxOptions meta: - name: keywords content: Kubernetes教程,K8S教程,Security Context,SecurityContext @@ -9,4 +9,14 @@ meta: # 为容器设置SELinux标签 -正在撰写... +Pod 或容器定义的 `securityContext` 中 `seLinuxOptions` 字段是一个 [SELinuxOptions](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#selinuxoptions-v1-core) 对象,该字段可用于为容器指定 SELinux 标签。如下所示: + +``` yaml +securityContext: + seLinuxOptions: + level: "s0:c123,c456" +``` + +::: tip +为容器指定 SELinux 标签时,宿主节点的 SELinux 模块必须加载。 +::: diff --git a/learning/k8s-intermediate/config/sec-ctx/con.md b/learning/k8s-intermediate/config/sec-ctx/con.md index 5cc3ecc..9b7ee9d 100644 --- a/learning/k8s-intermediate/config/sec-ctx/con.md +++ b/learning/k8s-intermediate/config/sec-ctx/con.md @@ -1,7 +1,7 @@ --- -# vssueId: 64 +vssueId: 110 layout: LearningLayout -description: Kubernetes教程_为Pod容器组或Container容器配置Security Context安全上下文 +description: Kubernetes教程_为Container容器配置Security Context安全上下文。容器的定义中包含 securityContext 字段。通过指定该字段,可以为容器设定安全相关的配置,当该字段的配置与 Pod 级别的 securityContext 配置相冲突时,容器级别的配置将覆盖 Pod 级别的配置。 meta: - name: keywords content: Kubernetes教程,K8S教程,Security Context,SecurityContext @@ -9,4 +9,36 @@ meta: # 为容器设置Security Context -正在撰写... +容器的定义中包含 `securityContext` 字段,该字段接受 [SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#securitycontext-v1-core) 对象。通过指定该字段,可以为容器设定安全相关的配置,当该字段的配置与 Pod 级别的 `securityContext` 配置相冲突时,容器级别的配置将覆盖 Pod 级别的配置。容器级别的 `securityContext` 不影响 Pod 中的数据卷。 + +下面的示例中的 Pod 包含一个 Container,且 Pod 和 Container 都有定义 `securityContext` 字段: + +<<< @/.vuepress/public/statics/learning/sec-ctx/security-context-2.yaml {7,13} + +* 执行命令以创建 Pod + ``` sh + kubectl apply -f https://kuboard.cn/statics/learning/sec-ctx/security-context-2.yaml + ``` +* 执行命令以验证容器已运行 + ``` sh + kubectl get pod security-context-demo-2 + ``` +* 执行命令进入容器的命令行界面: + ``` sh + kubectl exec -it security-context-demo-2 -- sh + ``` +* 在命令行界面中查看所有的进程 + ```sh + ps aux + ``` + 请注意,容器的进程以 userID 2000 的身份运行。该取值由 `spec.containers[*].securityContext.runAsUser` 容器组中的字段定义。Pod 中定义的 `spec.securityContext.runAsUser` 取值 1000 被覆盖。输出结果如下所示: + ``` + PID USER TIME COMMAND + 1 2000 0:00 sleep 1h + 6 2000 0:00 sh + 11 2000 0:00 ps aux + ... + ``` +* 执行命令 `exit` 退出命令行界面 + +:tada: :tada: :tada: diff --git a/learning/k8s-intermediate/config/sec-ctx/index.md b/learning/k8s-intermediate/config/sec-ctx/index.md index c73891a..97f62e0 100644 --- a/learning/k8s-intermediate/config/sec-ctx/index.md +++ b/learning/k8s-intermediate/config/sec-ctx/index.md @@ -1,5 +1,6 @@ --- vssueId: 108 +titlePrefix: 为Pod或Container配置Security Context layout: LearningLayout description: Kubernetes教程_为Pod容器组或Container容器配置Security Context安全上下文 meta: @@ -7,7 +8,7 @@ meta: content: Kubernetes教程,K8S教程,Security Context,SecurityContext --- -# 为Pod或Container配置Security Context +# 概述 > 参考文档:Kubernetes 官网文档 [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#assign-selinux-labels-to-a-container) @@ -36,3 +37,6 @@ Security Context可以按照如下几种方式设定: * [为容器设置Security Context](./con.html) * [为容器设置Linux Capabilities](./con-cap.html) * [为容器设置SELinux标签](./con-sel.html) +* [关于数据卷](./volumes.html) + +> 详细信息请点击对应链接。 diff --git a/learning/k8s-intermediate/config/sec-ctx/pod.md b/learning/k8s-intermediate/config/sec-ctx/pod.md index dcfa6b9..4d47d67 100644 --- a/learning/k8s-intermediate/config/sec-ctx/pod.md +++ b/learning/k8s-intermediate/config/sec-ctx/pod.md @@ -1,7 +1,7 @@ --- -# vssueId: 64 +vssueId: 109 layout: LearningLayout -description: Kubernetes教程_为Pod容器组或Container容器配置Security Context安全上下文 +description: Kubernetes教程_为Pod容器组配置Security Context安全上下文。在 Pod 的定义中增加 securityContext 字段,即可为 Pod 指定 Security 相关的设定。通过该字段指定的内容将对该 Pod 中所有的容器生效。 meta: - name: keywords content: Kubernetes教程,K8S教程,Security Context,SecurityContext @@ -9,4 +9,74 @@ meta: # 为Pod设置Security Context -正在撰写... +在 Pod 的定义中增加 `securityContext` 字段,即可为 Pod 指定 Security 相关的设定。 `securityContext` 字段是一个 [PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#podsecuritycontext-v1-core) 对象。通过该字段指定的内容将对该 Pod 中所有的容器生效。 + +## Pod示例 + +以下面的 Pod 为例: + +<<< @/.vuepress/public/statics/learning/sec-ctx/security-context-1.yaml {7,8,9,21} + +在上面的例子中: +* `spec.securityContext.runAsUser` 字段指定了该 Pod 中所有容器的进程都以UserID `1000` 的身份运行,`spec.securityContext.runAsGroup` 字段指定了该 Pod 中所有容器的进程都以GroupID `3000` 的身份运行 + * 如果该字段被省略,容器进程的GroupID为 root(0) + * 容器中创建的文件,其所有者为 userID 1000,groupID 3000 +* `spec.securityContext.fsGroup` 字段指定了该 Pod 的 fsGroup 为 2000 + * 数据卷 (本例中,对应挂载点 `/data/demo` 的数据卷为 `sec-ctx-demo`) 的所有者以及在该数据卷下创建的任何文件,其 GroupID 为 2000 + +## 执行Pod示例 + +* 创建 Pod + ```sh + kubectl apply -f https://kuboard.cn/statics/learning/sec-ctx/security-context-1.yaml + ``` +* 验证 Pod 已运行 + ```sh + kubectl get pod security-context-demo + ``` +* 进入容器的命令行界面 + ```sh + kubectl exec -it security-context-demo -- sh + ``` +* 在该命令行界面中,查看正在运行的进程 + ```sh + ps + ``` + 请注意,所有的进程都以 user 1000 的身份运行(由 runAsUser 指定),输出结果如下所示: + ``` + PID USER TIME COMMAND + 1 1000 0:00 sleep 1h + 6 1000 0:00 sh + ... + ``` +* 在命令行界面中,切换到目录 `/data`,并查看目录中的文件列表 + ```sh + cd /data + ls -l + ``` + 请注意,`/data/demo` 目录的 groupID 为 2000(由 fsGroup 指定),输出结果如下所示: + ``` + drwxrwsrwx 2 root 2000 4096 Oct 4 05:08 demo + ``` +* 在命令行界面中,切换到目录 `/data/demo`,并创建一个文件 + ``` sh + cd /data/demo + echo hello > testfile + ls -l + ``` + 请注意,`testfile` 的 groupID 为 2000 (由 FSGroup 指定),输出结果如下所示: + ``` + -rw-r--r-- 1 1000 2000 6 Oct 4 05:09 testfile + ``` +* 在命令行界面中执行 `id` 命令,输出结果如下所示: + ``` sh + $ id + uid=1000 gid=3000 groups=2000 + ``` + 请注意: + * gid 为 3000,与 `runAsGroup` 字段所指定的一致 + * 如果 `runAsGroup` 字段被省略,则 gid 取值为 0(即 root),此时容器中的进程将可以操作 root Group 的文件 + +* 执行 `exit` 退出命令行界面 + +:tada: :tada: :tada: diff --git a/learning/k8s-intermediate/config/sec-ctx/volumes.md b/learning/k8s-intermediate/config/sec-ctx/volumes.md new file mode 100644 index 0000000..d01553f --- /dev/null +++ b/learning/k8s-intermediate/config/sec-ctx/volumes.md @@ -0,0 +1,18 @@ +--- +# vssueId: 112 +layout: LearningLayout +description: Kubernetes教程_为Pod容器组或Container容器配置Security Context安全上下文的_seLinuxOptions +meta: + - name: keywords + content: Kubernetes教程,K8S教程,Security Context,SecurityContext +--- + +# 关于数据卷 + +Pod 的 securityContext 作用于 Pod 中所有的容器,同时对 Pod 的数据卷也同样生效。具体来说,`fsGroup` 和 `seLinuxOptions` 将被按照如下方式应用到 Pod 中的数据卷: +* `fsGroup`:对于支持 ownership 管理的数据卷,通过 `fsGroup` 指定的 GID 将被设置为该数据卷的 owner,并且可被 `fsGroup` 写入。更多细节请参考 [Ownership Management design document](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/volume-ownership-management.md) +* `seLinuxOptions`:对于支持 SELinux 标签的数据卷,将按照 `seLinuxOptions` 的设定重新打标签,以使 Pod 可以访问数据卷内容。通常您只需要设置 `seLinuxOptions` 中 `level` 这一部分内容。该设定为 Pod 中所有容器及数据卷设置 [Multi-Category Security (MCS)](https://selinuxproject.org/page/NB_MLS) 标签。 + +::: warning +这段内容来自于 [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#discussion)。尚未验证这段文字的细节。 +::: diff --git a/support/index.md b/support/index.md index 23cf377..c5b86a5 100644 --- a/support/index.md +++ b/support/index.md @@ -29,10 +29,10 @@ description: Kubernetes教程_本文描述了如何获得Kuboard授权 -
  • Kuboard 诞生于大型微服务项目的落地实施,在其发布之前,就已经经历了许多个实际项目的考验
  • +
  • Kuboard 诞生于大型微服务项目的落地实施,在其发布之前,就已经在许多个实际项目中经受住了考验
  • Kuboard 一经发布,就获得了广泛的关注
  • Kuboard 公开发布不到两个月时间,就已经获得了 422 Github Star(如图所示)
  • -
  • Kuboard 社群中,已有许多的用户将Kuboard用于自己的生产环境
  • +
  • Kuboard 社群中,已有许多的用户将 Kuboard 用于自己的生产环境