kubernetes系列三:概念梳理——认证和授权

文章目录

  • 一、集群里面相关的策略
    • 1、Kubernetes API的访问控制
      • (1)传输安全
      • (2)认证
      • (4)准入控制
      • (5)API Server 的端口和IP
    • 2、身份认证
      • (1)k8s的用户
      • (2)认证策略
        • a、X509 客户端证书
        • b、静态 Token 文件
        • c、Bootstrap Token
        • d、静态密码文件
        • e、Service Account Token
        • f、openid-connect-token
        • g、Webhook Token 认证
        • h、认证代理
      • (3)User impersonation(用户扮演)
      • (4)client-go credential plugins
      • (5)老版本的文档中的创建证书
        • a、部署脚本
        • b、esayrsa
        • c、openssl
    • 3、授权
      • (1)权限认证(概述)
        • a、请求属性
        • b、确定请求动词
        • c、授权模块
        • d、检查API访问(没有明白)
        • e、为您的授权模块使用标志
      • (2)serviceAccount概念
        • a、用户账号 vs 服务账号
        • b、服务账号自动化
        • c、服务账号准入控制器
        • d、令牌控制器
        • e、创建额外的api token
      • (3)serviceAccount管理
        • a、使用默认的 Service Account 访问 API server
        • b、使用多个Service Account
        • c、手动创建 service account 的 API token
        • d、为 service account 添加 ImagePullSecret
      • (4)ABAC
        • a、策略文件格式
        • b、授权算法
        • c、Kubectl
        • d、例子
      • (5)RBAC
        • a、API概述
          • Ⅰ、Role与ClusterRole
          • Ⅱ、RoleBinding与ClusterRoleBinding
          • Ⅲ、对资源的引用
          • Ⅳ、对角色绑定主体(Subject)的引用
        • b、默认角色与默认角色绑定
        • c、初始化与预防权限升级
        • d、一些命令行工具
        • e、服务账户(serviceAccount)权限
        • f、宽泛的RBAC权限
    • 4、准入控制
      • (1)准入控制详细
      • (2)推荐的准入控制配置:

一、集群里面相关的策略

大量内容参考了https://k8smeetup.github.io
基于1.11

1、Kubernetes API的访问控制

    用户可以通过kubectl命令, 客户端库, 或者发送REST请求来访问API 。kubernetes用户和服务账号都可以用于API访问时的授权。 当请求到达API时, 它会经历几个阶段,如下图所示:

(1)传输安全

    在一个典型的 Kubernetes集群里, API 的侦听端口是443, TLS连接会被建立。API server会提供一个证书。 这个证书是自签名的, 因此在$USER/.kube/config路径下会包含API server证书的根证书,你可以指定这个证书用来替换系统默认的根证书。当你使用kube-up.sh来创建集群时,这个证书会自动写入到$USER/.kube/config目录下。如果集群有多个用户, 那么集群创建者需要和其它用户共享这个证书。

(2)认证

  • TLS一旦建立连接, HTTP请求就会转到认证这一步, 即图示中标注的步骤1. 集群创建脚本或者集群的管理者通过配置API server可以加载一个或多个认证模块。 认证模块的更多描述信息参考:https://k8smeetup.github.io/docs/admin/authentication/。
  • 认证这一步骤的输入就是整个HTTP的请求, 然而,整个认证步骤也是只是检查了HTTP的header信息,和/或者 客户端证书。 认证模块包括客户端证书, 密码,明文token, 初始token, 和JWT token(用于服务账号)。

###(3)授权

  • 当一个请求被验证来自指定用户时, 这个请求紧接着必须被授权, 即如图示中的步骤2所示. 一个请求必须包含请求者的用户名, 请求的动作, 影响动作的对象。 如果有存在的策略声明这个用户有权限完成这个动作,那么该请求就会被授权。

(4)准入控制

  • 准入控制模块是可以修改或者拒绝请求的模块。 作为授权模块的补充, 准入控制可以访问一个正在被创建或更新的对象的内容, 它们在对象创建, 删除,更新, 连接(代理)期间起作用,在读取对象时它们不起作用。
  • 可以配置多个准入控制器, 每个准入控制器会按照顺序被调用。
  • 跟认证和授权模块不同的时,如果任何一个准入控制模块拒绝了请求, 那么请求就会立马被拒绝掉。 除了拒绝对象之外, 准入控制器还可以为字段设置复杂的默认值。
  • 参考:https://k8smeetup.github.io/docs/admin/admission-controllers/,使用准入控制插件

(5)API Server 的端口和IP

  • 本地端口:
    • 用于测试或者启动集群, 还有master 节点的其它组件跟API的交互
    • 没有TLS
    • 默认的侦听端口是8080,可以通过参数 --insecure-port 指定别的端口
    • 默认绑定的IP是localhost, 可以通过参数 --insecure-bind-address指定别的地址
    • 请求会绕过认证和授权模块
    • 请求会经过准入控制模块处理
    • 通过对主机进行访问控制保护接口
  • 安全端口:
    • 按需启用
    • 使用 TLS. 通过 --tls-cert-file参数指定证书路径, --tls-private-key-file 参数指定证书的私钥
    • 默认侦听6443端口, 可以通过--secure-port指定别的端口
    • 默认IP绑定在第一个非localhost的网络接口, 可以通过--bind-address指定IP地址
    • 请求会经过认证和授权模块的处理
    • 请求会经过准入控制模块的处理
    • 认证和授权模块会运行 如果在谷歌计算引擎平台(GCE)或者其他一些云提供商上用kube-up.sh创建集群的话, API Server会侦听443端口。 在GCE上, 默认会开放防火墙策略允许从外部通过HTTPS访问集群的API. 其它云供应商的策略不尽相同。

2、身份认证

(1)k8s的用户

  • 由 Kubernetes 管理的 service account
    • service account 是由 Kubernetes API 管理的帐户。它们都绑定到了特定的 namespace,并由 API server 自动创建,或者通过 API 调用手动创建。Service account 关联了一套凭证,存储在 Secret,这些凭证同时被挂载到 pod 中,从而允许 pod 与 kubernetes API 之间的调用。
  • 普通用户
    • 普通用户被假定为由外部独立服务管理。管理员分发私钥,用户存储(如 Keystone 或 Google 帐户),甚至包含用户名和密码列表的文件。在这方面,Kubernetes 没有代表普通用户帐户的对象。无法通过 API 调用的方式向集群中添加普通用户。
  • 匿名用户
    • API 请求被绑定到普通用户或 serivce account 上,或者作为匿名请求对待。这意味着集群内部或外部的每个进程,无论从在工作站上输入 kubectl 的人类用户到节点上的 kubelet,到控制平面的成员,都必须在向 API Server 发出请求时进行身份验证,或者被视为匿名用户

(2)认证策略

  • Kubernetes 使用客户端证书、bearer token、身份验证代理或者 HTTP 基本身份验证等身份认证插件来对 API 请求进行身份验证。
  • 当有 HTTP 请求发送给 API server 时,插件会尝试将以下属性关联到请求上:
    • 用户名:标识最终用户的字符串。常用值可能是 kube-admin 或 [email protected]
    • UID:标识最终用户的字符串,比用户名更加一致且唯一。
    • 组:一组将用户用常用组关联的字符串。
    • 额外字段:包含其他有用认证信息的字符串列表的映射。
  • 您可以一次性启用多种身份验证方式。通常使用至少以下两种认证方式:
    • 服务帐户的 service account token
    • 至少一种其他的用户认证的方式
  • 当启用了多个认证模块时,第一个认证模块成功认证后将短路请求,不会进行第二个模块的认证。API server 不会保证认证的顺序。
  • 与其他身份验证协议(LDAP、SAML、Kerberos、x509 方案等)的集成可以使用本文后面的 身份验证代理 或 身份验证 webhook 来实现

a、X509 客户端证书

  • 通过将 --client-ca-file=SOMEFILE 选项传递给 API server 来启用客户端证书认证。引用的文件必须包含一个或多个证书颁发机构,用于验证提交给 API server 的客户端证书。如果客户端证书已提交并验证,则使 subject 的 common name(CN)作为请求的用户名。
  • 从 Kubernetes 1.4开始,客户端证书还可以使用证书的 orgnization 字段来指示用户的组成员身份。要为用户包含多个组成员身份,请在证书中包含多个组织字段。
  • eg:
    • openssl req -new -key jbeda.pem -out jbeda-csr.pem -subj "/CN=jbeda/O=app1/O=app2"
    • 这将为一个用户名为”jbeda“的 CSR,属于两个组“app1”和“app2”
看看用kubeadm创建的集群中的apiServer启动参数:
[root@server .kube]# ps -ef |grep -v grep |grep -i

kube-apiserver --authorization-mode=Node,RBAC \
--advertise-address=10.40.2.230 \
--allow-privileged=true \
--client-ca-file=/etc/kubernetes/pki/ca.crt \
--disable-admission-plugins=PersistentVolumeLabel \
--enable-admission-plugins=NodeRestriction \
--enable-bootstrap-token-auth=true \
--etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt \
--etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt \
--etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key \
--etcd-servers=https://127.0.0.1:2379 \
--insecure-port=0 \
--kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt \
--kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key \
--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \
--proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt \
--proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key \
--requestheader-allowed-names=front-proxy-client \
--requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--secure-port=6443 \
--service-account-key-file=/etc/kubernetes/pki/sa.pub \
--service-cluster-ip-range=10.96.0.0/12 \
--tls-cert-file=/etc/kubernetes/pki/apiserver.crt \
--tls-private-key-file=/etc/kubernetes/pki/apiserver.key

b、静态 Token 文件

  • 当在命令行上指定 --token-auth-file=SOMEFILE 选项时,API server 从文件读取 bearer token。
  • 目前,token 会无限期地持续下去,并且不重新启动 API server 的话就无法更改令牌列表。
  • token 文件是一个 csv 文件,每行至少包含三列:token、用户名、用户 uid,其次是可选的组名。请注意,如果您有多个组,则该列必须使用双引号。
    token,user,uid,"group1,group2,group3"
  • 当通过http客户端访问apiServer时,使用bearer token,API server 期望 Authorization header 中包含Bearer TOKEN的值。Bearer token 必须是一个字符串序列,只需使用 HTTP 的编码和引用功能就可以将其放入到 HTTP header 中。
    • eg: Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269

c、Bootstrap Token

  • 使用kubeadm初始化集群时可以使用
  • 更多信息参考官网:https://kubernetes.io/docs/reference/access-authn-authz/authentication/

d、静态密码文件

  • 通过将 --basic-auth-file=SOMEFILE 选项传递给 API server 来启用基本身份验证。
  • 目前,基本身份验证凭证将无限期地保留,并且密码在不重新启动API服务器的情况下无法更改。
  • 基本身份认证是一个 csv 文件,至少包含3列:密码、用户名和用户 ID。在 Kubernetes 1.6 和更高版本中,可以指定包含以逗号分隔的组名称的可选第四列。如果您有多个组,则必须将第四列值用双引号(")括起来
    password,user,uid,"group1,group2,group3"
  • 当使用来自 HTTP 客户端的基本身份验证时,API server 需要 Authorization header 中包含 Basic BASE64ENCODED(USER:PASSWORD) 的值

e、Service Account Token

  • Service account 是使用签名的 bearer token 来验证请求的自动启用的验证器。该插件包括两个可选的标志:
    • --service-account-key-file 一个包含签名 bearer token 的 PEM 编码文件。如果未指定,将使用 API server 的 TLS 私钥。
    • --service-account-lookup 如果启用,从 API 中删除掉的 token 将被撤销。
  • Service account bearer token 在集群外使用也是完全有效的,并且可以用于为希望与 Kubernetes API通信的长期运行的作业创建身份。
  • Service account 验证时用户名: system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT),被指定到组 system:serviceaccountssystem:serviceaccounts:(NAMESPACE)
  • 注意:
    • 由于 service account 的 token 存储在 secret 中,所以具有对这些 secret 的读取权限的任何用户都能以 service account 的身份进行验证。授予 service account 权限和读取 secret 功能时要谨慎。

f、openid-connect-token

  • 参考官网

g、Webhook Token 认证

  • 参考官网

h、认证代理

  • 可以配置 API server 从请求 header 的值中识别用户,例如 X-Remote-User。这样的设计是用来与请求 header 值的验证代理结合使用。
    • --requestheader-username-headers 必需,大小写敏感。按 header 名称和顺序检查用户标识。包含值的第一个 header 将被作为用户名。
    • --requestheader-group-headers 1.6 以上版本。可选。大小写敏感。建议为 “X-Remote-Group”。按 header 名称和顺序检查用户组。所有指定的 header 中的所有值都将作为组名。
    • --requestheader-extra-headers-prefix 1.6 以上版本。可选,大小写敏感。建议为 “X-Remote-Extra-”。标题前缀可用于查找有关用户的额外信息(通常由配置的授权插件使用)。以任何指定的前缀开头的 header 都会删除前缀,header 名称的其余部分将成为额外的键值,而 header 值则是额外的值。
  • 例如:
    • 配置:
      --requestheader-username-headers=X-Remote-User
      --requestheader-group-headers=X-Remote-Group
      --requestheader-extra-headers-prefix=X-Remote-Extra-
      
    • 请求
      GET / HTTP/1.1
      X-Remote-User: fido
      X-Remote-Group: dogs
      X-Remote-Group: dachshunds
      X-Remote-Extra-Scopes: openid
      X-Remote-Extra-Scopes: profile
      
    • 产生用户:
      name: fido
      groups:
      - dogs
      - dachshunds
      extra:
        scopes:
        - openid
        - profile
      
  • 为了防止 header 欺骗,验证代理需要在验证请求 header 之前向 API server 提供有效的客户端证书,以对照指定的 CA 进行验证。
    • –requestheader-client-ca-file 必需。PEM 编码的证书包。在检查用户名的请求 header 之前,必须针对指定文件中的证书颁发机构提交并验证有效的客户端证书。
    • –requestheader-allowed-names 可选。Common Name (cn)列表。如果设置了,则在检查用户名的请求 header 之前, 必须提供指定列表中 Common Name(cn)的有效客户端证书。如果为空,则允许使用任何 Common Name

(3)User impersonation(用户扮演)

参考:https://v1-11.docs.kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation

  • 简单来说就是当前用户扮演另外一个用户
  • 功能:测试扮演目标用户的权限,比如admin要测试新建的一个授权策略,就可以临时使用这个特性扮演另外一个用户进行测试
  • 详细过程:参考官网
  • 配置HTTP头部信息
    • Impersonate-User: The username to act as
    • Impersonate-Group: A group name to act as. Can be provided multiple times to set multiple groups. Optional. Requires “Impersonate-User”
    • Impersonate-Extra-( extra name ): A dynamic header used to associate extra fields with the user. Optional. Requires “Impersonate-User”
    • example:
      Impersonate-User: [email protected]
      Impersonate-Group: developers
      Impersonate-Group: admins
      Impersonate-Extra-dn: cn=jane,ou=engineers,dc=example,dc=com
      Impersonate-Extra-scopes: view
      Impersonate-Extra-scopes: development
      
  • 命令行中使用:
    # When using kubectl set the --as flag to configure the Impersonate-User header,
    # set the --as-group flag to configure the Impersonate-Group header
    $ kubectl drain mynode --as=superman --as-group=system:masters
    node "mynode" cordoned
    node "mynode" drained
    
  • 扮演另一个人,需要权限配置:
    • 扮演者需要的权限RBAB:
      # user, group
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: impersonator
      rules:
      - apiGroups: [""]
        resources: ["users", "groups", "serviceaccounts"]
        verbs: ["impersonate"]
      
      # extra fields
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: scopes-impersonator
      rules:
      # Can set "Impersonate-Extra-scopes" header.
      - apiGroups: ["authentication.k8s.io"]
        resources: ["userextras/scopes"]
        verbs: ["impersonate"]
      
    • 资源也可以进行严格的限制:
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: limited-impersonator
      rules:
      # Can impersonate the user "[email protected]"
      - apiGroups: [""]
        resources: ["users"]
        verbs: ["impersonate"]
        resourceNames: ["[email protected]"]
      
      # Can impersonate the groups "developers" and "admins"
      - apiGroups: [""]
        resources: ["groups"]
        verbs: ["impersonate"]
        resourceNames: ["developers","admins"]
      
      # Can impersonate the extras field "scopes" with the values "view" and "development"
      - apiGroups: ["authentication.k8s.io"]
        resources: ["userextras/scopes"]
        verbs: ["impersonate"]
        resourceNames: ["view", "development"]
      

(4)client-go credential plugins

参考:https://v1-11.docs.kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins

  • 抽空再翻译

(5)老版本的文档中的创建证书

a、部署脚本

  • 1.9版本还有,1.10版本之后就没有了
  • cluster/saltbase/salt/generate-cert/make-ca-cert.sh
  • 调用的还是esayrsa,因此这里忽略

b、esayrsa

  • 下载,解压,并初始化修补版本的easyrsa3
    curl -L -O https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz
    tar xzf easy-rsa.tar.gz
    cd easy-rsa-master/easyrsa3
    ./easyrsa init-pki
    
  • 生成 CA(使用 --batch 设置为自动模式。使用 --req-cn 设置默认的 CN)
    ./easyrsa --batch "--req-cn=${MASTER_IP}@`date +%s`" build-ca nopass
    
  • 生成服务器证书和密钥。(build-server-full [文件名]:生成一个键值对,在本地为客户端和服务器签名。)
    ./easyrsa --subject-alt-name="IP:${MASTER_IP}" build-server-full server nopass
    
  • 复制 pki/ca.crt, pki/issued/server.crt 和 pki/private/server.key 到您的目录下。
  • 将以下参数添加到 API server 的启动参数中:
    --client-ca-file=/yourdirectory/ca.crt
    --tls-cert-file=/yourdirectory/server.crt
    --tls-private-key-file=/yourdirectory/server.key
    

c、openssl

openssl 可以用来手动为集群生成证书。

  • 生成一个 2048 bit 的 ca.key:
    openssl genrsa -out ca.key 2048
    
  • 根据 ca.key 生成一个 ca.crt(使用 -days 设置证书的有效时间):
    openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
    
  • 生成一个 2048 bit 的 server.key:
    openssl genrsa -out server.key 2048
    
  • 根据 server.key 生成一个 server.csr:
    openssl req -new -key server.key -subj "/CN=${MASTER_IP}" -out server.csr
    
  • 根据 ca.key、ca.crt 和 server.csr 生成 server.crt:
    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 10000
    
  • 查看证书:
    openssl x509  -noout -text -in ./server.crt
    
  • 最后,不要忘了向 API server 的启动参数中增加配置

3、授权

(1)权限认证(概述)

  • 在 Kubernetes 里,您必须经过身份验证(登录),才能授权您的请求(授予访问权限).

a、请求属性

Kubernetes 仅查看以下API请求属性:

  • user - 验证期间提供的 user 字符串
  • group - 认证用户所属的组名列表
  • “extra” - 由认证层提供的任意字符串键到字符串值的映射
  • API - 指示请求是否用于API资源
  • Request path - 诸如/api或/healthz的其他非资源端点的路径(请参阅kubectl).
  • 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 组.

b、确定请求动词

  • 要确定资源 API 端点的请求动词,请查看所使用的HTTP动词以及请求是否对单个资源或资源集合进行操作:

    HTTP动词 请求动作
    POST 创建
    GET,HEAD 获取(个人资源),列表(结合)
    PUT 更新
    PATCH 补丁
    DELETE 删除(个人资源),删除(收藏)
  • Kubernetes 有时会使用专门的动词检查授权以获得额外的权限。例如:

    • PodSecurityPolicy在extensions API组中的podsecuritypolicies资源上检查use动词的授权。
    • RBAC 在rbac.authorization.k8s.io API组中的roles和clusterroles资源上检查bind动词的授权。
    • 认证 在核心API组中的users,groups和serviceaccounts上的impersonate动词的授权以及authentication.k8s.io API组中的userextras进行层次检查

c、授权模块

  • ABAC
  • RBAC
  • Webhook

d、检查API访问(没有明白)

参考:https://k8smeetup.github.io/docs/admin/authorization/#检查api访问

e、为您的授权模块使用标志

  • 您的策略中必须包含一个标志,以指出您的策略包含哪个授权模块:
    • –authorization-mode=ABAC 基于属性的访问控制(ABAC)模式允许您使用本地文件配置策略。
    • –authorization-mode=RBAC 基于角色的访问控制(RBAC)模式允许您使用Kubernetes API创建和存储策略.
    • –authorization-mode=Webhook WebHook是一种HTTP回调模式,允许您使用远程REST管理授权。
    • –authorization-mode=AlwaysDeny 此标志阻止所有请求. 仅使用此标志进行测试。
    • –authorization-mode=AlwaysAllow 此标志允许所有请求. 只有在您不需要API请求授权的情况下才能使用此标志。
  • 注意:
    • 您可以选择多个授权模块. 如果其中一种模式为 AlwaysAllow,则覆盖其他模式,并允许所有API请求。

(2)serviceAccount概念

  • 一开始看RBAC和身份认证,一脸懵逼,不知道servceAccount是什么概念,找到别人翻译的博文,才慢慢的找到一点感觉
  • 参考:
    • https://k8smeetup.github.io/docs/tasks/configure-pod-container/configure-service-account/
    • https://k8smeetup.github.io/docs/admin/service-accounts-admin/

a、用户账号 vs 服务账号

  • 用户账号是给人使用的。服务账号是给 pod 中运行的进程使用的。
  • 用户账号为全局设计的。命名必须在一个集群的所有命名空间中唯一,未来的用户资源不会被设计到命名空间中。 服务账号是在命名空间里的。
  • 典型场景中,一个集群的用户账号是从企业数据库的同步来的,在数据库中新用户帐号一般需要特殊权限,并且账号是与复杂的业务流程关联的。 服务账号的创建往往更轻量,允许集群用户为特定的任务创建服务账号(即,权限最小化原则)。
  • 对于人和服务的账号,审计要求会是不同的。
  • 对于复杂系统而言,配置包可以包含该系统各类组件的服务账号定义, 因为服务账号能被临时创建,并且有命名空间分类的名字,这类配置是便携式的

b、服务账号自动化

服务账号的自动化由三个独立的组件共同配合实现:

  • 服务账号准入控制器(Service account admission controller)
  • 令牌控制器(Token controller)
  • 服务账号控制器(Service account controller)

c、服务账号准入控制器

    服务帐号控制器在命名空间内管理 ServiceAccount,需要保证名为 “default” 的 ServiceAccount 在每个命名空间中存在。
    对于 pods 的操作是通过一个叫做 准入控制器 的插件(plugin)实现的。它是 APIserver 的一部分。 当 pod 被创建或更新时,它会同步更改 pod。当这个插件是活动状态时(大部分版本默认是活动状态),在 pod 被创建或者更改时, 它会做如下操作:

  • 如果 pod 没有配置 ServiceAccount,它会将 ServiceAccount 设置为 default。
  • 确保被 pod 关联的 ServiceAccount 是存在的,否则就拒绝请求。
  • 如果 pod 没有包含任何的 ImagePullSecrets,那么 ServiceAccount 的 ImagePullSecrets 就会被添加到 pod。
  • 它会把 volume 添加给 pod,该 pod 包含有一个用于 API 访问的令牌。
  • 它会把 volumeSource 添加到 pod 的每个容器,挂载到 /var/run/secrets/kubernetes.io/serviceaccount

d、令牌控制器

令牌控制器(TokenController)作为 controller-manager 的一部分运行。它异步运行。它会:

  • 监听对于 serviceAccount 的创建动作,并创建对应的 Secret 以允许 API 访问。
  • 监听对于 serviceAccount 的删除动作,并删除所有对应的 ServiceAccountToken Secret。
  • 监听对于 secret 的添加动作,确保相关联的 ServiceAccount 是存在的,并根据需要为 secret 添加一个令牌。
  • 监听对于 secret 的删除动作,并根据需要删除对应 ServiceAccount 的关联。

你必须给令牌控制器传递一个服务帐号的私钥(private key),通过 --service-account-private-key-file 参数完成。传递的私钥将被用来对服务帐号令牌进行签名。 类似的,你必须给 kube-apiserver 传递一个公钥(public key),通过 --service-account-key-file 参数完成。传递的公钥在认证过程中会被用于验证令牌

e、创建额外的api token

控制器的循环运行会确保对于每个服务帐号都存在一个带有 API 令牌的 secret。 如需要为服务帐号创建一个额外的 API 令牌,可以创建一个 ServiceAccountToken 类型的 secret,并添加与服务帐号对应的 annotation 属性,控制器会为它更新令牌:

{
    "kind": "Secret",
    "apiVersion": "v1",
    "metadata": {
        "name": "mysecretname",
        "annotations": {
            "kubernetes.io/service-account.name": "myserviceaccount"
        }
    },
    "type": "kubernetes.io/service-account-token"
}
kubectl create -f ./secret.json
kubectl describe secret mysecretname
# 删除服务账号
kubectl delete secret mysecretname

注意:

上面的实验,myserviceaccount的serviceAccount必须提前存在???

(3)serviceAccount管理

  • 参考:
    • https://k8smeetup.github.io/docs/tasks/configure-pod-container/configure-service-account/
  • Pod 容器中的进程也可以与 apiserver 联系。 当它们在联系 apiserver 的时候,它们会被认证为一个特定的 Service Account(例如default)

a、使用默认的 Service Account 访问 API server

  • 执行get pod命令,获取相关信息
    [root@server apis]# kubectl get pods hello-world-86cddf59d5-9b8zz -o yaml
    spec
      serviceAccount: default
      serviceAccountName: default
      containers:
        volumeMounts:
        - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
          name: default-token-qc6t2
          readOnly: true
    
  • 如果不想用默认的服务账号,可以使用spec.automountServiceAccountToken: false来取消,但是必须用sepc.serviceAccountName: build-rebot来设置一个
  • Service account 是否能够取得访问 API 的许可取决于您使用的 授权插件和策略。

b、使用多个Service Account

  • 每个 namespace 中都有一个默认的叫做 default 的 service account 资源。
    [root@server apis]# kubectl get serviceAccounts
    NAME      SECRETS   AGE
    default   1         16d
    
  • 创建serviceAccount
    $ cat > /tmp/serviceaccount.yaml <<EOF
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: build-robot
    EOF
    $ kubectl create -f /tmp/serviceaccount.yaml
    serviceaccount "build-robot" created
    
    [root@server apis]# kubectl get serviceaccounts/build-robot -o yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      creationTimestamp: 2018-12-24T07:01:20Z
      name: build-robot
      namespace: default
      resourceVersion: "2046916"
      selfLink: /api/v1/namespaces/default/serviceaccounts/build-robot
      uid: b7424d09-0749-11e9-92e8-005056b6756e
    secrets:
      - name: build-robot-token-h2h97
    
    # 删除
    $ kubectl delete serviceaccount/build-robot
    
  • 解读serviceAccount:
[root@server apis]# kubectl describe serviceaccounts/build-robot
Name:                build-robot
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   build-robot-token-h2h97
Tokens:              build-robot-token-h2h97
Events:              <none>
重点:就是一个Tokens,访问apiServer的认证信息

[root@server apis]# kubectl get secret build-robot-token-h2h97 -o yaml
apiVersion: v1
data:
  ca.crt:
  ......
  namespace: ZGVmYXVsdA==
  token:
  ......
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: build-robot
    kubernetes.io/service-account.uid: b7424d09-0749-11e9-92e8-005056b6756e
  creationTimestamp: 2018-12-24T07:01:20Z
  name: build-robot-token-h2h97
  namespace: default
  resourceVersion: "2046915"
  selfLink: /api/v1/namespaces/default/secrets/build-robot-token-h2h97
  uid: b743aba5-0749-11e9-92e8-005056b6756e
type: kubernetes.io/service-account-token
重点:
	- ca.crt
		- 这个是API Server的CA公钥证书,用于Pod中的Process对API Server的服务端数字证书进行校验时使用的;
	- namespace
		- 这个就是Secret所在namespace的值的base64编码,echo -n "default"|base64的输出
	- token

c、手动创建 service account 的 API token

$ cat > /tmp/build-robot-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: build-robot-secret
  annotations:
    kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
$ kubectl create -f /tmp/build-robot-secret.yaml
secret "build-robot-secret" created

[root@server apis]# kubectl get serviceaccounts/build-robot -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2018-12-24T07:01:20Z
  name: build-robot
  namespace: default
  resourceVersion: "2046916"
  selfLink: /api/v1/namespaces/default/serviceaccounts/build-robot
  uid: b7424d09-0749-11e9-92e8-005056b6756e
secrets:
- name: build-robot-token-h2h97

[root@server apis]# kubectl get secrets
NAME                      TYPE                                  DATA      AGE
build-robot-secret        kubernetes.io/service-account-token   3         6m
build-robot-token-h2h97   kubernetes.io/service-account-token   3         17m
default-token-qc6t2       kubernetes.io/service-account-token   3         16d

[root@server apis]# kubectl describe secret build-robot-token-h2h97
......

d、为 service account 添加 ImagePullSecret

这样做是为了不用每个使用私有仓库的 pod 进行操作进时指定ImagePullSecret,默认会继承serviceAccount的对应值

创建一个secret:
$ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

$ kubectl get secrets myregistrykey
NAME             TYPE                              DATA    AGE
myregistrykey    kubernetes.io/.dockerconfigjson   1       1d

修改 namespace 中的默认 service account 使用该 secret 作为 imagePullSecret
$ kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'

然后所有当前 namespace 中新创建的 pod 的 spec 中都会增加如下内容
spec:
  imagePullSecrets:
  - name: myregistrykey

(4)ABAC

基于属性的访问控制(Attribute-based access control - ABAC)
当策略有更新时需要重启apiServer

a、策略文件格式

  • 启用ABAC模式,启动的时候指定 --authorization-policy-file=SOME_FILENAME 和 --authorization-mode=ABAC
  • 文件格式:
    • 版本控制属性:
      • apiVersion,字符串类型: 有效值为"abac.authorization.kubernetes.io/v1beta1",允许版本控制和转换策略格式。
      • kind,字符串类型: 有效值为 “Policy”,允许版本控制和转换策略格式。
    • spec 配置为具有以下映射的属性:
      • 匹配属性:
        • user,字符串类型; 来自 --token-auth-file 的用户字符串,如果你指定user,它必须与验证用户的用户名匹配。
        • group,字符串类型; 如果指定group,它必须与经过身份验证的用户的一个组匹配,system:authenticated匹配所有经过身份验证的请求。system:unauthenticated匹配所有未经过身份验证的请求。
    • 资源匹配属性:
      • apiGroup,字符串类型; 一个 API 组。
        • 例: extensions
        • 通配符: *匹配所有 API 组。
      • namespace,字符串类型; 一个命名空间。
        • 例如: kube-system
        • 通配符: * 匹配所有资源请求。
      • resource,字符串类型; 资源类型。
        • 例:pods
        • 通配符: *匹配所有资源请求。
    • 非资源匹配属性:
      • nonResourcePath,字符串类型; 非资源请求路径。
        • 例如:/version/apis
        • 通配符:
          • * 匹配所有非资源请求。
          • /foo/* 匹配/foo/的所有子路径。
    • readonly,键入 boolean,如果为 true,则表示该策略仅适用于 get,list 和 watch 操作。
  • 注意:
    • 未设置的属性与类型设置为零值的属性相同(例如空字符串,0、false),然而未知的应该可读性优先。

b、授权算法

  • 请求具有与策略对象的属性对应的属性。
  • 当接收到请求时,确定属性。 未知属性设置为其类型的零值(例如: 空字符串,0,false)。
  • 设置为“*"的属性将匹配相应属性的任何值。
  • 检查属性的元组,以匹配策略文件中的每个策略。 如果至少有一行匹配请求属性,则请求被授权(但可能会在稍后验证失败)。
  • 要允许任何经过身份验证的用户执行某些操作,请将策略组属性设置为 "system:authenticated“。
  • 要允许任何未经身份验证的用户执行某些操作,请将策略组属性设置为"system:authentication“。
  • 要允许用户执行任何操作,请使用设置为“*” 的 apiGroup,namespace,resource 和 nonResourcePath 属性编写策略

c、Kubectl

  • Kubectl 使用 api-server 的 /api 和 /apis 端点进行协商客户端/服务器版本。 通过创建/更新来验证发送到API的对象操作,kubectl 查询某些 swagger 资源。 对于API版本”v1”, 那就是/swaggerapi/api/v1 & /swaggerapi/ experimental/v1。
  • 当使用 ABAC 授权时,这些特殊资源必须明确通过策略中的 nonResourcePath 属性暴露出来(参见下面的例子):
    • /api,/api/,/apis和/apis/ 用于 API 版本协商.
    • /version 通过 kubectl version 检索服务器版本.
    • /swaggerapi/* 用于创建/更新操作.

d、例子

  • 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
    	}
    }
    
  • Kubelet 可以读写事件
    {
    	"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
    	"kind": "Policy",
    	"spec": {
    		"user": "kubelet",
    		"namespace": "*",
    		"resource": "events"
    	}
    }
    
  • Bob 可以在命名空间”projectCaribou”中读取 Pod
    {
    	"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
    	"kind": "Policy",
    	"spec": {
    		"user": "bob",
    		"namespace": "projectCaribou",
    		"resource": "pods",
    		"readonly": true
    	}
    }
    
  • 任何人都可以对所有非资源路径进行只读请求:
    {
    	"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
    	"kind": "Policy",
    	"spec": {
    		"group": "system:authenticated",
    		"readonly": true,
    		"nonResourcePath": "*"
    	}
    }
    {
    	"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
    	"kind": "Policy",
    	"spec": {
    		"group": "system:unauthenticated",
    		"readonly": true,
    		"nonResourcePath": "*"
    	}
    }
    

(5)RBAC

  • 基于角色的访问控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group实现授权决策,允许管理员通过Kubernetes API动态配置策略。
  • 到1.8版本,RBAC已经stable版,后端rbac.authorization.k8s.io/v1,要启用RBAC,请使用--authorization-mode=RBAC启动API Server。

a、API概述

Ⅰ、Role与ClusterRole
  • 在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否定”的规则)。
  • 角色可以由名字空间(namespace)内的Role对象定义,而整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现。
  • 一个Role对象只能用于授予对某一单一名字空间中资源的访问权限。eg:”default”名字空间中的一个Role对象的定义,用于授予对pod的读访问权限。
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      namespace: default
      name: pod-reader
    rules:
    - apiGroups: [""] # 空字符串""表明使用core API group
      resources: ["pods"]
      verbs: ["get", "watch", "list"]
    
  • ClusterRole对象可以授予与Role对象相同的权限,但由于它们属于集群范围对象, 也可以使用它们授予对以下几种资源的访问权限:
    • 集群范围资源(例如节点,即node)
    • 非资源类型endpoint(例如”/healthz”)
    • 跨所有名字空间的名字空间范围资源(例如pod,需要运行命令kubectl get pods --all-namespaces来查询集群中所有的pod)
    • 下面的例子:ClusterRole定义可用于授予用户对某一特定名字空间,或者所有名字空间中的secret(取决于其绑定方式)的读访问权限:
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      # 鉴于ClusterRole是集群范围对象,所以这里不需要定义"namespace"字段
      name: secret-reader
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    
Ⅱ、RoleBinding与ClusterRoleBinding
  • 角色绑定将一个角色中定义的各种权限授予一个或者一组用户。 角色绑定包含了一组相关主体(即subject, 包括用户——User、用户组——Group、或者服务账户——Service Account)以及对被授予角色的引用。 在名字空间中可以通过RoleBinding对象授予权限,而集群范围的权限授予则通过ClusterRoleBinding对象完成。
  • RoleBinding对象在”default”名字空间中将”pod-reader”角色授予用户”jane”。 这一授权将允许用户”jane”从”default”名字空间中读取pod。
    # 以下角色绑定定义将允许用户"jane"从"default"名字空间中读取pod。
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1beta1
    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
    
  • RoleBinding对象也可以引用一个ClusterRole对象用于在RoleBinding所在的名字空间内授予用户对所引用的ClusterRole中 定义的名字空间资源的访问权限。这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的名字空间中复用这些角色。
    • 例如:尽管下面示例中的RoleBinding引用的是一个ClusterRole对象,但是用户”dave”(即角色绑定主体)还是只能读取”development” 名字空间中的secret(即RoleBinding所在的名字空间)。
    # 以下角色绑定允许用户"dave"读取"development"名字空间中的secret。
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      name: read-secrets
      namespace: development # 这里表明仅授权读取"development"名字空间中的资源。
    subjects:
    - kind: User
      name: dave
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: secret-reader
      apiGroup: rbac.authorization.k8s.io
    
  • 使用ClusterRoleBinding在集群级别和所有名字空间中授予权限。下面示例中所定义的ClusterRoleBinding 允许在用户组”manager”中的任何用户都可以读取集群中任何名字空间中的secret。
    # 以下`ClusterRoleBinding`对象允许在用户组"manager"中的任何用户都可以读取集群中任何名字空间中的secret。
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      name: read-secrets-global
    subjects:
    - kind: Group
      name: manager
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: secret-reader
      apiGroup: rbac.authorization.k8s.io
    
Ⅲ、对资源的引用

子资源:

  • 大多数资源由代表其名字的字符串表示,例如”pods”,就像它们出现在相关API endpoint的URL中一样。然而,有一些Kubernetes API还 包含了”子资源”,比如pod的logs。在Kubernetes中,pod logs endpoint的URL格式为:GET /api/v1/namespaces/{namespace}/pods/{name}/log,在此,”pods”是名字空间资源,而”log”是pods的子资源。
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      namespace: default
      name: pod-and-pod-logs-reader
    rules:
    - apiGroups: [""]
      resources: ["pods", "pods/log"]
      verbs: ["get", "list"]
    

资源名称列表:

  • 当指定了resourceNames列表时,不同动作 种类的请求的权限,如使用”get”、”delete”、”update”以及”patch”等动词的请求,将被限定到资源列表中所包含的资源实例上。例如,如果需要限定一个角色绑定主体只能”get”或者”update”一个configmap时,您可以定义以下角色:
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      namespace: default
      name: configmap-updater
    rules:
    - apiGroups: [""]
      resources: ["configmap"]
      resourceNames: ["my-configmap"]
      verbs: ["update", "get"]
    
  • 如果设置了resourceNames,则请求所使用的动词不能是list、watch、create或者deletecollection。 由于资源名不会出现在create、list、watch和deletecollection等API请求的URL中,所以这些请求动词不会被设置了resourceNames 的规则所允许,因为规则中的resourceNames部分不会匹配这些请求

一些角色定义的例子

  • 允许读取core API Group中定义的资源”pods”:
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "list", "watch"]
    
  • 允许读写在”extensions”和”apps” API Group中定义的”deployments”:
    rules:
    - apiGroups: ["extensions", "apps"]
      resources: ["deployments"]
      verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
    
  • 允许读取”pods”以及读写”jobs”:
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "list", "watch"]
    - apiGroups: ["batch", "extensions"]
      resources: ["jobs"]
      verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
    
  • 允许读取一个名为”my-config”的ConfigMap实例(需要将其通过RoleBinding绑定从而限制针对某一个名字空间中定义的一个ConfigMap实例的访问):
    rules:
    - apiGroups: [""]
      resources: ["configmaps"]
      resourceNames: ["my-config"]
      verbs: ["get"]
    
  • 允许读取core API Group中的”nodes”资源(由于Node是集群级别资源,所以此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效):
    rules:
    - apiGroups: [""]
      resources: ["nodes"]
      verbs: ["get", "list", "watch"]
    
  • 允许对非资源endpoint “/healthz”及其所有子路径的”GET”和”POST”请求(此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效):
    rules:
    - nonResourceURLs: ["/healthz", "/healthz/*"] # 在非资源URL中,'*'代表后缀通配符
      verbs: ["get", "post"]
    
Ⅳ、对角色绑定主体(Subject)的引用
  • RoleBinding或者ClusterRoleBinding将角色绑定到角色绑定主体(Subject)。 角色绑定主体可以是用户组(Group)、用户(User)或者服务账户(Service Accounts)。
  • 用户名,由字符串表示,可以是纯粹的用户名,也可以是邮箱,由k8s的认证模块产生,前缀system:是 为Kubernetes系统使用而保留的,所以管理员应该确保用户名不会意外地包含这个前缀。
  • 组名,同样由授权模块提供,前缀system:同样是被系统保留的。
  • 服务账户拥有包含 system:serviceaccount:前缀的用户名,并属于拥有system:serviceaccounts:前缀的用户组

角色绑定的例子:

  • 一个名为”[email protected]”的用户
    subjects:
    - kind: User
      name: "[email protected]"
      apiGroup: rbac.authorization.k8s.io
    
  • 一个名为”frontend-admins”的用户组:
    subjects:
    - kind: Group
      name: "frontend-admins"
      apiGroup: rbac.authorization.k8s.io
    
  • kube-system名字空间中的默认服务账户:
    subjects:
    - kind: ServiceAccount
      name: default
      namespace: kube-system
    
  • 名为”qa”名字空间中的所有服务账户:
    subjects:
    - kind: Group
      name: system:serviceaccounts:qa
      apiGroup: rbac.authorization.k8s.io
    
  • 在集群中的所有服务账户:
    subjects:
    - kind: Group
      name: system:serviceaccounts
      apiGroup: rbac.authorization.k8s.io
    
  • 所有认证过的用户(version 1.5+):
    subjects:
    - kind: Group
      name: system:authenticated
      apiGroup: rbac.authorization.k8s.io
    
  • 所有未认证的用户(version 1.5+):
    subjects:
    - kind: Group
      name: system:unauthenticated
      apiGroup: rbac.authorization.k8s.io
    
  • 所有用户(version 1.5+):
    subjects:
    - kind: Group
      name: system:authenticated
      apiGroup: rbac.authorization.k8s.io
    - kind: Group
      name: system:unauthenticated
      apiGroup: rbac.authorization.k8s.io
    

b、默认角色与默认角色绑定

  • API Server会创建一组默认的ClusterRole和ClusterRoleBinding对象。 这些默认对象中有许多包含system:前缀,表明这些资源由Kubernetes基础组件”拥有”。 对这些资源的修改可能导致非功能性集群(non-functional cluster)。
  • 自动更新: 每次启动时,API Server都会更新默认ClusterRole所缺乏的各种权限,并更新默认ClusterRoleBinding所缺乏的各个角色绑定主体。 这种自动更新机制允许集群修复一些意外的修改。
  • 发现类角色(略)
  • 面向用户的角色
    • cluster-admin,默认ClusterRoleBinding:system:masters group;超级用户权限,允许对任何资源执行任何操作。 在ClusterRoleBinding中使用时,可以完全控制集群和所有名字空间中的所有资源。 在RoleBinding中使用时,可以完全控制RoleBinding所在名字空间中的所有资源,包括名字空间自己。
    • admin,默认ClusterRoleBinding:None;管理员权限,利用RoleBinding在某一名字空间内部授予。 在RoleBinding中使用时,允许针对名字空间内大部分资源的读写访问, 包括在名字空间内创建角色与角色绑定的能力。 但不允许对资源配额(resource quota)或者名字空间本身的写访问。
    • edit,默认ClusterRoleBinding:None;允许对某一个名字空间内大部分对象的读写访问,但不允许查看或者修改角色或者角色绑定。
    • view,默认ClusterRoleBinding:None;允许对某一个名字空间内大部分对象的只读访问。 不允许查看角色或者角色绑定。 由于可扩散性等原因,不允许查看secret资源。
  • 核心组件角色(略)
  • 其它组件角色(略)
  • 控制器(Controller)角色(略)

c、初始化与预防权限升级

  • 官方说的有点绕,个人总结一下:
    • RBAC API会阻止用户通过编辑角色或者角色绑定来升级权限。 由于这一点是在API级别实现的,所以在RBAC授权器(RBAC authorizer)未启用的状态下依然可以正常工作
    • A自己没有查看本命名空间内secret的权限,但是A有创建角色和角色绑定的权限,他创建的角色也不会拥有查看本命名空间secret的权限,他创建的角色如果去访问secret,系统会禁止的

d、一些命令行工具

  • kubectl create rolebinding
    • 在名为”acme”的名字空间中将admin ClusterRole授予用户”bob”:
      kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
      
    • 在名为”acme”的名字空间中将view ClusterRole授予服务账户”myapp”:
      kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
      
  • kubectl create clusterrolebinding
    • 在整个集群范围内将cluster-admin ClusterRole授予用户”root”:
      kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
      
    • 在整个集群范围内将system:node ClusterRole授予用户”kubelet”:
      kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet
      
    • 在整个集群范围内将view ClusterRole授予名字空间”acme”内的服务账户”myapp”:
      kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
      

e、服务账户(serviceAccount)权限

  • 默认的RBAC策略将授予控制平面组件(control-plane component)、节点(node)和控制器(controller)一组范围受限的权限, 但对于”kube-system”名字空间以外的服务账户,则不授予任何权限(超出授予所有认证用户的发现权限)。
  • 这一点允许您根据需要向特定服务账号授予特定权限,从最安全到最不安全可以排序以下方法:
    • 对某一特定应用程序的服务账户授予角色(最佳实践):要求应用程序在其pod规范(pod spec)中指定serviceAccountName字段,并且要创建相应服务账户(例如通过API、应用程序清单或者命令kubectl create serviceaccount等)。
      • 例如:在”my-namespace”名字空间中授予服务账户”my-sa”只读权限:
      kubectl create rolebinding my-sa-view --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace
      
    • 在某一名字空间中授予”default”服务账号一个角色:如果一个应用程序没有在其pod规范中指定serviceAccountName,它将默认使用”default”服务账号。
      # 下面的例子将在”my-namespace”名字空间内授予”default”服务账号只读权限:
      kubectl create rolebinding default-view --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace
      
      # 目前,许多[加载项(addon)](/ docs / concepts / cluster-administration / addons /)作为”kube-system”名字空间中的”default”服务帐户运行。 要允许这些加载项使用超级用户访问权限,请将cluster-admin权限授予”kube-system”名字空间中的”default”服务帐户。
      # 注意:启用上述操作意味着”kube-system”名字空间将包含允许超级用户访问API的秘钥。
      kubectl create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default
      
    • 为名字空间中所有的服务账号授予角色: 如果您希望名字空间内的所有应用程序都拥有同一个角色,无论它们使用什么服务账户,您可以为该名字空间的服务账户用户组授予角色。
      # 下面的例子将授予”my-namespace”名字空间中的所有服务账户只读权限:
      kubectl create rolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace
      
    • 对集群范围内的所有服务账户授予一个受限角色(不鼓励): 如果您不想管理每个命名空间的权限,则可以将集群范围角色授予所有服务帐户。
      # 下面的例子将所有名字空间中的只读权限授予集群中的所有服务账户:
      kubectl create clusterrolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts
      
    • 授予超级用户访问权限给集群范围内的所有服务帐户(强烈不鼓励): 如果您根本不关心权限分块,您可以对所有服务账户授予超级用户访问权限。
      # 警告:这种做法将允许任何具有读取权限的用户访问secret或者通过创建一个容器的方式来访问超级用户的凭据。
      kubectl create clusterrolebinding serviceaccounts-cluster-admin --clusterrole=cluster-admin --group=system:serviceaccounts
      

f、宽泛的RBAC权限

```shell
# 警告:以下政策略允许所有服务帐户作为集群管理员。 运行在容器中的任何应用程序都会自动接收服务帐户凭据,并且可以对API执行任何操作,包括查看secret和修改权限。
# 因此,并不推荐使用这种策略。

kubectl create clusterrolebinding permissive-binding \
  --clusterrole=cluster-admin \
  --user=admin \
  --user=kubelet \
  --group=system:serviceaccounts
```

4、准入控制

  • 一个准入控制插件是一段代码,它会在请求通过认证和授权之后、对象被持久化之前拦截到达 API server 的请求。插件代码运行在 API server 进程中,必须将其编译为二进制文件,以便在此时使用。
  • 参考:
    • https://k8smeetup.github.io/docs/admin/admission-controllers/
    • https://v1-11.docs.kubernetes.io/docs/reference/access-authn-authz/admission-controllers/

(1)准入控制详细

  • AlwaysAdmit
  • AlwaysPullImages
  • AlwaysDeny
  • DenyEscalatingExec
  • ImagePolicyWebhook
  • ServiceAccount
  • SecurityContextDeny
  • ResourceQuota
  • LimitRanger
  • InitialResources (试验)
  • NamespaceLifecycle
  • DefaultStorageClass
  • DefaultTolerationSeconds
  • PodNodeSelector
  • PodSecurityPolicy
  • NodeRestriction

(2)推荐的准入控制配置:

  • version >= 1.10 ,使用–enable-admission-plugins flag (不用关心顺序)参数,这些版本中–admission-control参数被丢弃了
    --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
    
  • version = 1.9,顺序很重要
    --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
    
  • v1.6 <= version <= v1.8
    --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds
    

你可能感兴趣的:(k8s)