飞道的博客

K8S原理剖析:安全原理剖析和实践

362人阅读  评论(0)

大纲

  • 认证与鉴权
  • 准入控制
  • Service Account
  • Secret

认证与鉴权

API Server架构

Kubernetes的安全框架

访问K8S集群的资源需要过三关:认证、鉴权、准入控制。

  • 普通用户若要安全访问集群API Server,往往需要证书、 token、用户名-密码; Pod访问,需要ServiceAccount
  • K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过API Server配置来启用插件
    • ① Authentication
    • ② Authorization
    • ③ Admission Control

认证:三种客户端身份认证

认证方式 安全
级别
API Server配置 Client配置 访问示例
证书+私钥 --client-ca-file: CA根证书
--tls-cert-file: API Server证书文件
--tls-private-key-file: API Server私钥文件
--certificate-authority: CA根证书
--client-certificate:客户端证书文件
--client-key:客户端私钥文件
kubectl --server=https:/192.168.61.100:6443 --
certificate-authority=ca.pem --client
certificate=client.crt --client-key=client.key get
nodes
Token --token-auth-file:静态Token文件, csv格
式:
token,user,uid,“group1,group2,group3”
Kubectl --token
或者:
Authorization: Bearer ${token}
kubectl –server=https:/192.168.61.100:6443 --
token=792c62a1b5f2b07b --insecure-skip-tls
verify=true cluster-info
或者:
curl -k --header “Authorization: Bearer
792c62a1b5f2b07b” https:/192.168.61.100:6443/api
用户名+密
--basic_auth_file: basic认证文件,不建议
在生产环境使用
格式:
password,user,uid,"group1,group2,group3“
Kubectl –username –password
或者:
Authorization:Basic
BASE64ENCODED(USER:PASSWORD)
kubectl --server=https:/192.168.61.100:6443 --
username=admin --password=1234 --insecure-skip
tls-verify=true cluster-info
或者:
curl -k --header "Authorization:Basic
YWRtaW46MTIzNA=="
https:/192.168.61.100:6443/api

授权

  • 用户通过认证后,对指定的资源是否有权限访问,还需要经过授权环节。授权主要是用于对集群资源的访问控制,通过检查请求包含的相关属性值,与相对应的访问策略相比较, API请求必须满足某些策略才能被处理
  •  Kubernetes授权仅处理以下的请求属性:
    • ① user, group, extra
    • ② API、请求方法(如get、 post、 update、 patch和delete)和请求路径(如/api)
    • ③ 请求资源和子资源
    • ④ Namespace
    • ⑤ API Group
  • API Server支持多种授权策略,通过启动参数“--authorization_mode”设置,可以同时启用多种策略
授权策略 功能描述
AlwaysAllow 接受所有请求,如果集群不需要授权流程,采用该策略
AlwaysDeny 拒绝所有请求,一般用于测试
ABAC 基于属性的访问控制,使用用户配置的授权规则去匹配用户的请求
RBAC 基于角色的访问控制, RBAC 的授权策略可以利用 kubectl 或者 Kubernetes API 直接进行配置。 RBAC 可以授权给用
户,让用户有权进行授权管理,这样就可以无需接触节点,直接进行授权管理
Webhook WebHook 是一种 HTTP 回调, API Server把鉴权请求发给WebHook服务器,由服务器对请求进行鉴权
Node 对Node授权,配合NodeRestriction准入控制来限制kubelet仅可访问node、 endpoint、 pod、 service以及secret、
configmap、 PV和PVC等相关的资源

授权策略-ABAC

  • ABAC( Attribute-based access control),基于属性的访问控制, 通过使用将属性组合在一起的策略向用户授予访问权限
  • 给API Server指定策略文件, --authorization-policy-file=FILENAME,文件内容是一行一个Policy对象的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}}
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": "*"}}

授权策略-RBAC

RBAC( Role-Based Access Control),允许通过Kubernetes API 动态配置策略。
RBAC被映射成四种K8S顶级资源对象:

  • - 角色(Role): Role、 ClusterRole
    • * 角色表示一组权限的规则,累积规则
    • * Role适用带namespace的资源, ClusterRole适用集群资源或非资源API
  • - 建立用户与角色的映射/绑定关系: RoleBinding、 ClusterRoleBinding
    • * RoleBinding和ClusterRoleBinding的区别在于是否是namespace的资源
    • * 角色绑定包含了一组相关主体(即subject, 包括用户、用户组、或者Service Account)以及对被授予角色的引用

角色

角色绑定

Admission Control准入控制

  • Admission Control实际上是一个准入控制器(Admission Controller)插件列表(又叫“准入控制链” ),发送到API Server的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则APIServer拒绝请求
  • 会自动修改Pod的配置
  • 官方支持20+个准入控制插件,而且支持自定义扩展
  • 1.4以上版本官方推荐使用的插件
    • --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota

Secret

Secret 对象类型用来保存敏感信息,例如密码、 OAuth 令牌和 ssh key。将这些信息放在 secret 中比放在Pod 的定义或者 docker 镜像中可以更好地控制它的用途,并降低意外暴露的风险。
Pod 一般有3种方式使用 secret:

  • - 作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里
  • - 环境变量
  • - 当 Kubelet 为 pod 拉取镜像时使用(imagePullSecret)
类型 功能描述
Opaque 用来存储密码、密钥等,使用base64编码格式
kubernetes.io/dockerconfigjson 也称imagePullSecrets,用来存储私有docker registry的认证信息
kubernetes.io/service-account-token 用于被serviceaccount引用。 serviceaccout创建时Kubernetes会默认创建对应的
secret。 Pod如果使用了serviceaccount,对应的secret会自动挂载到Pod的
/run/secrets/kubernetes.io/serviceaccount目录中

Secret  - Opaque类型定义

Opaque类型的数据是一个map类型,要求value是base64编码格式
以数据库用户名(admin => YWRtaW4=)、密码(1f2d1e2e67df => MWYyZDFlMmU2N2Rm)为例:

# base64 解码
$ echo "MWYyZDFlMmU2N2Rm" | base64 --decode
1f2d1e2e67df

Secret - dockerconfigjson类型

kubernetes.io/dockerconfigjson类型secret是将包含Docker Registry凭证传递给 Kubelet 的一种方式,可以用来为Pod拉取私有镜像
$ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --dockerusername=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret/myregistrykey created.

OR: 从docker配置文件导入
$ kubectl create secret docker-registry myregistrykey –from-file=“~/.dockercfg”
$ kubectl get secret myregistrykey -o yaml


  
  1. kind: Secret
  2. type: kubernetes.io/dockerconfigjson
  3. data:
  4. .dockerconfigjson:
  5. eyJhdXRocyI6eyJET0NLRVJfUkVHSVNUUllfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFU
  6. l9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5
  7. YVDFKRSJ9fX0=
  8. metadata:
  9. name: myregistrykey


Service Account

Service Account用于Pod中的进程访问API Server

  • - 相对于客户端使用的user account(全局权限),为Pod内的进程提供身份标识

为什么需要Service Account?

  • - 客户端授权方式是“全授权”,可以任意操作集群!需要更轻量和精准的方式。

default Service Account

  • - 当namespace创建时,会自动创建一个名为default的Service Account
  • - 当default的Service Account创建时,会自动在同namespace下创建一个default-token-XXX,并关联到default的Service
  • Account上
  • - 创建Pod时,如果没有指定Service Account, K8S的Service Account Admission Controller会自动为该Pod指定default Service Account

Pod关联Service Account

  • - K8S会给Pod创建一个特殊的Volume,该Volume中包含指定Service Account Secret的token, namespace,证书文件,并将Volume挂载到Pod中所有容器的指定目录下(/var/run/secrets/kubernetes.io/serviceaccount)

认证环节

  • - 用户名 system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)
  • - 凭证 service account token

ServiceAccount使用

让Pod访问API Server

  • - 容器应用读取/var/run/secrets/kubernetes.io/serviceaccount/token文件,使用token认证方式访问API Server
  • - client-go做了封装


Kubectl使用ServiceAccount token访问API Server

  • ① 查看指定namespace(如default)下的ServiceAccount,获取Secret
  • ② 查看Secret,获取token
  • ③ 设置kubeconfig中设置token
  • ④ 使用kubectl访问

再看service-account-token类型Secret

创建Service Accout, K8S默认会创建对应的Secret

Secret使用:
kubernetes.io/service-account-token类型的Secret对应Pod中的ca.crt(API Server的CA公钥证书), namespace,
token(用API Server私钥签发的bearer token)三个文件:

  • ① /run/sercrets/kubernetes.io/serviceaccount/token
  • ② /run/sercrets/kubernetes.io/serviceaccount/ca.crt
  • ③ /run/sercrets/kubernetes.io/serviceaccount/namespace

转载:https://blog.csdn.net/fly910905/article/details/103836967
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场