5步将Istio与OPA集成

认证和授权是云架构师和DevOps工程师需要解决的网络安全谜题的重要组成部分。在这篇博客中,我们将特别查看如何实现授权/访问控制;即,认证实体在Istio服务网络中可以执行哪些操作。它通过防止具有恶意意图的操作来帮助保护基础设施。

在服务网络中,可以通过OPA策略来定义授权。OPA是一个帮助DevOps人员为Kubernetes工作负载定义和执行授权策略的机制。在这篇文章中,我们将看到:

  • 什么是OPA
  • 为什么你应该将OPA与Istio服务网络集成
  • Istio和OPA如何授权请求
  • 您可以遵循的确切步骤,以将OPA与Istio集成

OPA是什么?

OPA(“Open Policy Agent”的缩写)是一个开源的通用策略执行引擎,允许DevOps使用名为Rego的高级声明性语言将策略定义为代码。OPA帮助在堆栈中集中定义和执行策略,同时减轻开发人员将授权策略编写入应用程序代码的负担。OPA的工作方式如下(请参考图1):

  1. 应用程序/服务接收到请求。
  2. 服务将JSON授权请求发送到OPA。
  3. OPA将请求与定义的授权策略进行比对。
  4. OPA做出决定,并以JSON格式将授权响应(ALLOW/DENY)返回给服务。

图1:使用OPA的授权请求流程

请注意,发送授权请求的并不一定是开发者编写的应用程序:它可以是Argo CD、Kubernetes Gateway API资源、Terraform、Prometheus或其他任何内容,因为OPA是通用目的的。 (我在这里提到了一个在Kubernetes集群中编写的应用程序,并绘制了它,以便于理解和方便。)

为什么将OPA与Istio集成?

Istio具有强大的授权机制。然而,将像OPA这样的专用策略执行引擎与Istio服务网格一起使用,它有自己的优点:

  • 集中管理系统以定义和执行策略:OPA使DevOps能够更容易地集中管理整个堆栈的授权策略。这包括meshed工作负载、非meshed堆栈,以及授权检查(例如,阻止在周五部署的策略)。 
  • 在定义策略时更加灵活和细致:如果你查看下面的表格(图2),很明显Istio授权可以做很多事,并根据来自不同数据源的各种字段匹配请求。然而,Istio AuthorizationPolicy CRD在配置HTTP请求体或字段中的任何上下文数据方面可能存在局限性,此时可以利用OPA。与Istio不同,OPA可以在策略评估中使用任何数据。
  • 简化的AuthZ配置:在Istio中配置复杂的授权规则可能对DevOps来说很繁琐。OPA使用Rego进行配置,这更接近于一种编程语言。使用Rego设置基本的到复杂的策略规则相对简单。

图 2:Istio 与 OPA 授权的表格比较(来源

Istio 和 OPA 如何授权请求

DevOps 可以将 OPA 部署为一个完全独立的服务的容器,或者作为伴随 Envoy 代理和应用程序容器在 pod 中的边车容器。采用边车容器方法可以更好地减少延迟。

OPA 边车容器需要像 Istio 的 Envoy 代理边车容器一样注入到应用程序 pod 中。我们可以设置注入的 OPA 容器挂载包含授权规则的 ConfigMaps;这样,命名空间中的每个 OPA 边车容器都将挂载相同的配置和 AuthZ 规则,这些规则定义在 ConfigMap 中。

一旦注入了 OPA 边车,当服务接收到请求时,Envoy 代理将向 OPA 发送授权请求以做出授权决策:

图 3:Istio-OPA 授权工作流程

假设 DevOps 人员不希望同一个命名空间中注入的每个 OPA 容器都遵循相同的配置,并且想要执行不同的规则。在这种情况下,他们可以执行以下操作之一:

  • 移除硬编码,让当前的注入策略使用特定的 ConfigMap
  • 配置变异 webhook 并禁用 pod 级别的边车注入
  • 从远程HTTP服务器提供策略捆绑包
  • 在不同的命名空间中部署应用程序和边车,并使用不同的ConfigMap

将OPA与Istio集成的步骤:演示

这里的想法是让OPA成为外部授权者,而不是Envoy代理边车——做出访问控制决策。

我将使用Istio文档中的经典Bookinfo应用程序进行演示。我将配置OPA与Istio进行访问控制,并检查是否通过向bookinfo/productpage发送请求来执行:

图4:Istio-OPA集成教程图

注意/productpage是UI,它对其他服务(如评论和评分服务)进行内部调用(图表)。我将向bookinfo命名空间中的每个 Pod 注入OPA;由于所有OPA容器挂载相同的ConfigMap,因此具有相同的授权策略。Bookinfo应用程序的默认行为不转发任何HTTP认证,因此内部调用将失败认证,从而导致授权失败。

我们将按照给定的步骤顺序进行:

  1. 配置OPA边车注入
  2. 启用Istio代理和OPA之间的通信
  3. 部署OPA配置
  4. 应用Istio配置
  5. 部署应用程序并测试Istio-OPA授权设置

演示的先决条件是在您的集群中安装了Istio v1.19+。我这里使用的是Istio v1.21.0。

OPA提供了一个quickstart.yaml用于简化安装。我将yaml分成了三个部分以便更容易理解:IMESH GitHub仓库

第一步:配置OPA Sidecar注入

应用opa_controller.yaml

YAML

 

kubectl apply -f opa_controller.yaml

opa_controller.yaml文件将所有内容——TLS证书、包含注入策略的ConfigMap、准入控制器部署和变异webhook配置——部署到opa-istio命名空间中(参考图5):

  1. 变异webhook控制器(opa-istio-admission-controller)将监听特定标签(opa-istio-injection)的值设置为enabled的入站请求。
  2. Webhook控制器调用admission-controller,它具有注入策略。
  3. 注入策略告诉admission-controller如何将OPA边车容器注入到Pod中。

图5:OPA边车注入配置

现在,在部署Bookinfo应用之前,我们将创建bookinfo命名空间并遵循以下步骤:

通过应用bookinfo-ns.yaml创建bookinfo命名空间:

YAML

 

kubectl apply -f bookinfo-ns.yaml

You can see the namespace has the label opa-istio-injection: enabled, to auto-inject OPA sidecars.

第二步:启用Istio代理与OPA之间的通信

编辑istio-system命名空间中的Istio ConfigMap,并添加extensionProvidersopa-ext-authz-grpc),以便在网格中启用外部授权:

  • 从opa_controller.yaml中的注释中复制extensionProviders
  • 编辑Istio ConfigMap并在网格字段中添加extensionProviders
  • 确保缩进正确。
  • 保存配置。

这一步使得istio-proxy能够与Pod中的opa-istio容器进行授权请求。

如果查看extensionProviders,它是Envoy中的ExtAuthzGrpc过滤器类型,具有指定的服务条目和端口:

YAML

 

...

extensionProviders:
- name: opa-ext-authz-grpc
envoyExtAuthzGrpc:
service: opa-ext-authz-grpc.local
       port: "9191"

...

opa_authz.yamlopa_config.yaml中,extensionProviders的名称、服务地址和端口应该保持一致。

第3步:部署OPA配置

opa_config.yaml定义了与开放策略相关的配置。它包括opa-istio-configopa-policy ConfigMaps——分别定义了gRPC服务实现(envoy_ext_authz_grpc)和实际的授权策略。

授权策略可以分为两部分:第一部分定义了授权允许或拒绝的条件;第二部分定义了用户角色以及每个角色的权限。

授权策略可能需要一些时间来适应,因为Rego在这里没有使用很多关键词。启用Rego的新版本以获得关键词(例如允许条件关键词)。

bookinfo命名空间中应用OPA配置,因为它与应用程序相伴随:

YAML

 

kubectl apply -f opa_config.yaml -n bookinfo

第4步:应用Istio配置

opa_authz.yaml文件包含Istio配置。它有一个AuthorizationPolicy和一个ServiceEntry。请注意,授权策略提供者是opa-ext-authz-grpc,这是我们在第2步中在ConfigMap中配置的extensionProvider

同样,ServiceEntry中定义的主机名与extensionProvider中给出的服务地址相同(opa-ext-authz-grpc.local)。gRPC服务将在本地主机127.0.0.1的端口9191上运行,ServiceEntry通过istio-proxy容器使opa-istio侧car在容器内部可用。

部署配置:

YAML

 

kubectl apply -f opa_authz.yaml -n bookinfo

第5步:部署应用程序并测试Istio-OPA授权设置

部署Bookinfo应用程序和网关:

YAML

 

kubectl apply -f /your_Istio_directory/samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo
kubectl apply -f /your_Istio_directory/samples/bookinfo/networking/bookinfo-gateway.yaml -n bookinfo

检查bookinfo命名空间中的pods:

YAML

 

kubectl get pods -n bookinfo

您可以看到每个pods中都有3个正在运行的容器:应用程序、Envoy代理(istio-proxy)和OPA(opa-istio)容器。

获取Istio网关的IP以访问服务:

YAML

 

kubectl get svc -n istio-system

现在一切设置完成,我们准备测试授权策略。我们在opa_config.yaml中定义的策略如下:

YAML

 

...

user_roles = {
"alice": ["guest"],
"bob": ["admin"]
}

role_perms = {
"guest": [
{"method": "GET", "path": "/productpage"},
],
"admin": [
{"method": "GET", "path": "/productpage"},
{"method": "GET", "path": "/api/v1/products"},
        ],

...

Alice是一位只能访问/productpage的访客用户;Bob是一位管理员,可以访问路径/productpage/api/v1/products。让我们验证一下策略。

尝试从Alice访问/api/v1/products

YAML

 

curl -vvv your_istio_gateway_ip/api/v1/products -u alice:password

你可以看到自从Alice没有访问路径权限以来,一直显示403 Forbidden的响应。让我们像Bob一样尝试相同的路径:

YAML

 

curl -vvv your_istio_gateway_ip/api/v1/products -u bob:password

响应显示了200 OK的HTTP状态和页面内容。

使用OPA进行访问控制的示例场景

你可以使用Istio的AuthorizationPolicy CRD来强制上述演示中的策略。你不需要OPA。然而,如开头表格中提到的,Istio授权在某些情况下可能受限。让我举一个简单的例子。

假设有一个名为BookReviews的应用程序,它是一个GraphQL服务,其中评论者提交评论,编辑编辑并发布这些评论,用户阅读已发布的评论。

当评论者将书评添加到服务时,请求将包括评论者的JWT,其中包含评论者所属的组和角色(评论者或编辑)。请求体还将包含一个包含新创建评论数据的GraphQL突变查询。

让我们假设你想确保以下条件:

  • 只有评论者可以提交评论。
  • 只有当评论是由属于他们管理的同一组的评论者撰写时,编辑才能编辑评论。
  • 只有编辑才能将评论标记为“准备发布”。

以下是包括上述策略的图表:

Istio的AuthorizationPolicy将难以强制执行上述条件。原因是Istio无法使用GraphQL请求体进行授权检查,这是一个JSON对象,与用于策略评估的JWT一起需要。

OPA没有这样的限制。它可以加载任何数据进行策略检查,并且DevOps可以使用Rego以更人性化的方式编写这些规则。

视频:实际演示

如果您更愿意观看实际演示,请查看下面的视频:S

企业对集成Istio的支持

大多数企业使用OPA来定义和强制执行整个堆栈的授权策略。拥有一个集中的访问控制机制可以提高整体安全和IT团队的敏捷性。否则,开发人员将浪费时间将授权策略开发到用特定语言编写的应用程序代码中,这阻碍了可伸缩性和更快的业务逻辑推出。

Source:
https://dzone.com/articles/5-steps-to-integrate-istio-with-opa