使用RBAC授权

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用RBAC授权相关的知识,希望对你有一定的参考价值。

参考技术A

基于角色的访问控制 (RBAC) 是一种根据组织内各个用户的角色来调节对计算机或网络资源的访问的方法。

RBAC 授权使用 rbac.authorization.k8s.io API 组 推动授权决策,允许您通过 Kubernetes API 动态配置策略。

要启用 RBAC,请启动 API 服务器 将 --authorization-mode 标志设置为逗号分隔的列表,其中包括 RBAC ; 例如:

RBAC API 声明了四种 Kubernetes 对象: Role 、 ClusterRole 、 RoleBinding 和 ClusterRoleBinding 。您可以 像任何其他 Kubernetes 对象一样使用工具来 描述 或修改对象。 kubectl,

警告: 这些对象在设计上会施加访问限制。如果您在学习过程中对集群进行更改,请参阅 权限提升预防和引导 以了解这些限制如何阻止您进行某些更改。

RBAC 角色 或 ClusterRole 包含表示一组权限的规则。权限纯粹是附加的(没有“拒绝”规则)。

角色总是在特定的范围内设置权限 命名空间 ; 创建角色时,必须指定它所属的命名空间。

相反,ClusterRole 是一个非命名空间资源。资源具有不同的名称(Role 和 ClusterRole),因为 Kubernetes 对象总是必须具有命名空间或不具有命名空间;不可能两者兼而有之。

ClusterRoles 有多种用途。您可以使用 ClusterRole 来:

如果要在命名空间中定义角色,请使用角色;如果要在集群范围内定义角色,请使用 ClusterRole。

这是“默认”命名空间中的示例角色,可用于授予对 豆荚 :

ClusterRole 可用于授予与角色相同的权限。由于 ClusterRoles 是集群范围的,您还可以使用它们来授予对以下内容的访问权限:

下面是一个 ClusterRole 示例,可用于授予对 秘密 在任何特定命名空间中,或跨所有命名空间(取决于它的 绑定 方式):

Role 或 ClusterRole 对象的名称必须是有效的 路径段名称 。

角色绑定将角色中定义的权限授予一个用户或一组用户。它包含一个 主题 列表(用户、组或服务帐户),以及对被授予角色的引用。RoleBinding 授予特定命名空间内的权限,而 ClusterRoleBinding 授予访问集群范围的权限。

RoleBinding 可以引用同一命名空间中的任何角色。或者,RoleBinding 可以引用 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 的命名空间。如果要将 ClusterRole 绑定到集群中的所有命名空间,请使用 ClusterRoleBinding。

RoleBinding 或 ClusterRoleBinding 对象的名称必须是有效的 路径段名称 。

下面是一个 RoleBinding 示例,它将“pod-reader”角色授予“default”命名空间中的用户“jane”。这允许“jane”读取“default”命名空间中的 pod。

RoleBinding 还可以引用 ClusterRole 以将该 ClusterRole 中定义的权限授予 RoleBinding 命名空间内的资源。这种引用允许您在集群中定义一组通用角色,然后在多个命名空间中重用它们。

例如,即使以下 RoleBinding 引用 ClusterRole,“dave”(主题,区分大小写)也只能读取“development”命名空间中的 Secret,因为 RoleBinding 的命名空间(在其元数据中)是“development” .

要在整个集群中授予权限,您可以使用 ClusterRoleBinding。以下 ClusterRoleBinding 允许组“manager”中的任何用户读取任何命名空间中的机密。

创建绑定后,您无法更改它所引用的角色或集群角色。如果您尝试更改绑定 roleRef ,则会收到验证错误。如果确实要更改 roleRef 绑定,则需要删除绑定对象并创建替换。

这种限制有两个原因:

命令行实用程序创建或更新包含 RBAC 对象的 kubectl auth reconcile 清单文件,并在需要更改绑定对象引用的角色时处理删除和重新创建绑定对象。有关详细信息,请参阅 命令用法和示例 。

在 Kubernetes API 中,大多数资源都使用其对象名称的字符串表示形式来表示和访问,例如 pods Pod。RBAC 使用与相关 API 端点的 URL 中出现的完全相同的名称来引用资源。一些 Kubernetes API 涉及 子资源 ,例如 Pod 的日志。对 Pod 日志的请求如下所示:

在这种情况下, pods 是 Pod 资源的命名空间资源,并且 log 是 pods . 要在 RBAC 角色中表示这一点,请使用斜杠 ( / ) 来分隔资源和子资源。要允许主题读取 pods 并访问 log 每个 Pod 的子资源,请编写:

您还可以通过 resourceNames 列表为某些请求按名称引用资源。指定后,可以将请求限制为资源的单个实例。这是一个将其主题限制为 only get 或 update a 配置映射 命名 my-configmap :

注意: 您不能通过资源名称来限制 create 或 deletecollection 请求。对于 create ,此限制是因为在授权时可能不知道新对象的名称。如果您限制 list 或 watch 通过资源名称,客户端必须在其或请求中包含与指定资源名称匹配的 metadata.name 字段选择器才能获得授权。例如, list``watch``kubectl get configmaps --field-selector=metadata.name=my-configmap

您可以将多个 ClusterRole 聚合为一个组合的 ClusterRole。 一个控制器,作为集群控制平面的一部分运行,用一个集合监视 ClusterRole 对象 aggregationRule 。定义一个 aggregationRule 标签 选择器 控制器用来匹配应该组合到这个 rules 字段中的其他 ClusterRole 对象。

这是一个聚合 ClusterRole 的示例:

如果您创建与现有聚合 ClusterRole 的标签选择器匹配的新 ClusterRole,则该更改会触发将新规则添加到聚合 ClusterRole 中。这是一个示例,通过创建另一个标记为 的 ClusterRole,将规则添加到“监控”ClusterRole rbac.example.com/aggregate-to-monitoring: true 。

默认的 面向用户的角色 使用 ClusterRole 聚合。这使您作为集群管理员可以包含自定义资源的规则,例如由 自定义资源定义 或聚合 API 服务器,以扩展默认角色。

例如:以下 ClusterRoles 让“admin”和“edit”默认角色管理名为 CronTab 的自定义资源,而“view”角色只能对 CronTab 资源执行读取操作。您可以假设 CronTab 对象 "crontabs" 在 API 服务器看到的 URL 中命名。

以下示例是 Role 或 ClusterRole 对象的摘录,仅显示该 rules 部分。

允许 "pods" 在核心中读取资源 API 组 :

允许在 API 组和API 组中读/写部署(在 HTTP 级别: "deployments" 在其 URL 的资源部分中的对象) : "extensions"``"apps"

允许读取核心 API 组中的 Pod,以及读取或写入 API 组中的 Job "batch" 资源 "extensions" :

允许读取名为“my-config”的 ConfigMap(必须与 RoleBinding 绑定以限制单个命名空间中的单个 ConfigMap):

允许读取 "nodes" 核心组中的资源(因为节点是集群范围的,这必须在与 ClusterRoleBinding 绑定的 ClusterRole 中才能生效):

允许对非资源端点 /healthz 和所有子路径的 GET 和 POST 请求(必须在与 ClusterRoleBinding 绑定的 ClusterRole 中才能生效):

RoleBinding 或 ClusterRoleBinding 将角色绑定到主题。主题可以是组、用户或 服务帐户 .

Kubernetes 将用户名表示为字符串。这些可以是: 简单的名称,例如“alice”;电子邮件样式的名称,例如“ bob@example.com ”;或表示为字符串的数字用户 ID。作为集群管理员,您可以配置 身份验证模块 ,以便身份验证以您想要的格式生成用户名。

注意: 前缀 system: 是为 Kubernetes 系统保留的,因此您应该确保您没有名称 system: 以意外开头的用户或组。除了这个特殊的前缀,RBAC 授权系统不需要任何格式的用户名。

在 Kubernetes 中,Authenticator 模块提供组信息。组,如用户,表示为字符串,并且该字符串没有格式要求,除了 system: 保留前缀。

ServiceAccounts 的名称以 为前缀 system:serviceaccount: ,并且属于名称以 为前缀的组 system:serviceaccounts: 。

笔记:

以下示例是 RoleBinding 仅显示该 subjects 部分的摘录。

对于名为 的用户 alice@example.com :

对于名为 的组 frontend-admins :

对于“kube-system”命名空间中的默认服务帐户:

对于任何命名空间中“qa”组中的所有服务帐户:

对于“开发”命名空间中“开发”组中的所有服务帐户:

对于任何命名空间中的所有服务帐户:

对于所有经过身份验证的用户:

对于所有未经身份验证的用户:

对于所有用户:

API 服务器创建一组默认 ClusterRole 和 ClusterRoleBinding 对象。其中很多都是带 system: 前缀的,表示资源是由集群控制平面直接管理的。所有默认的 ClusterRoles 和 ClusterRoleBindings 都标有 kubernetes.io/bootstrapping=rbac-defaults 。

警告: 使用带有 system: 前缀的名称修改 ClusterRole 和 ClusterRoleBindings 时要小心。对这些资源的修改可能会导致集群无法正常工作。

在每次启动时,API 服务器会使用任何缺失的权限更新默认集群角色,并使用任何缺失的主题更新默认集群角色绑定。这允许集群修复意外修改,并有助于在新 Kubernetes 版本中权限和主题发生变化时保持角色和角色绑定是最新的。

要退出此协调,请将 rbac.authorization.kubernetes.io/autoupdate 默认集群角色或角色绑定上的注释设置为 false . 请注意,缺少默认权限和主题可能会导致集群无法正常工作。

如果 RBAC 授权方处于活动状态,则默认情况下会启用自动对帐。

默认角色绑定授权未经身份验证和经过身份验证的用户读取被认为安全且可公开访问的 API 信息(包括 CustomResourceDefinitions)。要禁用匿名未经身份验证的访问,请添加 --anonymous-auth=false 到 API 服务器配置。

通过 kubectl 运行查看这些角色的配置:

注意: 如果您编辑该 ClusterRole,您的更改将在 API 服务器重新启动时通过 auto-reconciliation 被覆盖。为避免覆盖,请不要手动编辑角色,或禁用自动协调。

<caption style="box-sizing: border-box; padding-top: 0.75rem; padding-bottom: 0.75rem; color: rgb(121, 118, 118); text-align: left; caption-side: bottom;">Kubernetes RBAC API 发现角色</caption><colgroup style="box-sizing: border-box;"><col style="box-sizing: border-box; width: 296.406px;"><col style="box-sizing: border-box; width: 296.406px;"><col style="box-sizing: border-box;"></colgroup>

一些默认 ClusterRoles 没有 system: 前缀。这些旨在成为面向用户的角色。它们包括超级用户角色 ( cluster-admin )、旨在使用 ClusterRoleBindings 在集群范围内授予的角色,以及旨在使用 RoleBindings ( admin 、 edit 、 view ) 在特定命名空间内授予的角色。

面向用户的 ClusterRoles 使用 ClusterRole 聚合 来允许管理员在这些 ClusterRoles 上包含自定义资源的规则。要将规则添加到 admin 、 edit 或 view 角色,请创建具有以下一个或多个标签的 ClusterRole:

<colgroup style="box-sizing: border-box;"><col style="box-sizing: border-box; width: 296.406px;"><col style="box-sizing: border-box; width: 296.406px;"><col style="box-sizing: border-box;"></colgroup>

如果在 RoleBinding 中使用,则允许对命名空间中的大多数资源进行读/写访问,包括在命名空间中创建角色和角色绑定的能力。此角色不允许对资源配额或命名空间本身进行写访问。此角色还不允许对使用 Kubernetes v1.22+ 创建的集群中的端点进行写访问。更多信息可在 “端点的写入访问”部分 中找到。

|
| 编辑 | 没有 | 允许对命名空间中的大多数对象进行读/写访问。

此角色不允许查看或修改角色或角色绑定。但是,该角色允许访问 Secrets 并作为命名空间中的任何 ServiceAccount 运行 Pod,因此它可以用于获取命名空间中任何 ServiceAccount 的 API 访问级别。此角色还不允许对使用 Kubernetes v1.22+ 创建的集群中的端点进行写访问。更多信息可在 “端点的写入访问”部分 中找到。

|
| 看法 | 没有 | 允许只读访问以查看命名空间中的大多数对象。它不允许查看角色或角色绑定。

此角色不允许查看 Secret,因为读取 Secret 的内容可以访问命名空间中的 ServiceAccount 凭证,这将允许 API 访问命名空间中的任何 ServiceAccount(一种权限提升形式)。

|

<colgroup style="box-sizing: border-box;"><col style="box-sizing: border-box; width: 296.406px;"><col style="box-sizing: border-box; width: 296.406px;"><col style="box-sizing: border-box;"></colgroup>

您应该使用 Node 授权 者和 NodeRestriction 准入插件 而不是<tt style="box-sizing: border-box;">system:node</tt>角色,并允许根据计划在其上运行的 Pod 授予对 kubelet 的 API 访问权限。

<tt style="box-sizing: border-box;">system:node</tt>角色的存在只是为了兼容从 v1.8 之前的版本升级的 Kubernetes 集群。

|
| 系统:节点代理 | 系统:kube-proxy 用户 | 允许访问所需的资源 kube-代理 零件。 |

<colgroup style="box-sizing: border-box;"><col style="box-sizing: border-box; width: 296.406px;"><col style="box-sizing: border-box; width: 296.406px;"><col style="box-sizing: border-box;"></colgroup>

Kubernetes 控制器管理器 运行 控制器 内置在 Kubernetes 控制平面中。当使用 调用时 --use-service-account-credentials ,kube-controller-manager 使用单独的服务帐户启动每个控制器。每个内置控制器都有对应的角色,前缀为 system:controller: . 如果控制器管理器不是以 启动的 --use-service-account-credentials ,它使用自己的凭据运行所有控制循环,必须授予所有相关角色。这些角色包括:

RBAC API 可防止用户通过编辑角色或角色绑定来提升权限。因为这是在 API 级别强制执行的,所以即使没有使用 RBAC 授权方,它也适用。

仅当以下至少一项为真时,您才能创建/更新角色:

例如,如果 user-1 无法在集群范围内列出 Secret,则无法创建包含该权限的 ClusterRole。允许用户创建/更新角色:

如果您已经拥有被引用角色中包含的所有权限(与角色绑定在同一范围内) ,或者 如果您已被授权 bind 对被引用角色执行谓词,则只能创建/更新角色绑定。例如,如果 user-1 无法在集群范围内列出 Secret,则它们无法创建 ClusterRoleBinding 到授予该权限的角色。允许用户创建/更新角色绑定:

例如,此 ClusterRole 和 RoleBinding 将允许 user-1 授予其他用户命名空间中的 admin 、 edit 和 view 角色 user-1-namespace :

在引导第一个角色和角色绑定时,初始用户有必要授予他们尚未拥有的权限。引导初始角色和角色绑定:

在单个命名空间中创建定义权限的角色对象。例子:

创建一个 ClusterRole。例子:

授予特定命名空间内的角色或集群角色。例子:

在整个集群(所有命名空间)中授予 ClusterRole。例子:

rbac.authorization.k8s.io/v1 从清单文件创建或更新API 对象。

如果需要,将创建缺少的对象,并为命名空间的对象创建包含的命名空间。

现有角色已更新以包含输入对象中的权限,并在 --remove-extra-permissions 指定时删除额外权限。

更新现有绑定以将主题包括在输入对象中,如果 --remove-extra-subjects 指定,则删除额外的主题。

例子:

默认 RBAC 策略授予控制平面组件、节点和控制器的范围权限,但 不授予 命名空间之外的服务帐户 kube-system 权限(除了授予所有经过身份验证的用户的发现权限)。

这允许您根据需要将特定角色授予特定的 ServiceAccounts。细粒度的角色绑定提供了更高的安全性,但需要更多的管理工作。更广泛的授权可以为 ServiceAccounts 提供不必要的(并且可能会升级的)API 访问,但更易于管理。

按照从最安全到最不安全的顺序,这些方法是:

Istio数据面配置解析18:使用RBAC对Http请求进行授权

Istio数据面配置解析18:使用RBAC对Http请求进行授权


Istio数据面配置解析18:使用RBAC对Http请求进行授权概述相关拓扑准备相关配置RbacConfigServiceRole和ServiceRoleBindingDestinationRule测试结果


概述

本文介绍了在Isito中使用RBAC对Http请求进行授权:

  1. 1.0版本针对Http的RBAC授权的配置会被加到Server端inbound listener的envoy.http_connection_manager这个filter的envoy.filters.http.rbac中。

  2. 1.0版本只支持针对Http的RBAC授权。

  3. 针对source.principal的授权,需要为Client端挂载证书和密钥。


相关拓扑

  • 在destinationrule中启用针对server端的istio_mutual的配置。

  • 为server端配置rbacconfig,开启rbac授权。

  • 为server端配置servicerole,为角色授权。

  • 为server端配置servicerolebinding,将角色与被授权对象关联。

  • 在本文中,将基于source.principal进行授权,也就是针对client端的证书信息进行授权。


  • 使用istio rbacconfig定义nginx.default.svc.cluster.local启用rbac授权。

  • 使用istio servicerole定义到nginx.default.svc.cluster.local服务的带有version: v1标签的端点的角色权限。

  • 使用istio servicerole定义到nginx.default.svc.cluster.local服务的带有version: v2标签的端点的角色权限。

  • 使用istio servicerolebinding定义将cluster.local/ns/default/sa/sleep-v1与v1角色绑定。

  • 使用istio servicerolebinding定义将cluster.local/ns/default/sa/sleep-v2与v2角色绑定。

  • 使用istio destinationrule为到nginx.default.svc.cluster.local服务的请求挂载证书。


准备

apiVersion: v1
kind: ServiceAccount
metadata:
 name: sleep-v1
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: sleep-v2
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: sleep-v1
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: sleep
       version: v1
   spec:
     serviceAccountName: sleep-v1
     containers:
     - name: sleep
       image: 192.168.0.61/istio-example/alpine-curl
       command: ["/bin/sleep","7200"]
       imagePullPolicy: IfNotPresent
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: sleep-v2
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: sleep
       version: v2
   spec:
     serviceAccountName: sleep-v2
     containers:
     - name: sleep
       image: 192.168.0.61/istio-example/alpine-curl
       command: ["/bin/sleep","7200"]
       imagePullPolicy: IfNotPresent
  • 准备sleep-v1和sleep-v2用于client端。

  • 为sleep-v1和sleep-v2准备相应的serviceaccount。


apiVersion: v1
kind: Service
metadata:
 name: nginx
spec:
 type: ClusterIP
 ports:
 - port: 80
   name: http
 selector:
   app: nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: nginx-v1
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: nginx
       version: v1
   spec:
     serviceAccountName: nginx
     containers:
     - name: nginx
       image: 192.168.0.61/istio-example/nginx
       ports:
       - containerPort: 80
       volumeMounts:
       - mountPath: /etc/nginx/conf.d/
         readOnly: true
         name: conf
       - mountPath: /etc/nginx/html/
         readOnly: true
         name: index
     volumes:
     - name: conf
       configMap:
         name: nginx-v1
         items:
           - key: default.conf
             path: default.conf
     - name: index
       configMap:
         name: nginx-v1
         items:
           - key: index.html
             path: index.html
---
apiVersion: v1
kind: ConfigMap
metadata:
 name: nginx-v1
data:
 default.conf: |
   server {
     listen       80;
     server_name  loalhost;

     location / {
       root   /etc/nginx/html/;
       index  index.html index.htm;
     }

     error_page   500 502 503 504  /50x.html;
     location = /50x.html {
       root   /usr/share/nginx/html;
     }
   }
 index.html: |
   <!DOCTYPE html>
   <html>
   <head>
   <title>Welcome to nginx!</title>
   <style>
     body {
       width: 35em;
       margin: 0 auto;
       font-family: Tahoma, Verdana, Arial, sans-serif;
     }
   </style>
   </head>
   <body>
   <h1>Welcome to nginx!</h1>
   <h1>v1!</h1>
   <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p>
   <p>For online documentation and support please refer to
   <a href="http://nginx.org/">nginx.org</a>.<br/>
   Commercial support is available at
   <a href="http://nginx.com/">nginx.com</a>.</p>
   <p><em>Thank you for using nginx.</em></p>
   </body>
   </html>
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: nginx-v2
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: nginx
       version: v2
   spec:
     serviceAccountName: nginx
     containers:
     - name: nginx
       image: 192.168.0.61/istio-example/nginx
       ports:
       - containerPort: 80
       volumeMounts:
       - mountPath: /etc/nginx/conf.d/
         readOnly: true
         name: conf
       - mountPath: /etc/nginx/html/
         readOnly: true
         name: index
     volumes:
     - name: conf
       configMap:
         name: nginx-v2
         items:
           - key: default.conf
             path: default.conf
     - name: index
       configMap:
         name: nginx-v2
         items:
           - key: index.html
             path: index.html
---
apiVersion: v1
kind: ConfigMap
metadata:
 name: nginx-v2
data:
 default.conf: |
   server {
     listen       80;
     server_name  loalhost;

     location / {
       root   /etc/nginx/html/;
       index  index.html index.htm;
     }

     error_page   500 502 503 504  /50x.html;
     location = /50x.html {
       root   /usr/share/nginx/html;
     }
   }
 index.html: |
   <!DOCTYPE html>
   <html>
   <head>
   <title>Welcome to nginx!</title>
   <style>
     body {
       width: 35em;
       margin: 0 auto;
       font-family: Tahoma, Verdana, Arial, sans-serif;
     }
   </style>
   </head>
   <body>
   <h1>Welcome to nginx!</h1>
   <h1>v2!</h1>
   <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p>
   <p>For online documentation and support please refer to
   <a href="http://nginx.org/">nginx.org</a>.<br/>
   Commercial support is available at
   <a href="http://nginx.com/">nginx.com</a>.</p>
   <p><em>Thank you for using nginx.</em></p>
   </body>
   </html>
  • 准备nginx-v1和nginx-v2用于server端。

  • 为nginx-v1和nginx-v2准备相应的service以及serviceaccount。


相关配置

RbacConfig

apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
 name: default
 namespace: istio-system
spec:
 mode: 'ON_WITH_INCLUSION'
 inclusion:
   services: ["nginx.default.svc.cluster.local"]
  • rbacconfig相关配置。

  • 目前istio的rbaconfig为全局配置,每个mesh中只能配置一个。

  • rbacconfig的name需要配置为default。

  • rbacconfig的namespace需要配置为istio-system。

  • rbacconfig的模式配置为ON_WITH_INCLUSION,即只针对inclusion中定义的服务启用rbac。

  • 在inclusion中,配置针对nginx.default.svc.cluster.local启用rbac授权。


ServiceRole和ServiceRoleBinding

apiVersion: rbac.istio.io/v1alpha1
kind: ServiceRole
metadata:
 name: sr-v1
 namespace: default
spec:
 rules:
 - services: ["nginx.default.svc.cluster.local"]
   methods: ["GET"]
   constraints:
   - key: "destination.labels[version]"
     values: ["v1"]
---
apiVersion: rbac.istio.io/v1alpha1
kind: ServiceRole
metadata:
 name: sr-v2
 namespace: default
spec:
 rules:
 - services: ["nginx.default.svc.cluster.local"]
   methods: ["GET"]
   constraints:
   - key: "destination.labels[version]"
     values: ["v2"]
  • servicerole相关配置。

  • 在servicerole sr-v1中,针对nginx.default.svc.cluster.local的destination.labels[version]包含v1的pod,授予http get的权限。

  • 在servicerole sr-v2中,针对nginx.default.svc.cluster.local的destination.labels[version]包含v2的pod,授予http get的权限。


apiVersion: rbac.istio.io/v1alpha1
kind: ServiceRoleBinding
metadata:
 name: srb-v1
 namespace: default
spec:
 subjects:
 - user: "cluster.local/ns/default/sa/sleep-v1"
 roleRef:
   kind: ServiceRole
   name: "sr-v1"
---
apiVersion: rbac.istio.io/v1alpha1
kind: ServiceRoleBinding
metadata:
 name: srb-v2
 namespace: default
spec:
 subjects:
 - user: "cluster.local/ns/default/sa/sleep-v2"
 roleRef:
   kind: ServiceRole
   name: "sr-v2"
  • servicerolebinding相关配置。

  • 将user,也就是source.principal,为cluster.local/ns/default/sa/sleep-v1,也就是sleep-v1应用,授予sr-v1的角色,也就是可以以http get的方式,访问nginx-v1。

  • 将user,也就是source.principal,为cluster.local/ns/default/sa/sleep-v2,也就是sleep-v2应用,授予sr-v2的角色,也就是可以以http get的方式,访问nginx-v2。


{
       "name": "10.234.1.48_80",
       "address": {
           "socketAddress": {
               "address": "10.234.1.48",
               "portValue": 80
           }
       },
       "filterChains": [
           {
               "filterChainMatch": {
                   "transportProtocol": "raw_buffer"
               },
               "filters": [
                   {
                       "name": "envoy.http_connection_manager",

                           "http_filters": [
                               {
                                   "config": {
                                       "policy": {
                                           "peers": [
                                               {
                                                   "mtls": {
                                                       "mode": "PERMISSIVE"
                                                   }
                                               }
                                           ]
                                       }
                                   },
                                   "name": "istio_authn"
                               },
                               {
                                   "config": {
                                       "rules": {
                                           "policies": {
                                               "sr-v1": {
                                                   "permissions": [
                                                       {
                                                           "and_rules": {
                                                               "rules": [
                                                                   {
                                                                       "or_rules": {
                                                                           "rules": [
                                                                               {
                                                                                   "header": {
                                                                                       "exact_match": "GET",
                                                                                       "name": ":method"

                                                   "principals": [
                                                       {
                                                           "and_ids": {
                                                               "ids": [
                                                                   {
                                                                       "metadata": {
                                                                           "filter": "istio_authn",
                                                                           "path": [
                                                                               {
                                                                                   "key": "source.principal"
                                                                               }
                                                                           ],
                                                                           "value": {
                                                                               "string_match": {
                                                                                   "exact": "cluster.local/ns/default/sa/sleep-v1"
  • 在nginx-v1的inbound listener中,会增加相应的filter,针对source.principal为cluster.local/ns/default/sa/sleep-v1的角色,授予get的权限。


{
       "name": "10.234.0.70_80",
       "address": {
           "socketAddress": {
               "address": "10.234.0.70”,
               "portValue": 80
           }
       },
       "filterChains": [
           {
               "filterChainMatch": {
                   "transportProtocol": "raw_buffer"
               },
               "filters": [
                   {
                       "name": "envoy.http_connection_manager",

                           "http_filters": [
                               {
                                   "config": {
                                       "policy": {
                                           "peers": [
                                               {
                                                   "mtls": {
                                                       "mode": "PERMISSIVE"
                                                   }
                                               }
                                           ]
                                       }
                                   },
                                   "name": "istio_authn"
                               },
                               {
                                   "config": {
                                       "rules": {
                                           "policies": {
                                               "sr-v1": {
                                                   "permissions": [
                                                       {
                                                           "and_rules": {
                                                               "rules": [
                                                                   {
                                                                       "or_rules": {
                                                                           "rules": [
                                                                               {
                                                                                   "header": {
                                                                                       "exact_match": "GET",
                                                                                       "name": ":method"

                                                   "principals": [
                                                       {
                                                           "and_ids": {
                                                               "ids": [
                                                                   {
                                                                       "metadata": {
                                                                           "filter": "istio_authn",
                                                                           "path": [
                                                                               {
                                                                                   "key": "source.principal"
                                                                               }
                                                                           ],
                                                                           "value": {
                                                                               "string_match": {
                                                                                   "exact": "cluster.local/ns/default/sa/sleep-v2”
  • 在nginx-v2的inbound listener中,会增加相应的filter,针对source.principal为cluster.local/ns/default/sa/sleep-v2的角色,授予get的权限。


DestinationRule

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: dr
spec:
 host: nginx.default.svc.cluster.local
 trafficPolicy:
   tls:
     mode: ISTIO_MUTUAL
  • destinationrule相关配置。

  • 因为是针对source.principal进行授权,所以要在client端挂载相应证书。

  • 针对到server端的请求,启用ISTIO_MUTUAL,挂载相应证书和密钥。


{
       "name": "outbound|80||nginx.default.svc.cluster.local",
       "type": "EDS",
       "edsClusterConfig": {
           "edsConfig": {
               "ads": {}
           },
           "serviceName": "outbound|80||nginx.default.svc.cluster.local"
       },
       "connectTimeout": "1.000s",
       "circuitBreakers": {
           "thresholds": [
               {}
           ]
       },
       "tlsContext": {
           "commonTlsContext": {
               "tlsCertificates": [
                   {
                       "certificateChain": {
                           "filename": "/etc/certs/cert-chain.pem"
                       },
                       "privateKey": {
                           "filename": "/etc/certs/key.pem"
                       }
                   }
               ],
               "validationContext": {
                   "trustedCa": {
                       "filename": "/etc/certs/root-cert.pem"
                   },
                   "verifySubjectAltName": [
                       "spiffe://cluster.local/ns/default/sa/nginx"
                   ]
               },
               "alpnProtocols": [
                   "istio"
               ]
           },
           "sni": "outbound|80||nginx.default.svc.cluster.local"
       }
   }
  • 在sleep-v1和sleep-v2的和服务nginx.default.svc.cluster.local相关的outbound cluster中,会挂载相应的证书和密钥。


测试结果

/ # curl http://nginx
RBAC: access denied/ #
/ #
/ # curl http://nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
 body {
   width: 35em;
   margin: 0 auto;
   font-family: Tahoma, Verdana, Arial, sans-serif;
 }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<h1>v1!</h1>
<p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
/ #
  • sleep-v1可以正常访问nginx-v1的服务,但在访问nginx-v2时,会发生RBAC: access denied。


/ # curl http://nginx
RBAC: access denied/ #
/ #
/ # curl http://nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
 body {
   width: 35em;
   margin: 0 auto;
   font-family: Tahoma, Verdana, Arial, sans-serif;
 }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<h1>v2!</h1>
<p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
/ #
  • sleep-v2可以正常访问nginx-v2的服务,但在访问nginx-v1时,会发生RBAC: access denied。


以上是关于使用RBAC授权的主要内容,如果未能解决你的问题,请参考以下文章

Istio数据面配置解析19:使用RBAC对Tcp连接进行授权(1.1)

RBAC授权

技术中台干货Kubernetes之RBAC授权控制

K8s:通过 kubectl 插件 rakkess 查看集群 RBAC授权信息

K8s:通过 kubectl 插件 rakkess 查看集群 RBAC授权信息

K8s:通过 kubectl 插件 rakkess 查看集群 RBAC授权信息