[译] 在 Istio Ambient Mesh 中集成 Open Policy Agent (OPA) 实现细粒度授权

本文介绍了如何在 Istio Ambient Mesh 中集成 Open Policy Agent (OPA),实现更强大的外部授权服务。通过 OPA,用户可以定义和执行细粒度的访问控制策略,超越 Istio 内置的授权功能。文章涵盖了 OPA 部署、集群配置以及示例应用,帮助用户在 Ambient Mesh 中轻松实现安全性和灵活性。

声明
此文为个人翻译,仅供参考,不代表我个人立场。翻译过程中可能有删改或遗漏,如需了解原文,请自行查阅。如有疏漏,欢迎指正。
查看本文大纲

这是关于在 Istio Ambient Mesh 中使用 Open Policy Agent (OPA) 的系列文章的第一篇。系列文章将涵盖如何使用 OPA 作为外部授权服务,建议的部署模式,以及提高可靠性和可扩展性的最佳架构。我们还将讨论使用 OPA 进行资源验证和控制 Istio 功能。

正如我在之前的文章中提到的,我对 Istio Ambient Mesh 感到非常兴奋。这是服务网格的显著进步,我致力于帮助大家理解如何利用 Ambient 来实现目标。我认为目前关于 Ambient 的用例和教程内容还比较少,我希望能帮助填补这个空白。

本文将介绍如何在 Istio Ambient Mesh 中设置 Open Policy Agent (OPA) 作为外部授权服务。授权是任何安全模型的重要组成部分,而 OPA 是实现细粒度访问控制策略的强大工具。通过将 OPA 用作外部授权服务,你可以强制执行比 Istio 内置授权策略更复杂的策略。

OPA 具有插件模型,允许在基础策略引擎之上添加额外功能。虽然这是一个复杂的用例,但幸运的是,OPA 社区已经创建并维护了实现 Envoy 外部授权 API 的 OPA 引擎版本。因此,你无需编写任何自定义代码即可在 Istio Ambient Mesh 中使用 OPA 作为外部授权服务。

集群架构图

image
OPA 和 Istio Ambient

在上图中,你可以看到我们集群中的资源架构。我们有三个命名空间:默认的 istio-system 命名空间(Istio 控制平面 istiod 和 ztunnel 代理运行的地方)、安装示例应用的 app 命名空间,以及 OPA 运行的 platform 命名空间。在这个例子中,我们将 OPA 部署为单个 Deployment。在后续文章中,我会介绍如何将 OPA 部署为 DaemonSet。

带有流量的集群架构图

image
OPA 和 Istio Ambient(带有流量)

上图展示了与之前相同的集群,但此时有流量通过系统。在本教程中,我们将发送流量到 app 命名空间中的 Waypoint 代理,该代理会向 platform 命名空间中的 OPA 服务进行授权检查。OPA 服务根据定义的策略返回决策,允许或拒绝请求。如果请求被允许,Waypoint 代理会将请求转发到 app 命名空间中的目标服务,否则将返回 403 Forbidden 响应。

集群安装与配置

首先,让我们创建集群并使用 Ambient 模式安装 Istio,以及 Kubernetes Gateway API:

# 创建集群
kind create cluster --name istio-opa

# 使用 Ambient 模式安装 Istio
istioctl install --set profile=ambient --skip-confirmation

# 安装 gateway-api CRD
kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
    { kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml; }

接下来,创建 app 命名空间并安装 Istio 的 bookinfo 示例应用及 sleep Pod,这将帮助我们进行集群内的测试:

# 创建命名空间
kubectl create namespace app

# 安装 bookinfo 示例应用
kubectl apply -n app -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/bookinfo/platform/kube/bookinfo.yaml
kubectl apply -n app -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/bookinfo/platform/kube/bookinfo-versions.yaml

# 安装 sleep 应用
kubectl apply -n app -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/sleep/sleep.yaml

我们还需要创建 Waypoint 代理,作为集群入口网关,并为 app 命名空间配置 Ambient 模式:

# 为 productpage 应用创建网关
kubectl apply -n app -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/bookinfo/gateway-api/bookinfo-gateway.yaml
istioctl waypoint apply -n app --enroll-namespace --wait

# 为网关添加 ClusterIP 类型
kubectl annotate gateway bookinfo-gateway networking.istio.io/service-type=ClusterIP --namespace=app

# 将命名空间标记为 Ambient 模式
kubectl label namespace app istio.io/dataplane-mode=ambient

接下来,创建 platform 命名空间来运行 OPA 服务:

kubectl create namespace platform

部署 Open Policy Agent

首先,部署 OPA:

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: opa-istio
  namespace: platform
spec:
  replicas: 1
  selector:
    matchLabels:
      app: opa-istio
  template:
    metadata:
      labels:
        app: opa-istio
    spec:
      containers:
      - name: opa-istio
        image: openpolicyagent/opa:0.68.0-istio-4-static
        ports:
        - containerPort: 9191
        - containerPort: 8282
        - containerPort: 8181
        args:
        - "run"
        - "--server"
        - "--addr=0.0.0.0:8181"
        - "--config-file=/config/config.yaml"
        - "/policy/policy.rego"
        volumeMounts:
        - name: opa-istio-config
          mountPath: /config
        - name: opa-policy
          mountPath: /policy
EOF

接着,我们需要定义两个 ConfigMap 来配置 OPA:

kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: opa-istio-config
  namespace: platform
data:
  config.yaml: |
    plugins:
      envoy_ext_authz_grpc:
        addr: 0.0.0.0:9191
        path: istio/authz/allow
    decision_logs:
      console: true
EOF
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: opa-policy
  namespace: platform
data:
  policy.rego: |
    package istio.authz
    import input.attributes.request.http as http_request
    import input.parsed_path
    default allow = false
    allow { roles_for_user[r] required_roles[r] }
    roles_for_user[r] { r := user_roles[user_name][_] }
    required_roles[r] { perm := role_perms[r][_] perm.method = http_request.method perm.path = http_request.path }
    user_name = parsed { [_, encoded] := split(http_request.headers.authorization, " ") [parsed, _] := split(base64url.decode(encoded), ":") }
    user_roles = { "alice": ["guest"], "bob": ["admin"] }
    role_perms = { "guest": [ { "method": "GET", "path": "/productpage" }, ], "admin": [ { "method": "GET", "path": "/productpage" }, { "method": "GET", "path": "/api/v1/products" }, ], }
EOF

最后,为 OPA 创建服务并配置 Istio MeshConfig:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: opa-istio
  namespace: platform
spec:
  ports:
  - name: grpc
    port: 9191
    targetPort: 9191
  selector:
    app: opa-istio
EOF

编辑 Istio MeshConfig,将 OPA 注册为 extensionProvider

apiVersion: v1
kind: ConfigMap
metadata:
  name: istio
  namespace: istio-system
data:
  mesh: |-
    extensionProviders:
    - name: opa-ext-authz-grpc
      envoyExtAuthzGrpc:
        service: opa-istio.platform.svc.cluster.local
        port: 9191

测试

通过 kubectl port-forward 命令,将 bookinfo-gateway 服务的端口转发到本地:

kubectl port-forward -n app svc/bookinfo-gateway-istio 8080:80

然后,使用 Alice 和 Bob 用户发送请求,验证不同权限的访问控制:

curl --user alice:password -vik http://localhost

:8080/api/v1/products # 应返回 403
curl --user alice:password -vik http://localhost:8080/productpage # 应返回 HTML 响应
curl --user bob:password -vik http://localhost:8080/api/v1/products # 应返回 JSON 响应
curl --user bob:password -vik http://localhost:8080/productpage # 应返回 HTML 响应

最后,应用 Istio 的 AuthorizationPolicy

kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: ext-authz
  namespace: app
spec:
  action: CUSTOM
  provider:
    name: opa-ext-authz-grpc
  rules:
  - to:
    - operation:
        paths: ["*"]
EOF

通过上述步骤,你已经成功配置了 OPA 作为 Istio Ambient Mesh 中的外部授权服务。在后续文章中,我们将讨论 OPA 在 Waypoint 代理中的最佳实践。

最后更新于 2024/10/15