外部授权

概述

外部授权允许将传入 HTTP 请求的授权卸载到可能不在代理上下文中运行的远程端点。

支持外部授权的代理将针对每个请求向远程端点发起权限检查。由于系统可能拥有大量 RPS,外部授权有许多可调整的设置,以允许或多或少的控制,但会牺牲性能(仅发送 HTTP 有效负载或标头、超时、授权无法回复时的默认行为等等)。

OSM 允许通过 OSM MeshConfig 来配置 Envoy 的 外部授权扩展

局限性

目前,授权过滤不能动态配置为安装在用户定义的代理子集或代理组中,而是在启用时全局应用于网格中的所有服务。

类似地,过滤方向将静态应用于网格内的 inboundoutbound 连接,启用后会影响对网格中的任何服务或应用程序发出的所有 HTTP 请求。

OSM 与 OPA 插件外部授权演练

以下部分将记录如何结合 opa-envoy-plugin 配置外部授权。

我们强烈建议先阅读 OPA envoy 插件 的文档,以进一步了解其配置选项和部署模型。

以下示例使用单个远程(通过网络)端点来验证所有流量。不建议将此配置用于生产部署。

  • 首先,从部署 OSM 的 Demo 开始。我们将使用此示例部署来测试外部授权功能。请参考 OSM的自动化Demo并按照说明操作。
  1. # Assuming OSM repo is available
  2. cd <PATH_TO_OSM_REPO>
  3. demo/run-osm-demo.sh # wait for all services to come up
  1. kubectl create namespace opa
  2. kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/opa/deploy-opa-envoy.yaml
  • 一旦 OSM 示例启动并运行,修改 OSM MeshConfig 添加网格的外部授权。为此,配置 inboundExternalAuthorization 指向远程外部授权端点,如下所示:
  1. kubectl edit meshconfig osm-mesh-config -n osm-system
  2. ## <scroll to the following section>
  3. ...
  4. inboundExternalAuthorization:
  5. enable: true
  6. address: opa.opa.svc.cluster.local
  7. port: 9191
  8. failureModeAllow: false
  9. statPrefix: inboundExtAuthz
  10. timeout: 1s
  11. ...
  • 这一步执行完,OSM 应该配置所有代理依赖外部授权服务用于授权决策。默认情况下,opa-envoy-plugin 提供的配置会拒绝所有访问网格内服务的请求。可以通过检查网格中的任一服务的日志来验证,应该有 403 Forbidden
  1. kubectl logs <bookbuyer_pod> -n bookbuyer bookbuyer
  1. ...
  2. --- bookbuyer:[ 8 ] -----------------------------------------
  3. Fetching http://bookstore.bookstore:14001/books-bought
  4. Request Headers: map[Client-App:[bookbuyer] User-Agent:[Go-http-client/1.1]]
  5. Identity: n/a
  6. Booksbought: n/a
  7. Server: envoy
  8. Date: Tue, 04 May 2021 01:20:39 GMT
  9. Status: 403 Forbidden
  10. ERROR: response code for "http://bookstore.bookstore:14001/books-bought" is 403; expected 200
  11. ...
  • 要进一步验证外部授权是否有效,请验证 opa-envoy-plugin 实例的日志。实例的日志应该包含 json blob,它记录收到的每个请求的评估 - 键值 result 应该出现在由提供给 opa-envoy-plugin 实例的配置所采取的授权结果中:
  1. kubectl logs <opa_pod_name> -n opa
  2. ...
  3. {"decision_id":"1df154b5-658a-47bf-ac18-be52998605da"
  4. ...
  5. "result":false, // resulting decision
  6. ...
  7. "time":"2021-05-04T01:21:18Z","timestamp":"2021-05-04T01:21:18.1971808Z","type":"openpolicyagent.org/decision_logs"
  8. }
  • 验证上一步后,继续更改 OPA 策略配置以默认授权所有流量:
  1. kubectl edit configmap opa-policy -n opa
  2. ...
  3. ...
  4. default allow = false

将上一行值更改为 true

  1. default allow = true
  • 最后,重新启动 opa-envoy-plugin。这是一个必要的步骤,因为此 deployment 的配置是作为配置推送的,而不是应用程序拉取它。
  1. kubectl rollout restart deployment opa -n opa
  • 验证对 bookbuyer 服务的请求现在是否已获得授权:
  1. --- bookbuyer:[ 2663 ] -----------------------------------------
  2. Fetching http://bookstore.bookstore:14001/books-bought
  3. Request Headers: map[Client-App:[bookbuyer] User-Agent:[Go-http-client/1.1]]
  4. Identity: bookstore-v1
  5. Booksbought: 1087
  6. Server: envoy
  7. Date: Tue, 04 May 2021 02:00:46 GMT
  8. Status: 200 OK
  9. MAESTRO! THIS TEST SUCCEEDED!
  10. Fetching http://bookstore.bookstore:14001/buy-a-book/new
  11. Request Headers: map[]
  12. Identity: bookstore-v1
  13. Booksbought: 1088
  14. Server: envoy
  15. Date: Tue, 04 May 2021 02:00:47 GMT
  16. Status: 200 OK
  17. ESC[90m2:00AMESC[0m ESC[32mINFESC[0m BooksCountV1=21490056 ESC[36mcomponent=ESC[0mdemo ESC[36mfile=ESC[0mbooks.go:167
  18. MAESTRO! THIS TEST SUCCEEDED!

可以重新验证 OPA 插件的输出,以确保为每个请求做出策略决策:

  1. {"decision_id":"3f29d449-7f71-4721-b93c-ad7d375e0f80",
  2. ...
  3. "result":true,
  4. ...
  5. "time":"2021-05-04T02:01:35Z","timestamp":"2021-05-04T02:01:35.816768454Z","type":"openpolicyagent.org/decision_logs"}

此示例规则展示了如何使用 OPA 插件对网络流量实施授权策略,但不适用于生产部署。例如,以这种方式对每个 HTTP 调用执行授权会增加大量开销,使用 OPA 注入器可以减少开销。有关使用 OPA 的更多信息,请参阅 Open Policy Agent 官方文档