一、kubernetes集群安全架构
用户使用kubectl、客户机或通过REST请求访问API。可以授权用户和Kubernetes服务帐户进行API访问。当一个请求到达API时,它会经历几个阶段,如下图所示:
1.访问K8S集群的资源需要过三关:认证、鉴权、准入控制;
2.普通用户若要安全访问集群API Server,往往需要证书、Token或者用户名+密码;
3.Pod访问,需要ServiceAccountK8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过API Server配置来启用插件。
- 1. Authentication
- 2. Authorization
- 3. Admission Contro
二、认证
API Server处理请求的过程中,认证插件负责鉴定⽤户⾝份,授权插件⽤于操作权限许可鉴别,⽽准⼊控制则⽤于在资源对象的创建、删除、更新或连接(proxy)操作时实现更精细的许可检查。Kubernetes使⽤⾝份验证插件对API请求进⾏⾝份验证,⽀持的认证⽅式包括客户端证书、承载令牌(bearer tokens)、⾝份验证代理(authenticating proxy)或HTTP basic认证等。
下面我们基于客户端证书来做认证:
1.将apiserver的根证书(ca.pem,ca-key.pem,ca-config.json)放到同一个目录下执行以下脚本:
[root@master hejianlai]# cat rbac-user.sh cat > hejianlai-csr.json <<EOF { "CN": "hejianlai", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing" } ] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes hejianlai-csr.json | cfssljson -bare hejianlai kubectl config set-cluster kubernetes --certificate-authority=ca.pem --embed-certs=true --server=https://172.31.182.140:6443 #Master ip --kubeconfig=hejianlai-kubeconfig kubectl config set-credentials hejianlai --client-key=hejianlai-key.pem --client-certificate=hejianlai.pem --embed-certs=true --kubeconfig=hejianlai-kubeconfig kubectl config set-context default --cluster=kubernetes --user=hejianlai --kubeconfig=hejianlai-kubeconfig kubectl config use-context default --kubeconfig=hejianlai-kubeconfig
三、RBAC授权
官方地址:https://kubernetes.io/docs/reference/access-authn-authz/rbac/
RBAC是⼀种操作授权机制,⽤于界定“谁”(subject)能够或不能够“操作”(verb)哪个或哪类“对象”(object)。动作的发出者即“主体”,通常以“账号”为载体,它既可以是常规⽤户(User Account),也可以是服务账号(Service Account)。“操作”(verb)⽤于表明要执⾏的具体操作,包括创建、删除、修改和查看等,对应于kubectl来说,它通常由create、apply、delete、update、patch、edit和get等⼦命令来给出。⽽“客体”则是指操作施加于的⽬标实体,对Kubernetes API来说主要是指各类的资源对象以及⾮资源型URL。
Kubernetes 使用 API 服务器授权 API 请求。它根据所有策略评估所有请求属性来决定允许或拒绝请求。 一个API请求的所有部分必须被某些策略允许才能继续。这意味着默认情况下拒绝权限。
(尽管 Kubernetes 使用 API 服务器,但是依赖于特定种类对象的特定字段的访问控制和策略由准入控制器处理。)
配置多个授权模块时,将按顺序检查每个模块。 如果任何授权模块批准或拒绝请求,则立即返回该决定,并且不会与其他授权模块协商。 如果所有模块对请求没有意见,则拒绝该请求。一个拒绝响应返回 HTTP 状态代码 403 。
Kubernetes仅审查以下API请求属性:
- user - 身份验证期间提供的
user
字符串。 - group - 经过身份验证的用户所属的组名列表。
- extra - 由身份验证层提供的任意字符串键到字符串值的映射。
- API - 指示请求是否针对 API 资源。
- Request path - 各种非资源端点的路径,如
/api
或/healthz
。 - API request verb - API 动词
get
,list
,create
,update
,patch
,watch
,proxy
,redirect
,delete
和deletecollection
用于资源请求。要确定资源API端点的请求动词,请参阅确定请求动词。 - HTTP request verb - HTTP 动词
get
,post
,put
和delete
用于非资源请求。 - Resource - 正在访问的资源的 ID 或名称(仅限资源请求) - 对于使用
get
,update
,patch
和delete
动词的资源请求,您必须提供资源名称。 - Subresource - 正在访问的子资源(仅限资源请求)。
- Namespace - 正在访问的对象的名称空间(仅适用于命名空间资源请求)。
- API group - 正在访问的 API 组(仅限资源请求)。空字符串表示核心API组。
1、创建role其权限只有简单的查看pod,我这里指定命名空间pci
[root@master rbac]# cat role.yaml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: pci name: pod-reader rules: - apiGroups: [""] # "" indicates the core API group resources: ["pods"] verbs: ["get", "watch", "list"]
2.创建rolebinding 绑定用户
[root@master rbac]# cat role-binding.yaml kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: read-pods namespace: pci subjects: - kind: User name: hejianlai # Name is case sensitive apiGroup: rbac.authorization.k8s.io roleRef: kind: Role #this must be Role or ClusterRole name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to apiGroup: rbac.authorization.k8s.io
三、准入控制
Kubernetes系统通过三个独⽴的组件间的相互协作来实现服务账户的⾃动化,三个组件具体为:Service Account准⼊控制器、令牌控制器(token controller)和Service Account账户控制器。Service Account控制器负责为名称空间管理相应的资源,并确保每个名称空间中都存在⼀个名为“default”的Service Account对象。
[root@master hejianlai]# cat sa.yaml apiVersion: v1 kind: ServiceAccount metadata: name: pod-reader namespace: pci --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: sa-read-pods namespace: pci subjects: - kind: ServiceAccount name: pod-reader roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
这时我们可以看见在pci这个命名中间下有一个默认的defaul和刚创建的pod-reader
这时我们验证下权限是否有效:
上图我们可以看到除了该命名空间下除了pod可以访问,其他的权限都是被拒绝的。
通过查看这个pod-reader生成的token我们就可以访问:
kubectl describe secret pod-reader -n pci
记住这个token要复制到记事本里取消自动换行!!!
然后我们用这个token去访问UI时也是只能看到pci这个命名中间下的。