13、容器安全上下文
Context
Container Security Context 应在特定 namespace 中修改 Deployment。
Task
按照如下要求修改 sec-ns 命名空间里的 Deployment secdep
一、用 ID 为 30000 的用户启动容器(设置用户 ID 为: 30000)
二、不允许进程获得超出其父进程的特权(禁止 allowPrivilegeEscalation)
三、以只读方式加载容器的根文件系统(对根文件的只读权限)
官方文档搜索”容器上下文" 找到 “为Pod或容器配置安全上下文”这个文档,可以看到有相关介绍。根据题目要求,有三个参数需要设置:
- 用户ID,按照文档应该是 runAsUser 参数设置
- allowPrivilegeEscalation 参数,按要求应该设置为 false
- 根目录只读,是 readOnlyRootFilesystem 参数,按要求应该设置为 true
runAsUser 这个参数可以在pod设置,也可以在container设置,后面两个参数都是container级别的,只能在container里面设置。所以每个container里都要设置一次。
# kubectl get deploy -n sec-ns secdep -o yaml > secdep_deploy.yaml #先备份一下
# kubeclt edit deploy -n sec-ns secdep
要注意,pod级别默认是应该有 securityContext参数了(我自己环境测试的时候是自动补全了,如果考试时没找到就自己加)。
视频里没注意到这点,直接在 template.spec 下面新增多一个,最后修改完发现还是空的。
...
volumeMounts:
- mountPath: /usr/local/nginx/conf/conf.d
name: nginx-config
securityContext: ## 这里与container的 volumeMounts对齐。每个container都要新增这三行。
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
...
schedulerName: default-scheduler
securityContext: ## 这个pod级别的,默认就有了,只不过默认值是 {}
runAsUser: 30000 ## 新增一行,添加这个参数。
14、启用 API server 认证
Context
由 kubeadm 创建的 cluster 的 Kubernetes API 服务器,出于测试目的,
临时配置允许未经身份验证和未经授权的访问,授予匿名用户 cluster-admin 的访问权限.
Task
重新配置 cluster 的 Kubernetes APl 服务器,以确保只允许经过身份验证和授权的 REST 请求。
使用授权模式 Node,RBAC 和准入控制器 NodeRestriction。
删除用户 system:anonymous 的 ClusterRoleBinding 来进行清理。
注意:所有 kubectl 配置环境/文件也被配置使用未经身份验证和未经授权的访问。
你不必更改它,但请注意,一旦完成 cluster 的安全加固, kubectl 的配置将无法工作。
您可以使用位于 cluster 的 master 节点上,cluster 原本的 kubectl 配置文件
/etc/kubernetes/admin.conf ,以确保经过身份验证的授权的请求仍然被允许。
14.1 配置Api Server 授权认证
关于授权模式,其实在前面的题目中已经涉及过,在api server参数中设置
- --authorization-mode=Node,RBAC
而准入控制器 NodeRestriction,也可以在 apiserver的官方文档中搜索NodeRestriction 可以找到有两个参数的值列表是包含这个的。
--disable-admission-plugins strings
--enable-admission-plugins strings
按题目要求,我们是要使用准入控制器,所以应该使用 –enable-admission-plugins 这个参数。所以我们修改 apiserver的yaml文件。注意,这两个参数应该是已经存在的,所以直接搜索后修改其值(不要直接新增)
#vi /etc/kubernetes/manifests/kube-apiserver.yaml
...
- --authorization-mode=Node,RBAC
- --enable-admission-plugins=NodeRestriction
然后重新重启kubelet生效
#systemctl daemon-reload
#systemctl restart kubelet.service
重启完成后,无法再直接使用kubectl命令,需要指定kubeconf文件才能继续使用
#kubectl --kubeconfig /etc/kubernetes/admin.conf get nodes
14.2 删除匿名用户的角色绑定
按照题目要求,是要删除 system:anonymous 这个用户的 ClusterRoleBinding。所以我们要先找到这个 ClusterRoleBinding 的名称,再删除。
# kubectl get ClusterRoleBinding -o jsonpath='{range .items[*]}{.metadata.name},{.subjects[0].name}{"\n"}{end}'|grep coredns #我的环境没有那个用户,所以用coredns来演示
system:coredns,coredns ##结果,逗号前面的是 ClusterRoleBinding 名称,逗号后面的是用户名
但是看视频,ClusterRoleBinding 的名字就是 system:anonymous ,直接删除就行。可能是题目的中文翻译有问题,因为这种格式确实不太像是用户名称。
所以正式考试时先直接找 system:anonymous 这个 ClusterRoleBinding 是否存在,存在的话可以 describe 看下是否符合,确定就可以删除
#kubectl delete ClusterRoleBinding system:anonymous
15、TLS安全配置
Task
通过 TLS 加强 kube-apiserver 安全配置,要求
1、kube-apiserver 除了 VersionTLS13 及以上的版本可以使用,其他版本都不允许使用。
2、密码套件(Cipher suite)为 TLS_AES_128_GCM_SHA256
通过 TLS 加强 ETCD 安全配置,要求
1、密码套件(Cipher suite)为 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
这道题跟正式考试时差别比较大,仅供参考了。
15.1 kube-apiserver配置
打开官方文档关于kube-apiserver的介绍,根据关键字 VersionTLS13 搜索,找到下面这个参数
--tls-min-version string
支持的最低 TLS 版本。可能的值:VersionTLS10,VersionTLS11,VersionTLS12,VersionTLS13
再根据TLS_AES_128_GCM_SHA256 找到:
--tls-cipher-suites strings
服务器的密码套件的列表,以逗号分隔。如果省略,将使用默认的 Go 密码套件。
首选值: TLS_AES_128_GCM_SHA256、TLS_AES_256_GCM_SHA384....
所以我们修改kube-apiserver的yaml文件,修改或增加这两个参数的值。
#cp /etc/kubernetes/manifests/kube-apiserver.yaml /tmp
#vi /etc/kubernetes/manifests/kube-apiserver.yaml
...
- --tls-min-version=VersionTLS13
- --tls-cipher-suites=TLS_AES_128_GCM_SHA256
重启kubelet生效,也可以等etcd也修改好后再一起重启。
#systemctl daemon-reload
#systemctl restart kubelet.service
15.2 etcd配置
etcd的参数在k8s官网找不到,而考试时是不允许打开其它网站的。可以按照视频办法,通过etcd -h命令查看。若没有etcd命令,则需要先安装
#apt install etcd-server
#etcd -h
--cipher-suites '' ## 能找到这个参数最符合题目要求(Cipher suite)
然后修改 etcd的yaml文件
# cp /etc/kubernetes/manifests/etcd.yaml /tmp/
#vi /etc/kubernetes/manifests/etcd.yaml
...
- --cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
重启kubelet生效.
#systemctl daemon-reload
#systemctl restart kubelet.service
15.3 另外的查看参数办法
除了上面介绍的办法,我们也可以通过进入kube-apiserver 和 etcd 的pod里面执行帮助命令来查找相关参数
# kubectl exec -it -n kube-system kube-apiserver-t-kubeadm-001 -- kube-apiserver -h|grep tls
--tls-cipher-suites strings Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used.
--tls-min-version string Minimum TLS version supported. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13
# kubectl exec -it -n kube-system etcd-t-kubeadm-001 -- etcd -h|grep cipher
--cipher-suites ''
Comma-separated list of supported TLS cipher suites between client/server and peers (empty will be auto-populated by Go).
16、 ImagePolicyWebhook 容器镜像扫描
Context
cluster上设置了容器镜像扫描器,但尚未完全集成到 cluster 的配置中。
完成后,容器镜像扫描器应扫描并拒绝易受攻击的镜像的使用。
Task
注意:你必须在 cluster 的 master 节点上完成整个考题,所有服务和文件都已被准备好并放置在该节点上。
给定一个目录 /etc/kubernetes/epconfig 中不完整的配置,
以及具有 HTTPS 端点 https://image-bouncer-webhook.default.svc:1323/image_policy 的功能性容器镜像扫描器:
1. 启用必要的插件来创建镜像策略
2. 校验控制配置并将其更改为隐式拒绝(implicit deny)
3. 编辑配置以正确指向提供的 HTTPS 端点
最后,通过尝试部署易受攻击的资源 /cks/img/web1.yaml 来测试配置是否有效。
/etc/kubernetes/epconfig 目录下有以下文件:
admission_configuraton.json
kubeconfig.yml
front-proxy-client.key
front-proxy=client.crt
server.crt
server-key.pem
admission_configuraton.json 内容如下
{
"imagePolicy":{
"kubeConfigFile":"/etc/kubernetes/epconfig/kubeconfig.yml",
"allowTTL": 50,
"denyTTL": 50,
"retryBackoff":500,
"defaultAllow": true
}
}
kubeconfig.yml 内容如下:
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/epconfig/server.crt
name: houncer_webhook
contextst:
- context:
cluster: bouncer_webhook
user: api-server
name: bouncer_validator
current-context: bouncer_validator
preferences: {}
users :
- name: api-server
user:
client-certificate: /etc/kubernetes/pki/front-proxy-client.crt
client-key: /etc/kubernetes/pki/front-proxy-client.key
16.1 修改 ImagePolicyWebhook 准入配置
首先,我们官网搜索准入控制器或者ImagePolicyWebhook。找到准入控制器的介绍文档,然后搜索 ImagePolicyWebhook 找到这个准入控制器的介绍部分。
ImagePolicyWebhook 准入控制器允许使用后端 Webhook 做出准入决策。
此准入控制器默认被禁用。
因为这个准入控制器是默认被禁用的,所以需要先显式声明启用。我们在apiserver文档里搜索ImagePolicyWebhook这个可以找到启用这个准入控制器的参数
--enable-admission-plugins strings
接着看准入控制器的介绍,看到
在通过命令行标志 --admission-control-config-file 为 API 服务器提供的文件中, 引用 ImagePolicyWebhook 配置文件:
我们在apiserver中也找到了该参数
--admission-control-config-file string
包含准入控制配置的文件。
这两个参数我们在第二步里再修改(apiserver里面的参数)。
我们看题目要求的第二点:校验控制配置并将其更改为隐式拒绝(implicit deny)。这个是在admission_configuraton.json文件里配置
{
"imagePolicy":{
"kubeConfigFile":"/etc/kubernetes/epconfig/kubeconfig.yml",
"allowTTL": 50,
"denyTTL": 50,
"retryBackoff":500,
"defaultAllow": false
}
}
只需要把 defaultAllow 的值从 true 修改为 false。另外,注意检查 kubeConfigFile 这个参数指定的文件是否正确。
再看第三点要求:编辑配置以正确指向提供的 HTTPS 端点。 这个是在kubeconfig.yml文件里定义,参考文档里的介绍,我们修改如下
...
- cluster:
certificate-authority: /etc/kubernetes/epconfig/server.crt
server: https://image-bouncer-webhook.default.svc:1323/image_policy ## 增加这行
...
这样就修改完了(我有点疑问就是其他认证文件好像都没用上,总感觉不至于给多这么多文件的)。
16.2 配置apiserver支持ImagePolicyWebhook
按照上面的分析,需要增加两个参数,而且由于涉及到使用配置文件,所以要增加卷的挂载(和前面的审计日志后端类似)
#cp /etc/kubernetes/manifests/kube-apiserver.yaml /tmp
#vi /etc/kubernetes/manifests/kube-apiserver.yaml
...
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook ## 注意,原来已经有这个参数了,不要删除原来的值,在后面添加。
- --admission-control-config-file=/etc/kubernetes/epconfig/admission_configuraton.json ## 先检查是否存在,存在则修改值,不存在则新增。
...
volumeMounts:
- mountPath: /etc/kubernetes/epconfig/ ## 注意检查是否已经存在,不要重复添加,会报错。
name: epconfig
readOnly: true
...
volumes:
- hostPath:
path: /etc/kubernetes/epconfig/ ## 注意检查是否已经存在,不要重复添加,会报错。
type: DirectoryOrCreate
name: epconfig
16.3 生效和验证
重启kubelet让配置生效
#systemctl daemon-reload
#systemctl restart kubelet.service
#kubectl apply -f /cks/img/web1.yaml
如果应用 /cks/img/web1.yaml 提示镜像被阻止就说明成功了。
...