Kubernetes指南:集群安全机制
集群安全机制
Authentication、Authorization、Admission Control、Secret、Service Account等
安全性目标:
1.容器与其所在宿主机的隔离;
2.限制容器给基础设施及其他容器带来消极影响的能力;
3.最小权限原则;
4.明确组件间边界的划分
5.划分普通用户和管理员角色;
6.允许将管理员权限赋给普通用户;
7.允许拥有Secret数据的应用在集群中运行;
API Server认证
Kubernetes提供了3种级别的客户端身份认证方式:
1.HTTPS证书认证;
2.HTTP Token
3.HTTP Base:用户名+密码
HTTPS认证原理
CA是PKI(Public Key Infrastructure,PKI,公开密钥基础设施)系统中通信双方都信任的实体,被称为可信第三方(TTP, Trusted Third Party)
HTTP Token
- H “Authorization: Bearer xxxxxx” …
HTTP Base
-H ‘Authorization: Basic xxxxxx’
1.6版本的几种认证方式
客户端认证
客户端证书认证叫作TLS双向认证,也就是服务器客户端互相验证证书的正确性,在都正确的情况下协调通信加密方案。
静态Token文件
用token唯一标识请求者,只要apiserver存在该token,则认为认证通过,但是如果需要新增Token,则需要重启kube-apiserver组件,实际效果不是很好。
API Server授权
授予不同的用户不同的访问权限
目前支持的授权策略: (在API-server启动参数–authorization-mode中设置)
-
AlwaysDeny:一般用于测试
-
AlwaysAllow:默认配置
-
ABAC:Attribute-Based Access Control,基于属性的访问控制
四个基本属性:
1.用户名;
2.是否只读请求;
3.被访问的是哪一类资源;
4.被访问对象所属的Namespace 启用ABAC模式时,需要指定授权文件的路径和名字(–authorization_policy_file),授权文件的每一行都是一个map类型的JSON对象:
{“user”:”Kubelet”, “resource”: “pods”, “readonly”: true, “ns”: “my_namespace”}
-
RBAC:Role-Based Access Control,基于角色控制
-
Webhook:通过调用外部REST服务对用户进行授权;
-
Node:是一种专用模式,用于对kubelet发出的请求进行访问控制;
API Server在接收到请求后,会读取该请求中的数据,生成一个访问策略对象;
然后将这个访问策略对象和授权策略文件中的所有访问策略对象逐条匹配,如果至少有一个策略对象被匹配, 则该请求被鉴权通过,否则终止API调用流程,并返回客户端的错误调用码;
ABAC授权模式
ABAC,Attribute Based Access Control,基于属性的访问控制
API Server启用ABAC模式时,需要指定授权策略文件的路径和名称(–authorization-policy-file=SOME_FILENAME), 授权策略文件里的每一行都以一个Map类型的JSON对象进行设置,这被称为“访问策略对象”;
常见ABAC授权示例
允许用户alice对所有资源做任何修改:
{
"apiVersion":"abac.authorization.kubernetes.io/v1beta1",
"kind":"Policy",
"spec":{
"user":"alice",
"namespace":"*",
"resource":"*",
"apiGroup":"*"
}
}
kubelet可以读取任意Pod:
{
"apiVersion":"abac.authorization.kubernetes.io/v1beta1",
"kind":"Policy",
"spec":{
"user":"kubelet",
"namespace":"*",
"resource":"pods",
"readonly":true
}
}
任何用户都可以对非资源类路径进行只读请求:
{
"apiVersion":"abac.authorization.kubernetes.io/v1beta1",
"kind":"Policy",
"spec":{
"group":"system:authenticated",
"nonResourcePath":"*",
"readonly":true
}
}
{
"apiVersion":"abac.authorization.kubernetes.io/v1beta1",
"kind":"Policy",
"spec":{
"group":"system:unauthenticated",
"nonResourcePath":"*",
"readonly":true
}
}
ABAC授权算法
在API Server收到请求之后, 首先识别出请求携带的策略对象的属性, 然后根据在策略文件中定义的策略对这些属性进行逐条匹配,以判定是否允许授权。 如果有至少一条匹配成功,那么这个请求就通过了授权(不过还是可能在后续其他授权校验中失败);
将group属性设置为system:authenticated:允许所有认证用户做某件事;
group属性设 置为system:unauthenticated:允许所有未认证用户做某件事;
要允许一个用户做任何事,将策略的apiGroup、namespace、 resource和nonResourcePath属性设置为“*”即可;
对Service Account进行授权
Service Account会自动生成一个ABAC用户名(username),用户名按照以下命名规则生成:
system:serviceaccount:
创建新的命名空间时,会产生一个如下名称的Service Account:
system:serviceaccount:
如果希望kube-system命名空间中的Service Account “default”具有全部权限, 需要在策略文件中加入如下内容:
{
"apiVersion":"abac.authorization.kubernetes.io/v1beta1",
"kind":"Policy",
"spec":{
"user": "system:serviceaccount:kube-system:default",
"namespace":"*",
"apiGroup":"*",
"resource":"*"
}
}
Webhook授权模式
Webhook定义了一个HTTP回调接口,实现Webhook的应用会在指定事件发生时, 向一个URL地址发送(POST)通知信息; 启用 Webhook授权模式后,Kubernetes会调用外部REST服务对用户进行授权;
RBAC授权模式
RBAC,Role-Based Access Control,基于角色的访问控制在Kubernetes的1.5版本中引入, 在1.6版本时升级为Beta版本,在1.8版本时升级为GA; kubeadm安装方式的默认选项;
优势: 对集群中的资源和非资源权限均有完整的覆盖;
整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubectl或API进行操作;
可以在运行时进行调整,无须重新启动API Server;
RBAC的API资源对象说明
1.Role
一个角色就是一组权限的集合,这里的权限都是许可形式的,不存在拒绝的规则;
例如:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
2.ClusterRole
集群角色除了具有和角色一致的命名空间内资源的管理能力,因其集群级别的范围, 还可以用于一些特殊元素的授权: 集群范围的资源,例如Node;
非资源型的路径,例如“/healthz”;
包含全部命名空间的资源,例如pods(用于kubectl get pods – all-namespaces这样的操作授权)
如下集群角色可以让用户有权访问任意一个或所有命名空间的secrets:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
# metadata:
# Cluster不受限于命名空间,所以无需设置namaspace
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
3.RoleBinding
角色绑定或集群角色绑定用来把一个角色绑定到一个目标上, 绑定目标可以是User(用户)、Group(组)或者Service Account。 使用 RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权;
在default命名空间中把pod-reader角色授予用户jane:
kind: Rolebinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
4.ClusterRoleBinding
集群角色绑定中的角色只能是集群角色,用于进行集群级别或者对所有命名空间都生效的授权;
允许manager组的用户读取任意namespace中的secret:
kind: ClusterRolebinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secret-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
Admission Control准入控制
发送给API Server的任何请求都需要通过列表中每个准入控制器的检查;
-
AlwaysAdmit:已弃用,允许所有请求;
-
AlwaysPullImages:在启动容器之前总是尝试重新下载镜像;
-
AlwaysDeny:已弃用,禁止所有请求,用于测试;
-
DenyExecOnPrivileged:已弃用,拦截所有想在Privileged Container上执行命令的请求
-
ServiceAccount:这个插件将ServiceAccount实现了自动化,如果想使用ServiceAccount对象,推荐使用它;
-
SecurityContextDeny:这个插件将在Pod中定义的SecurityContext选项全部失效;
-
ResourceQuota:用于资源配额管理目的,作用于Namespace; 推荐在Admission Control参数列表中将这个插件排最后一个,以免可能被其他插件拒绝的Pod被过早分配资源;
-
LimitRanger:监控进入的请求,确保请求的内容符合在Namespace中定义的LimitRange对象里的资源限制;
配置: –admission-control=xxxxxxx,xxx
新版本增加:
DefaultStorageClass:会关注PersistentVolumeClaim资源对象的创建, 如果其中没有包含任何针对特定Storage class的请求,则为其指派指定的Storage class;
DefaultTolerationSeconds:针对没有设置容忍node.kubernetes.io/not-ready:NoExecute或者 node.alpha.kubernetes.io/unreachable:NoExecute的Pod,设置5min的默认容忍时间;
DenyEscalatingExec:拦截所有exec和attach到具有特权的Pod上的请求; 如果集群支持运行有escalated privilege权限的容器, 又希望限制用户在这些容器内执行命令的情况下,可以使用;
EventReateLimit:Alpha版本,用于应对事件密集情况下对API Server造成的洪水攻击;
ExtendedResourceToleration:如果运维人员要创建带有特定资源(例如GPU、FPGA等)的独立节点, 则可能会对节点进行Taint处理来进行特别配置。 该控制器能够自动为申请这些特别资源的Pod加入Toleration定义,无须人工干预;
Service Account
提供给运行在Pod里的进程用的身份证明;
describe serviceaccounts
kubectl describe serviceaccounts
Name: default
Namespace: testing
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-xxxxx
Tokens: default-token-xxxxx
Events: <none>
describe secrets token
kubectl -n testing describe secrets default-token-xxxxx
Name: default-token-xxxxx
Namespace: default-token-xxxxx
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: xxxxxxx
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 6 bytes
token: xxxxxeyJhbGciOiJSUxxxxxgq1hP1AdPL7ZQbl38aHotmPXjk77_JnTlDu7lS9EHy37Gsod1Q-Q
每个namespace下有一个名为default的默认的Service Account对象,这个Service Account里有一个名为token的 可以当作Volume一样被Mount到Pod的Secret;
Pod启动时,这个Secret会自动被Mount到Pod指定目录下,用来协助完成Pod中的进程访问API Server时的身份鉴权;
secret
更新secret的流程和部署一个新的image是一样的
PodSecurityPolicy–Pod的安全策略
Pod 安全策略使得对 Pod 创建和更新进行细粒度的权限控制成为可能。
1.4版本开始引入了PodSecurityPolicy资源对象对Pod的安全策略进行管理;
1.10版本中升级为Beta版,PodSecurityPolicy资源对象的API版本为extensions/v1beta1;
1.14版本时趋于成熟;
1.16版本时弃用extensions/v1beta1;
PodSecurityPolicy的工作机制
启用PodSecurityPolicy机制: 设置kube-apiserver服务的启动参数–enable-admission-plugins=PodSecurityPolicy;
开启PodSecurityPolicy准入控制器后, Kubernetes默认不允许创建任何Pod, 需要创建PodSecurityPolicy策略和相应的RBAC授权策略 (Authorizing Policies), Pod才能创建成功;
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp-test
spec:
privileged: false
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
PodSecurityPolicy配置
安全策略类型:
1.特权模式相关配置
privileged:是否允许Pod以特权模式运行;
2.宿主机资源相关配置
hostPID:是否允许Pod共享宿主机的进程空间; hostIPC:是否允许Pod共享宿主机的IPC命名空间; hostNetwork:是否允许Pod使用宿主机网络的命名空间。 hostPorts:是否允许Pod使用宿主机的端口号,可以通过hostPortRange字段设置允许使用的端口号范围,以[min, max]设置最小端口号和最大端口号; Volumes:允许Pod使用的存储卷Volume类型,设置为“*”表 示允许使用任意Volume类型; AllowedHostPaths:允许Pod使用宿主机的hostPath路径名称,可以通过pathPrefix字段设置路径的前缀,并可以设置是否为只读属性; FSGroup:设置允许访问某些Volume的Group ID范围,可以将规则(rule字段)设置为MustRunAs、MayRunAs或RunAsAny; ReadOnlyRootFilesystem:要求容器运行的根文件系统(root filesystem)必须是只读的; allowedFlexVolumes:对于类型为flexVolume的存储卷,设置允许使用的驱动类型;
3.用户和组相关配置
RunAsUser:设置运行容器的用户ID(User ID)范围,规则字段(rule)的值可以被设置为MustRunAs、MustRunAsNonRoot或 RunAsAny;
RunAsGroup:设置运行容器的Group ID范围,规则字段的值可以被设置为MustRunAs、MustRunAsNonRoot或RunAsAny;
SupplementalGroups:设置容器可以额外添加的Group ID范围,可以将规则(rule字段)设置为MustRunAs、MayRunAs或 RunAsAny;
4.提升权限相关配置
AllowPrivilegeEscalation:设置容器内的子进程是否可以提升权限,通常在设置非root用户(MustRunAsNonRoot)时进行设置
DefaultAllowPrivilegeEscalation:设置AllowPrivilegeEscalation 的默认值,设置为disallow时, 管理员还可以显式设置 AllowPrivilegeEscalation来指定是否允许提升权限;
5.Linux能力相关配置
AllowedCapabilities:设置容器可以使用的Linux能力列表, 设置为“*”表示允许使用Linux的所有能力(如NET_ADMIN、SYS_TIME等);
RequiredDropCapabilities:设置不允许容器使用的Linux能力列表;
DefaultAddCapabilities:设置默认为容器添加的Linux能力列表,例如SYS_TIME等;
6.SELinux相关配置
seLinux:设置SELinux参数,可以将规则字段(rule)的值设置为MustRunAs或RunAsAny;
7.其他Linux相关配置
AllowedProcMountTypes:设置允许的ProcMountTypes类型列表, 可以设置allowedProcMountTypes或DefaultProcMount;
AppArmor:设置对容器可执行程序的访问控制权限;
Seccomp:设置允许容器使用的系统调用(System Calls)的profile;
Sysctl:设置允许调整的内核参数;
Pod的安全设置
在系统管理员对Kubernetes集群中设置了PodSecurityPolicy策略之后, 系统将对Pod和Container级别的安全设置进行校验, 对于不满足PodSecurityPolicy安全策略的Pod,系统将拒绝创建;
Pod和容器的安全策略可以在Pod或Container的securityContext字段中进行设置;
Pod级别安全策略类型: runAsUser:容器内运行程序的用户ID;
runAsGroup:容器内运行程序的用户组ID;
runAsNonRoot:是否必须以非root用户运行程序;
fsGroup:SELinux相关设置;
seLinuxOptions:SELinux相关设置;
supplementalGroups:允许容器使用的其他用户组ID;
sysctls:设置允许调整的内核参数;
apiVersion: v1
kind: Pod
metadata:
name: security-context-pod
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: xxx
image: xxxx
Container级别安全策略类型: runAsUser:容器内运行程序的用户ID;
unAsGroup:容器内运行程序的用户组ID;
runAsNonRoot:是否必须以非root用户运行程序;
privileged:是否以特权模式运行;
allowPrivilegeEscalation:是否允许提升权限;
readOnlyRootFilesystem:根文件系统是否为只读属性;
capabilities:Linux能力列表;
seLinuxOptions:SELinux相关设置;
apiVersion: v1
kind: Pod
metadata:
name: security-context-container
spec:
securityContext:
runAsUser: 1000
containers:
- name: xxx
image: xxxx
securityContext:
runAsUser: 2000
allowPrivilegeEscalation: false
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
refs
《Kubernetes:The Definitive Guide》
https://kubernetes.io/zh/docs/concepts/policy/pod-security-policy/
Mem
2021.04.01更新