Kubernetes的安全基础知识:身份验证,授权,审计



任何系统的运行迟早都会引发安全性问题:确保身份验证,权限分离,审计和其他任务。 已经为Kubernetes创建了许多解决方案 ,即使在非常苛刻的环境中也可以实现标准合规性。相同的材料专门用于在K8内置机制的框架内实现的基本安全方面。 首先,对于开始了解Kubernetes的人来说,这将是有用的,它是研究安全问题的起点。

认证方式


Kubernetes有两种类型的用户:

  • 服务帐户 -由Kubernetes API管理的帐户;
  • 用户 -由外部独立服务控制的“普通”用户。

这些类型之间的主要区别在于,对于服务帐户,Kubernetes API中有一些特殊的对象(它们称为ServiceAccounts ),这些对象与名称空间和存储在集群中类型为Secrets的对象中的授权数据集相关。 此类用户(服务帐户)主要用于管理对在Kubernetes集群中运行的Kubernetes API进程的访问权限。

普通用户在Kubernetes API中没有条目:它们必须由外部机制管理。 它们适用于居住在集群外部的人员或流程。

对API的每个请求都绑定到服务帐户或用户,或者被视为匿名。

用户认证数据包括:

  • 用户名-用户名(区分大小写!);
  • UID是机器可读的用户标识字符串,“比用户名更一致和唯一”;
  • -用户所属的组列表;
  • 额外 -授权机制可以使用的其他字段。

Kubernetes可以使用多种身份验证机制:X509证书,承载令牌,身份验证代理,HTTP基本身份验证。 使用这些机制,可以实现大量的授权方案:从带有密码的静态文件到OpenID OAuth2。

此外,同时允许多个授权方案。 默认情况下,集群使用:

  • 服务帐户令牌-用于服务帐户;
  • X509-适用于用户。

有关ServiceAccounts管理的问题不在本文的讨论范围之内,但是我建议开始从官方文档页面开始学习有关此问题的更多信息。 我们将更详细地考虑X509证书的工作问题。

用户证书(X.509)


使用证书的经典方法包括:

  • 密钥生成:

     mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/.certs/mynewuser.key 2048 
  • 证书申请生成:

     openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company" 
  • 使用Kubernetes集群CA密钥处理证书请求,获取用户证书(要获取证书,您需要使用有权访问Kubernetes集群证书颁发机构密钥的帐户,该帐户默认位于/etc/kubernetes/pki/ca.key ):

     openssl x509 -req -in ~/.certs/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/.certs/mynewuser.crt -days 500 
  • 创建配置文件:
    • 群集说明(指定特定群集安装的CA证书文件的地址和位置):

       kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 
    • 或者-如果不是推荐的选项-您可以省略根证书(然后,kubectl将不会检查api服务器集群的正确性):

       kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443 
    • 将用户添加到配置文件:

       kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key 
    • 添加上下文:

       kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser 
    • 默认上下文分配:

       kubectl config use-context mynewuser-context 

经过上述操作后,将在.kube/config文件中创建表单的.kube/config

 apiVersion: v1 clusters: - cluster: certificate-authority: /etc/kubernetes/pki/ca.crt server: https://192.168.100.200:6443 name: kubernetes contexts: - context: cluster: kubernetes namespace: target-namespace user: mynewuser name: mynewuser-context current-context: mynewuser-context kind: Config preferences: {} users: - name: mynewuser user: client-certificate: /home/mynewuser/.certs/mynewuser.crt client-key: /home/mynewuser/.certs/mynewuser.key 

为了便于在帐户和服务器之间转移配置,编辑以下键的值很有用:

  • certificate-authority
  • client-certificate
  • client-key

为此,您可以使用base64对其中指示的文件进行编码,然后通过将后缀-data添加到密钥名称中来将它们注册到配置中,即 获取certificate-authority-data

证书与kubeadm


随着Kubernetes 1.15的发布,由于kubeadm实用程序支持的alpha版本,使用证书变得更加容易。 例如,这就是现在使用用户密钥生成配置文件的样子:

 kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 

注意 :可以在api-server配置中查看所需的广告地址 ,该配置默认位于/etc/kubernetes/manifests/kube-apiserver.yaml

生成的配置将输出到stdout。 它必须保存在用户帐户的~/.kube/configKUBECONFIG环境KUBECONFIG指定的文件中。

深入挖掘


对于那些希望彻底了解所描述问题的人:


登入


默认情况下,通过身份验证的帐户无权在群集中执行操作。 Kubernetes具有用于授予权限的授权机制。

在1.6版之前,Kubernetes使用一种称为ABAC (基于属性的访问控制)的身份验证类型。 可以在官方文档中找到有关它的详细信息。 目前,这种方法被认为是旧方法,但是您仍然可以与其他类型的授权同时使用。

划分群集访问权限的实际(更灵活)方法称为RBAC基于角色的访问控制 )。 自Kubernetes 1.8以来,它已被宣布稳定。 RBAC实现了一种权限模型,该模型禁止任何未明确允许的内容。
要启用RBAC ,您需要使用--authorization --authorization-mode=RBAC选项运行Kubernetes api-server。 参数是使用api-server配置在清单中设置的,默认情况下,该文件位于command部分中的路径/etc/kubernetes/manifests/kube-apiserver.yaml中。 但是,默认情况下已启用RBAC,因此您可能不必担心:您可以通过authorization-mode的值(在已提及的kube-apiserver.yaml )进行验证。 顺便说一句,在其值中可能还有其他类型的授权( nodewebhookalways allow ),但是我们将其保留在材料范围之外。

顺便说一句,我们已经发表了一篇文章,其中包含有关使用RBAC的原理和功能的相当详细的故事,因此我将进一步限制自己的基础知识和示例清单。

以下API实体用于控制通过RBAC对Kubernetes的访问:

  • RoleClusterRole是描述特权的角色:
  • Role允许您描述名称空间中的权限;
  • ClusterRole群集内,包括特定于群集的对象,例如节点,非资源url(即与Kubernetes资源无关-例如/version/logs/api* );
  • RoleBindingClusterRoleBinding用于将RoleClusterRole绑定到用户,用户组或ServiceAccount。

实体Role和RoleBinding受名称空间限制,即 必须在同一名称空间内。 但是,RoleBinding可以引用ClusterRole,它允许您创建一组标准权限并使用它们来控制访问。

角色使用包含以下内容的规则集描述权限:

  • API组-请参阅apiGroups的官方文档以及kubectl api-resources的输出;
  • 资源( 资源podnamespacedeployment等);
  • 动词( 动词setupdate等)。
  • 资源名称( resourceNames )-适用于需要提供对特定资源而非此类型所有资源的访问权限的情况。

可以在官方文档页面上找到有关Kubernetes中授权的更详细讨论。 取而代之(或者说,除此之外),我将举例说明其工作。

RBAC实体示例


一个简单的Role ,可让您获取pod的列表和状态,并在target-namespace对其进行监视:

 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: target-namespace name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] 

一个ClusterRole的示例,它允许您获取ClusterRole的列表和状态并在整个集群中监视它们:

 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: #  "namespace" ,   ClusterRole    name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] 

示例RoleBinding ,它允许用户mynewusermy-namespace “读取” pod:

 apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: target-namespace subjects: - kind: User name: mynewuser #     ! apiGroup: rbac.authorization.k8s.io roleRef: kind: Role #    “Role”  “ClusterRole” name: pod-reader #  Role,      namespace, #   ClusterRole,   #    apiGroup: rbac.authorization.k8s.io 

活动审核


在示意图上,Kubernetes的体系结构可以表示如下:

图片

负责处理请求的Kubernetes的关键组件是api-server 。 集群上的所有操作都将通过它。 在文章“ 开始运行kubectl时在Kubernetes中会发生什么? ”中详细了解这些内部机制 ”。

系统审核是Kubernetes中一个有趣的功能,默认情况下已关闭。 它允许您记录对Kubernetes API的所有调用。 您很容易猜到,通过此API,将执行与监视和更改群集状态有关的所有操作。 与往常一样,可以在官方的 K8s 文档中找到其功能的详细说明 。 接下来,我将尝试以一种简单的语言来介绍该主题。

因此, 要启用审核 ,我们需要将三个必需的参数传递给api服务器中的容器,以下将对其进行详细说明:

  • --audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml
  • --audit-log-path=/var/log/kube-audit/audit.log
  • --audit-log-format=json

除了这三个必需参数之外,还有许多其他与审核相关的设置:从日志轮换到Webhook描述。 日志轮换参数示例:

  • --audit-log-maxbackup=10
  • --audit-log-maxsize=100
  • --audit-log-maxage=7

但是我们不会更详细地介绍它们-您可以在kube-apiserver文档中找到所有详细信息。

如前所述,所有参数均在api部分中的api-server配置(默认为/etc/kubernetes/manifests/kube-apiserver.yaml )中设置。 让我们回到3个必需参数并进行分析:

  1. audit-policy-file file-带有审核策略说明的YAML文件的路径。 我们将返回其内容,但是现在我注意到该文件应该可以通过api-server进程进行读取。 因此,有必要将其安装在容器内,为此,您可以将以下代码添加到配置的相应部分:

      volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies 
  2. audit-log-path日志文件的路径。 路径也应该可供api-server进程访问,因此,我们类似地描述其安装:

      volumeMounts: - mountPath: /var/log/kube-audit name: logs readOnly: false volumes: - hostPath: path: /var/log/kube-audit type: DirectoryOrCreate name: logs 
  3. audit-log-format 。 默认情况下,这是json ,但是旧文本格式也可用。

审核政策


现在关于提到的文件以及日志记录策略的描述。 审核策略的第一个概念是level ,即日志记录级别 。 它们如下:

  • None -不登录;
  • Metadata -记录请求元数据:用户,请求时间,目标资源(pod,名称空间等),操作类型(动词)等;
  • Request -记录元数据和请求正文;
  • RequestResponse元数据,请求正文和响应正文。

最后两个级别( RequestRequestResponse )不记录未访问资源的请求(对所谓的非资源url的调用)。

此外,所有请求都经过几个阶段

  • RequestReceived处理程序接收到请求但尚未沿着处理程序链进一步转移的阶段;
  • ResponseStarted发送响应头,但在发送响应主体之前。 为长时间查询而生成(例如watch );
  • ResponseComplete发送响应主体,将不发送更多信息;
  • Panic -检测到紧急情况时会生成事件。

您可以使用omitStages跳过任何阶段。

在策略文件中,我们可以描述具有不同日志级别的几个部分。 策略说明中找到的第一个匹配规则将适用。

kubelet守护程序使用api-server配置监视清单更改,如果检测到任何更改,它将使用api-server重新启动容器。 但是有一个重要的细节: 他们将忽略对策略文件的更改 。 更改策略文件后,您将需要手动重新启动api-server。 由于api-server作为静态pod运行,因此kubectl delete命令不会重新启动它。 您将必须手动使docker在更改了审核策略的kube-master上docker stop

 docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}') 

启用审核时,请务必记住kube-apiserver具有较高的负载 。 特别是,用于存储请求上下文的内存消耗正在增加。 仅在发送响应头之后才开始记录日志。 同样,负载取决于审核策略的配置。

政策范例


让我们使用示例分析策略文件的结构。

这是一个简单的policy文件,用于记录Metadata级别的所有内容:

 apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata 

您可以在策略中指定用户列表( UsersServiceAccounts )和用户组。 例如,这是我们将忽略系统用户,但在“ Request级别记录其他所有Request

 apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: None userGroups: - "system:serviceaccounts" - "system:nodes" users: - "system:anonymous" - "system:apiserver" - "system:kube-controller-manager" - "system:kube-scheduler" - level: Request 

也可以描述目标:

  • namespaces
  • 动词( 动词getupdatedelete等);
  • 资源( 资源 ,即: podconfigmaps等)和资源组( apiGroups )。

注意! 可以使用以下命令获取资源和资源组(API组,即apiGroups)以及它们在群集中安装的版本:

 kubectl api-resources kubectl api-versions 

以下审计策略是阿里云文档中最佳实践的演示:

 apiVersion: audit.k8s.io/v1beta1 kind: Policy #    RequestReceived omitStages: - "RequestReceived" rules: #   ,     : - level: None users: ["system:kube-proxy"] verbs: ["watch"] resources: - group: "" #  api group   ,    #   Kubernetes,  “core” resources: ["endpoints", "services"] - level: None users: ["system:unsecured"] namespaces: ["kube-system"] verbs: ["get"] resources: - group: "" # core resources: ["configmaps"] - level: None users: ["kubelet"] verbs: ["get"] resources: - group: "" # core resources: ["nodes"] - level: None userGroups: ["system:nodes"] verbs: ["get"] resources: - group: "" # core resources: ["nodes"] - level: None users: - system:kube-controller-manager - system:kube-scheduler - system:serviceaccount:kube-system:endpoint-controller verbs: ["get", "update"] namespaces: ["kube-system"] resources: - group: "" # core resources: ["endpoints"] - level: None users: ["system:apiserver"] verbs: ["get"] resources: - group: "" # core resources: ["namespaces"] #     read-only URLs: - level: None nonResourceURLs: - /healthz* - /version - /swagger* #   ,     “”: - level: None resources: - group: "" # core resources: ["events"] #   Secret, ConfigMap  TokenReview    , #         - level: Metadata resources: - group: "" # core resources: ["secrets", "configmaps"] - group: authentication.k8s.io resources: ["tokenreviews"] #   get, list  watch   ;    - level: Request verbs: ["get", "list", "watch"] resources: - group: "" # core - group: "admissionregistration.k8s.io" - group: "apps" - group: "authentication.k8s.io" - group: "authorization.k8s.io" - group: "autoscaling" - group: "batch" - group: "certificates.k8s.io" - group: "extensions" - group: "networking.k8s.io" - group: "policy" - group: "rbac.authorization.k8s.io" - group: "settings.k8s.io" - group: "storage.k8s.io" #        API - level: RequestResponse resources: - group: "" # core - group: "admissionregistration.k8s.io" - group: "apps" - group: "authentication.k8s.io" - group: "authorization.k8s.io" - group: "autoscaling" - group: "batch" - group: "certificates.k8s.io" - group: "extensions" - group: "networking.k8s.io" - group: "policy" - group: "rbac.authorization.k8s.io" - group: "settings.k8s.io" - group: "storage.k8s.io" #         - level: Metadata 


另一个良好的审核策略示例是GCE中使用配置文件

为了快速响应审核事件,可以描述一个webhook 。 此问题已在官方文档中披露,我将不在本文讨论范围之内。

总结


本文概述了Kubernetes集群中的基本安全机制,这些机制使您可以创建个性化的用户帐户,共享其权限并记录其操作。 我希望这对于那些在理论上或已经在实践中面临此类问题的人都是有用的。 我还建议您阅读“ PS”中列出的有关Kubernetes中安全性主题的其他材料列表-也许您会在其中找到与您相关的问题的必要详细信息。

聚苯乙烯


另请参阅我们的博客:

Source: https://habr.com/ru/post/zh-CN468679/


All Articles