kubernetes API Server权限管理的示例分析

84次阅读
没有评论

共计 10658 个字符,预计需要花费 27 分钟才能阅读完成。

这篇文章主要介绍 kubernetes API Server 权限管理的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

API Server 权限管理应用                                
API Server 权限控制方式介绍

API Server 权限控制分为三种:Authentication(身份认证)、Authorization(授权)、AdmissionControl(准入控制)。

身份认证:

  当客户端向 Kubernetes 非只读端口发起 API 请求时,Kubernetes 通过三种方式来认证用户的合法性。kubernetes 中,验证用户是否有权限操作 api 的方式有三种:证书认证,token 认证,基本信息认证。

证书认证

  设置 apiserver 的启动参数:–client_ca_file=SOMEFILE,这个被引用的文件中包含的验证 client 的证书,如果被验证通过,那么这个验证记录中的主体对象将会作为请求的 username。

Token 认证

  设置 apiserver 的启动参数:–token_auth_file=SOMEFILE。token file 的格式包含三列:token,username,userid。当使用 token 作为验证方式时,在对 apiserver 的 http 请求中,增加 一个 Header 字段:Authorization,将它的值设置为:Bearer SOMETOKEN。

基本信息认证

  设置 apiserver 的启动参数:–basic_auth_file=SOMEFILE,如果更改了文件中的密码,只有重新启动 apiserver 使 其重新生效。其文件的基本格式包含三列:passwork,username,userid。当使用此作为认证方式时,在对 apiserver 的 http 请求中,增加一个 Header 字段:Authorization,将它的值设置为:Basic BASE64ENCODEDUSER:PASSWORD。

授权:

  在 Kubernetes 中,认证和授权是分开的,而且授权发生在认证完成之后,认证过程是检验发起 API 请求的用户是不是他所声称的那个人。而授权过程则 判断此用户是否有执行该 API 请求的权限,因此授权是以认证的结果作为基础的。Kubernetes 授权模块应用于所有对 APIServer 的 HTTP 访 问请求(只读端口除外),访问只读端口不需要认证和授权过程。APIServer 启动时默认将 authorization_mode 设置为 AlwaysAllow 模式,即永远允许。

  Kubernetes 授权模块检查每个 HTTP 请求并提取请求上下文中的所需属性(例如:user,resource kind,namespace)与访问控制规则进行比较。任何一个 API 请求在被处理前都需要通过一个或多个访问控制规则的验证。

  目前 Kubernetes 支持并实现了以下的授权模式(authorization_mode),这些授权模式可以通过在 apiserver 启动时传入参数进行选择。

–authorization_mode=AlwaysDeny

–authorization_mode=AlwaysAllow

–authorization_mode=ABAC

AlwaysDeny 模式屏蔽所有的请求(一般用于测试)。AlwaysAllow 模式允许所有请求,默认 apiserver 启动时采用的便是 AlwaysAllow 模式)。ABAC(Attribute-Based Access Control,即基于属性的访问控制)模式则允许用户自定义授权访问控制规则。

ABAC 模式:

一个 API 请求中有 4 个属性被用于用户授权过程:

  UserName:String 类型,用于标识发起请求的用户。如果不进行认证、授权操作,则该字符串为空。

  ReadOnly:bool 类型,标识该请求是否仅进行只读操作(GET 就是只读操作)。

  Kind:String 类型,用于标识要访问的 Kubernetes 资源对象的类型。当访问例如 /api/v1beta1/pods 等 API endpoint 时,Kind 属性才非空,但访问其他 endpoint 时,例如 /version,/healthz 等,Kind 属性为空。

  Namespace:String 类型,用于标识要访问的 Kubernetes 资源对象所在的 namespace。

  对 ABAC 模式,在 apiserver 启动时除了需要传入 –authorization_mode=ABAC 选项外,还需要指定 –authorization_policy_file=SOME_FILENAME。authorization_policy_file 文件的每一 行都是一个 JSON 对象,该 JSON 对象是一个没有嵌套的 map 数据结构,代表一个访问控制规则对象。一个访问控制规则对象是一个有以下字段的 map:

    user:–token_auth_file 指定的 user 字符串。

  readonly:true 或 false,如果是 true 则表明该规则只应用于 GET 请求。

  kind:Kubernetes 内置资源对象类型,例如 pods、events 等。

  namespace:也可以缩写成 ns。

一个简单的访问控制规则文件如下所示,每一行定义一条规则。

{user : admin}

{user : alice , ns : projectCaribou}

{user : kubelet , readonly : true, kind : pods}

{user : kubelet , kind : events}

{user : bob , kind : pods , readonly : true, ns : projectCaribou}

注:缺省的字段与该字段类型的零值(空字符串,0,false 等)等价。

规则逐行说明如下。

  第一行表明,admin 可以做任何事情,不受 namespace,资源类型,请求类型的限制。

  第二行表明,alice 能够在 namespace projectCaribou 中做任何事情,不受资源类型,请求类型的限制。

  第三行表明,kubelet 有权限读任何一个 pod 的信息。

  第四行表明,kubelet 有权限读写任何一个 event。

  第五行表明,Bob 有权限读取在 namespace projectCaribou 中所有 pod 的信息。

  一个授权过程就是一个比较 API 请求中各属性与访问控制规则文件中对应的各字段是否匹配的一个过程。当 apiserver 接收到一个 API 请求时,该请求 的各属性就已经确定了,如果有一个属性未被设置,则 apiserver 将其设为该类型的空值(空字符串,0,false 等)。匹配规则很简单,如下所示。

如果 API 请求中的某个属性为空值,则规定该属性与访问控制规则文件中对应的字段匹配。

如果访问控制规则的某个字段为空值,则规定该字段与 API 请求的对应属性匹配。

如果 API 请求中的属性值非空且访问控制规则的某个字段值也非空,则将这两个值进行比较,如果相同则匹配,反之则不匹配。

API 请求的属性元组(tuple)会与访问控制规则文件中的所有规则逐条匹配,只要有一条匹配则表示匹配成功,如若不然,则授权失败。

准入控制:

  准入控制 admission controller 本质上为一段准入代码,在对 kubernetes api 的请求过程中,顺序为 先经过 认证 授权,然后执行准入操作,再对目标对象进行操作。这个准入代码在 apiserver 中,而且必须被编译到二进制文件中才能被执行。

  在对集群进行请求时,每个准入控制代码都按照一定顺序执行。如果有一个准入控制拒绝了此次请求,那么整个请求的结果将会立即返回,并提示用户相应的 error 信息。

  在某些情况下,为了适用于应用系统的配置,准入逻辑可能会改变目标对象。此外,准入逻辑也会改变请求操作的一部分相关资源。

作用

  在 kubernetes 中,一些高级特性正常运行的前提条件为,将一些准入模块处于 enable 状态。总结下,对于 kubernetes apiserver,如果不适当的配置准入控制模块,它就不能称作是一个完整的 server,某些功能也不会正常的生效。

开启方式

  在 kubernetes apiserver 中有一个参数:admission_control,他的值为一串用逗号连接的 有序的 准入模块列表,设置后,就可在对象被操作前执行一定顺序的准入模块调用。

模块功能

  AlwaysAdmit:允许所有请求

  AlwaysDeny:禁止所有请求,多用于测试环境。

  DenyExecOnPrivileged:它会拦截所有想在 privileged container 上执行命令的请求。如果自己的集群支持 privileged container,自己又希望限制用户在这些 privileged container 上执行命令,那么强烈推荐使用它。

  ServiceAccount:这个 plug-in 将 serviceAccounts 实现了自动化,如果想要使用 ServiceAccount 对象,那么强烈推荐使用它。

关于 serviceAccount 的描述如下:一个 serviceAccount 为运行在 pod 内的进程添加了相应的认证信息。当准入模块中开启了此插件(默认开启),那么当 pod 创建或修改时他会做一下事情:

      如果 pod 没有 serviceAccount 属性,将这个 pod 的 serviceAccount 属性设为“default”;

  确保 pod 使用 de serviceAccount 始终存在;

  如果 LimitSecretReferences 设置为 true,当这个 pod 引用了 Secret 对象却没引用 ServiceAccount 对象,弃置这个 pod;

  如果这个 pod 没有包含任何 ImagePullSecrets,则 serviceAccount 的 ImagePullSecrets 被添加给这个 pod;

      如果 MountServiceAccountToken 为 true,则将 pod 中的 container 添加一个 VolumeMount。

  SecurityContextDeny:这个插件将会将使用了 SecurityContext 的 pod 中定义的选项全部失效。SecurityContext 在 container 中定义了操作系统级别的安全设定(uid, gid, capabilities, SELinux 等等)。

  ResourceQuota:它会观察所有的请求,确保在 namespace 中 ResourceQuota 对象处列举的 container 没有任何异常。如果在 kubernetes 中使用了 ResourceQuota 对象,就必须使用这个插件来约束 container。推荐在 admission control 参数列表中,这个插件排最后一个。

  LimitRanger:他会观察所有的请求,确保没有违反已经定义好的约束条件,这些条件定义在 namespace 中 LimitRange 对象中。如果在 kubernetes 中使用 LimitRange 对象,则必须使用这个插件。

  NamespaceExists:它会观察所有的请求,如果请求尝试创建一个不存在的 namespace,则这个请求被拒绝。

推荐插件顺序

–admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount, ResourceQuota

验证流程

1.  API Server 的初始化参数中设置了一些与权限认证相关的默认属性:

安全监听端口:  SecurePort:        8443 读 / 写 权限,支持 x509 安全证书和 x509 私钥认证

非安全监听端口:InsecurePort:        8080 没有用户身份认证和授权,有读 / 写 权限

授权模式:    AuthorizationMode:  AlwaysAllow ,

准入控制插件:  AdmissionControl:  AlwaysAdmit

2. API Server 启动时可以设置与权限认证相关的参数:

–insecure_port                        自定义非安全监听端口

–secure_port                    自定义安全监听端口

–tls_cert_file  设置安全证书文件

–tls_private_key_file  设置私钥文件

–cert_dir  安全证书文件和私钥文件被设置时,此属性忽略。安全证书文件和私钥文件未设置时,apiserver 会自动为该

  端口绑定的公有 IP 地址分别生成一个自注册的证书文件和密钥并将它们存储在 /var/run/kubernetes 下

–service_account_key_file        服务账号文件,包含 x509 公私钥

–client_ca_file                                 client 证书文件

–token_auth_file                             token 文件

–basic_auth_file        基本信息认证文件

–authorization_mode          授权模式

–ahtuorization_policy_file        授权文件

–admission_control  准入控制模块列表

–admission_control_config_file     准入控制配置文件

3. 解析入参,进行认证信息提取:

公 私钥文件设置:查看 ServerAccountKeyFile 是否已指定,如果未指定,并且 TLSPrivateKeyFile 被指定,则判断 TLSPrivateKeyFile 中是否包含有效的 RSA key,包含时,将 TLSPrivateKeyFile 作为 ServerAccountKeyFile。

身份认证信息提取:从参 数设置的 CSV 文件中取出 username,userID,password(或者 token)封装成 map 结构,key 为 username,value 为三种属性的 struct。从 basicAuthFile, clientCAFile, tokenFile, serviceAccountKeyFile(serviceAccountLookup)中取 user 信息, 得到一个验证信息的 map 数组。

授 权信息提取:读取设置的授权文件,解析字符串,返回授权信息数组。(包含 username,group,resource,read only,namespace)Make the cluster Kinds be one API group (minions, bindings,events,endpoints)。The user Kinds are another (pods,services,replicationControllers,operations)。

准入控制插件:获取所有插件名,返回准入控制接口(执行所有插件)

4. 将身份认证信息、授权信息、准入控制插件作为 Master 的配置,New Master。

5. 请求认证:

调 apiserver 的 NewRequestAttributeGetter 方法,从请求中提取授权信息,调用 WithAuthorizationCheck 方法(授权验证)。

调 用 handler 的 NewRequestAuthenticator 方法,Request 中提取 authencate 信息, 调用 AuthenticateRequest 方法(对 client certificates,token,basic auth 分别有不同的验证方法)。

补充

  身份认证:

  token 认证,请求时,在请求头中加入 Authorization:bearer token 字符串。CSV 文件中,三列分别为 token,username,userid。当 CSV 中有与请求的 Authorization 匹配行时,认证成功。

  basic auth 认证,请求时,在请求头中加入 Authorization:basic base64 编码的 user:password 字符串。CSV 文件中,三列分别为 password,username,userid。当 CSV 文件中有与请求的 Ahtuorization 匹配行时,认证成功。

证书校验:

API Server 启动时,指定服务端数字证书和密钥(如果不指定,会在 server 启动时自动生成),指定客户端 ca 文件,server 启动时,会解析 ca 文 件,遍历其中的 cert,加入 certpool。在 Server 的 TLSConfig 中指定认证模式:目前使用的是 RequestClientCert(不强制认证,无认证时不拒绝连接,允许其他认证),此外还有其他认证模式 requireAndVerifyClientCert(强制校验)。使用 ListenAndServeTLS(将服务端数字证书和密钥作为参数)监听在 安全端口。

API Server 权限控制操作(暂时未加入 namespace)测试:

启动 server:指定 token 验证文件、授权方式、授权文件

./_output/local/bin/linux/amd64/canary-apiserver –logtostderr=true –log-dir=/tmp –v=4 –etcd_servers=http://127.0.0.1:4001 –insecure_bind_address=127.0.0.1 –insecure_port=8088 –secure_port=8442 –kubelet_port=10250 –service-cluster-ip-range=10.1.1.0/24 –allow_privileged=true –runtime-config= api/v1beta3=false –redis-addr=localhost:6379 –profiling=true –token_auth_file=token.csv –authorization_mode=ABAC –authorization_policy_file=abac.csv

Token 文件内容:

abcdef,hankai,123456

abcdefg,hk,123457

abcd,admin,1234

abc,hhh,111

授权文件内容:

{“user”:”admin”}

{“user”:”hankai”,”readonly”:true}

{“user”:”hhh”,”resource”:”apps”}

{“user”:”hk”,”readonly”:true,”resource”:”namespaces”}

验证:admin(有读写所有 resource 的权限)

  curl -X GET -H Content-Type: application/json -H Authorization: bearer abcd -k https://10.57.104.59:8442/api/v1/apps 

  curl -X GET -H Content-Type: application/json -H Authorization: bearer abcd -k https://10.57.104.59:8442/api/v1/namespaces 

  curl -X POST -H Content-Type: application/json -H Authorization: bearer abcd -d@ n1.json -k https://10.57.104.59:8442/api/v1/namespaces 

  curl -X POST -H Content-Type: application/json -H Authorization: bearer abcd -d@ app_demo1.json -k https://10.57.104.59:8442/api/v1/apps

验证 hankai (只有读权限 GET)

  curl -X POST -H Content-Type: application/json -H Authorization: bearer abcdef -d@ app_demo1.json -k https://10.57.104.59:8442/api/v1/apps   forbidden

  curl -X POST -H Content-Type: application/json -H Authorization: bearer abcdef -d@ n1.json -k https://10.57.104.59:8442/api/v1/namespaces    forbidden

  curl -X GET -H Content-Type: application/json -H Authorization: bearer abcdef   -k https://10.57.104.59:8442/api/v1/namespaces

  curl -X GET -H Content-Type: application/json -H Authorization: bearer abcdef   -k https://10.57.104.59:8442/api/v1/apps

验证 hk (只有对 namespaces 的 GET 权)

  curl -X GET -H Content-Type: application/json -H Authorization: bearer abcdefg   -k https://10.57.104.59:8442/api/v1/apps 

  forbidden 

  curl -X GET -H Content-Type: application/json -H Authorization: bearer abcdefg   -k https://10.57.104.59:8442/api/v1/namespaces

  curl -X POST -H Content-Type: application/json -H Authorization: bearer abcdefg -d@ n1.json -k https://10.57.104.59:8442/api/v1/namespaces   forbidden

  curl -X POST -H Content-Type: application/json -H Authorization: bearer abcdefg -d@ app_demo1.json -k https://10.57.104.59:8442/api/v1/apps                      forbidden

验证 hhh(拥有对 apps 的读写权)

  curl -X POST -H Content-Type: application/json -H Authorization: bearer abc -d@ app_demo1.json -k https://10.57.104.59:8442/api/v1/apps

  curl -X GET -H Content-Type: application/json -H Authorization: bearer abc   -k https://10.57.104.59:8442/api/v1/apps

  curl -X GET -H Content-Type: application/json -H Authorization: bearer abc   -k https://10.57.104.59:8442/api/v1/namespaces 

          forbidden

  curl -X POST -H Content-Type: application/json -H Authorization: bearer abc -d@ n1.json -k https://10.57.104.59:8442/api/v1/namespaces 

  forbidden

  注:后续只需要在 abac.csv 文件的每列中,指定 namespace,就可以实现 user 对指定 namespace 的操作权限。

新增:TSL 客户端证书认证

  使用自生成证书测试:使用 openssl 生成 server.crt,server.key,ca.key,ca.crt。Server 启动时,传入 –tls_cert_file=server.crt –tls_private_key_file=server.key –client_ca_file=ca.crt

  ./_output/local/bin/linux/amd64/canary-apiserver –logtostderr=true –log-dir=/tmp –v=4 –etcd_servers=http://127.0.0.1:4001 –insecure_bind_address=7.0.0.1 –insecure_port=8088 –secure_port=8442 –kubelet_port=10250 –service-cluster-ip-range=10.1.1.0/24 –allow_privileged=true –runtime-config= api/v1beta3=false –redis-addr=localhost:6379 –profiling=true –tls_cert_file=server.crt –tls_private_key_file=server.key –client_ca_file=ca.crt  –token_auth_file=token.csv –authorization_mode=ABAC –authorization_policy_file=abac.csv

  请求时,通过 -cacert 指定客户端证书(可以通过修改 opnessl 的配置文件指定客户端证书的路径,或者浏览器中导入客户端证书)curl -X GET –cacert ca.crt -H Content-Type: application/json -H Authorization: bearer abcd -k https://10.57.104.59:8442/api/v1/apps 即可实现认证。

以上是“kubernetes API Server 权限管理的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注丸趣 TV 行业资讯频道!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计10658字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)