外部授权
概述
外部授权允许将传入 HTTP 请求的授权卸载到可能不在代理上下文中运行的远程端点。
支持外部授权的代理将针对每个请求向远程端点发起权限检查。由于系统可能拥有大量 RPS,外部授权有许多可调整的设置,以允许或多或少的控制,但会牺牲性能(仅发送 HTTP 有效负载或标头、超时、授权无法回复时的默认行为等等)。
OSM 允许通过 OSM MeshConfig 来配置 Envoy 的 外部授权扩展
局限性
目前,授权过滤不能动态配置为安装在用户定义的代理子集或代理组中,而是在启用时全局应用于网格中的所有服务。
类似地,过滤方向将静态应用于网格内的 inbound
和 outbound
连接,启用后会影响对网格中的任何服务或应用程序发出的所有 HTTP 请求。
OSM 与 OPA 插件外部授权演练
以下部分将记录如何结合 opa-envoy-plugin
配置外部授权。
我们强烈建议先阅读 OPA envoy 插件 的文档,以进一步了解其配置选项和部署模型。
以下示例使用单个远程(通过网络)端点来验证所有流量。不建议将此配置用于生产部署。
- 首先,从部署 OSM 的 Demo 开始。我们将使用此示例部署来测试外部授权功能。请参考 OSM的自动化Demo并按照说明操作。
# Assuming OSM repo is available
cd <PATH_TO_OSM_REPO>
demo/run-osm-demo.sh # wait for all services to come up
- 当 OSM 的演示启动并运行时,继续部署
opa-envoy-plugin
。OSM 提供了 [整理好的独立 opa-envoy-plugin 部署 chart](https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/opa/deploy-opa-envoy.yaml),它通过服务公开opa-envoy-plugin
的 gRPC 端口(默认为9191
)。这是 OSM 在启用外部授权时将配置代理的端点。下面的代码片段创建了一个opa
命名空间,并在其中部署了opa-envoy-plugin
,并使用了最少的 deny-all 配置:
kubectl create namespace opa
kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/opa/deploy-opa-envoy.yaml
- 一旦 OSM 示例启动并运行,修改 OSM MeshConfig 添加网格的外部授权。为此,配置
inboundExternalAuthorization
指向远程外部授权端点,如下所示:
kubectl edit meshconfig osm-mesh-config -n osm-system
## <scroll to the following section>
...
inboundExternalAuthorization:
enable: true
address: opa.opa.svc.cluster.local
port: 9191
failureModeAllow: false
statPrefix: inboundExtAuthz
timeout: 1s
...
- 这一步执行完,OSM 应该配置所有代理依赖外部授权服务用于授权决策。默认情况下,
opa-envoy-plugin
提供的配置会拒绝所有访问网格内服务的请求。可以通过检查网格中的任一服务的日志来验证,应该有403 Forbidden
:
kubectl logs <bookbuyer_pod> -n bookbuyer bookbuyer
...
--- bookbuyer:[ 8 ] -----------------------------------------
Fetching http://bookstore.bookstore:14001/books-bought
Request Headers: map[Client-App:[bookbuyer] User-Agent:[Go-http-client/1.1]]
Identity: n/a
Booksbought: n/a
Server: envoy
Date: Tue, 04 May 2021 01:20:39 GMT
Status: 403 Forbidden
ERROR: response code for "http://bookstore.bookstore:14001/books-bought" is 403; expected 200
...
- 要进一步验证外部授权是否有效,请验证
opa-envoy-plugin
实例的日志。实例的日志应该包含 json blob,它记录收到的每个请求的评估 - 键值result
应该出现在由提供给opa-envoy-plugin
实例的配置所采取的授权结果中:
kubectl logs <opa_pod_name> -n opa
...
{"decision_id":"1df154b5-658a-47bf-ac18-be52998605da"
...
"result":false, // resulting decision
...
"time":"2021-05-04T01:21:18Z","timestamp":"2021-05-04T01:21:18.1971808Z","type":"openpolicyagent.org/decision_logs"
}
- 验证上一步后,继续更改 OPA 策略配置以默认授权所有流量:
kubectl edit configmap opa-policy -n opa
...
...
default allow = false
将上一行值更改为 true
:
default allow = true
- 最后,重新启动
opa-envoy-plugin
。这是一个必要的步骤,因为此 deployment 的配置是作为配置推送的,而不是应用程序拉取它。
kubectl rollout restart deployment opa -n opa
- 验证对
bookbuyer
服务的请求现在是否已获得授权:
--- bookbuyer:[ 2663 ] -----------------------------------------
Fetching http://bookstore.bookstore:14001/books-bought
Request Headers: map[Client-App:[bookbuyer] User-Agent:[Go-http-client/1.1]]
Identity: bookstore-v1
Booksbought: 1087
Server: envoy
Date: Tue, 04 May 2021 02:00:46 GMT
Status: 200 OK
MAESTRO! THIS TEST SUCCEEDED!
Fetching http://bookstore.bookstore:14001/buy-a-book/new
Request Headers: map[]
Identity: bookstore-v1
Booksbought: 1088
Server: envoy
Date: Tue, 04 May 2021 02:00:47 GMT
Status: 200 OK
ESC[90m2:00AMESC[0m ESC[32mINFESC[0m BooksCountV1=21490056 ESC[36mcomponent=ESC[0mdemo ESC[36mfile=ESC[0mbooks.go:167
MAESTRO! THIS TEST SUCCEEDED!
可以重新验证 OPA 插件的输出,以确保为每个请求做出策略决策:
{"decision_id":"3f29d449-7f71-4721-b93c-ad7d375e0f80",
...
"result":true,
...
"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 官方文档。