外部授權 (ext_authz) 過濾器

外部授權沙箱示範了 Envoy 的 ext_authz 過濾器 功能,可將通過 Envoy 的傳入請求的授權委派給外部服務。

雖然 ext_authz 也可用作網路過濾器,但此沙箱僅限於展示 ext_authz HTTP 過濾器,該過濾器支援呼叫 HTTP 或 gRPC 服務。

此沙箱的設定與前端代理部署非常相似,但是對代理後面上游服務的呼叫將由外部 HTTP 或 gRPC 服務檢查。在此沙箱中,對於每個授權的呼叫,外部授權服務都會將額外的 x-current-user 標頭項目新增到要轉發到上游服務的原始請求標頭中。

步驟 1:啟動所有容器

變更為 examples/ext_authz 目錄。

若要建置此沙箱範例並啟動範例服務,請執行以下命令

$ pwd
envoy/examples/ext_authz
$ docker compose pull
$ docker compose up --build -d
$ docker compose ps

               Name                             Command               State                   Ports
--------------------------------------------------------------------------------------------------------------------
ext_authz_ext_authz-grpc-service_1   /app/server -users /etc/us       Up
ext_authz_ext_authz-http-service_1   docker-entrypoint.sh node        Up
ext_authz_front-envoy_1              /docker-entrypoint.sh /bin       Up           10000/tcp, 0.0.0.0:8000->8000/tcp
ext_authz_upstream-service_1         python3 /code/service.py         Up (healthy)

注意

此沙箱具有由 FRONT_ENVOY_YAML 環境變數控制的多個設定,該變數指向要使用的有效 Envoy 配置。FRONT_ENVOY_YAML 的預設值可以在 .env 檔案中定義,或在執行 docker compose up 命令時內嵌提供。

如需更多資訊,請參閱 Compose 文件中的環境變數

預設情況下,FRONT_ENVOY_YAML 指向 config/grpc-service/v3.yaml 檔案,該檔案使用 ext_authz HTTP 過濾器和 gRPC 服務 V3 啟動前端 Envoy (這由 transport_api_version 欄位 指定)。

FRONT_ENVOY_YAML 的可能值可以在 config 目錄中找到。

例如,若要使用帶有 HTTP 服務的 ext_authz HTTP 過濾器執行 Envoy,則會是

$ pwd
envoy/examples/ext_authz
$ docker compose pull
$ # Tearing down the currently running setup
$ docker compose down
$ FRONT_ENVOY_YAML=config/http-service.yaml docker compose up --build -d
$ # Or you can update the .env file with the above FRONT_ENVOY_YAML value, so you don't have to specify it when running the "up" command.

步驟 4:存取前端 Envoy 後面的上游服務

您現在可以嘗試通過前端 Envoy 向上游服務發送請求,如下所示

$ curl -v localhost:8000/service
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /service HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< date: Fri, 19 Jun 2020 15:02:24 GMT
< server: envoy
< content-length: 0

如所觀察,請求失敗,並顯示 403 Forbidden 狀態碼。發生這種情況是因為 Envoy 採用的 ext_authz 過濾器拒絕了呼叫。若要讓請求到達上游服務,您需要通過 Authorization 標頭提供 Bearer 權杖。

注意

完整的用戶列表在 auth/users.json 檔案中定義。例如,以下範例中使用的 token1 對應於 user1

成功的請求範例可以觀察如下

$ curl -v -H "Authorization: Bearer token1" localhost:8000/service
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /service HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.58.0
> Accept: */*
> Authorization: Bearer token1
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 24
< server: envoy
< date: Fri, 19 Jun 2020 15:04:29 GMT
< x-envoy-upstream-service-time: 2
<
* Connection #0 to host localhost left intact
Hello user1 from behind Envoy!

我們還可以採用 Open Policy Agent 伺服器 (啟用 envoy_ext_authz_grpc 外掛程式) 作為授權伺服器。若要執行此範例

$ pwd
envoy/examples/ext_authz
$ docker compose pull
$ # Tearing down the currently running setup
$ docker compose down
$ FRONT_ENVOY_YAML=config/opa-service/v3.yaml docker compose up --build -d

向 (通過前端 Envoy) 的上游服務發送請求會產生

$ curl localhost:8000/service --verbose
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8000 (#0)
> GET /service HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 28
< server: envoy
< date: Thu, 02 Jul 2020 06:29:58 GMT
< x-envoy-upstream-service-time: 2
<
* Connection #0 to host localhost left intact
Hello OPA from behind Envoy!

從日誌中,我們可以觀察到來自 Open Policy Agent 伺服器的策略決策訊息 (對於上述針對 config/opa-service/policy.rego 中定義的策略的請求)

$ docker compose logs ext_authz-opa-service | grep decision_id -A 30
ext_authz-opa-service_1   |   "decision_id": "8143ca68-42d8-43e6-ade6-d1169bf69110",
ext_authz-opa-service_1   |   "input": {
ext_authz-opa-service_1   |     "attributes": {
ext_authz-opa-service_1   |       "destination": {
ext_authz-opa-service_1   |         "address": {
ext_authz-opa-service_1   |           "Address": {
ext_authz-opa-service_1   |             "SocketAddress": {
ext_authz-opa-service_1   |               "PortSpecifier": {
ext_authz-opa-service_1   |                 "PortValue": 8000
ext_authz-opa-service_1   |               },
ext_authz-opa-service_1   |               "address": "172.28.0.6"
ext_authz-opa-service_1   |             }
ext_authz-opa-service_1   |           }
ext_authz-opa-service_1   |         }
ext_authz-opa-service_1   |       },
ext_authz-opa-service_1   |       "metadata_context": {},
ext_authz-opa-service_1   |       "request": {
ext_authz-opa-service_1   |         "http": {
ext_authz-opa-service_1   |           "headers": {
ext_authz-opa-service_1   |             ":authority": "localhost:8000",
ext_authz-opa-service_1   |             ":method": "GET",
ext_authz-opa-service_1   |             ":path": "/service",
ext_authz-opa-service_1   |             "accept": "*/*",
ext_authz-opa-service_1   |             "user-agent": "curl/7.64.1",
ext_authz-opa-service_1   |             "x-forwarded-proto": "http",
ext_authz-opa-service_1   |             "x-request-id": "b77919c0-f1d4-4b06-b444-5a8b32d5daf4"
ext_authz-opa-service_1   |           },
ext_authz-opa-service_1   |           "host": "localhost:8000",
ext_authz-opa-service_1   |           "id": "16617514055874272263",
ext_authz-opa-service_1   |           "method": "GET",
ext_authz-opa-service_1   |           "path": "/service",

嘗試發送方法不是 GET 的請求會導致拒絕

$ curl -X POST localhost:8000/service --verbose
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8000 (#0)
> PUT /service HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< date: Thu, 02 Jul 2020 06:46:13 GMT
< server: envoy
< content-length: 0

另請參閱

ext_authz 過濾器

了解有關使用 Envoy 的 ext_authz 過濾器的更多資訊。

Open Policy Agent

適用於雲原生環境的基於策略的控制。

envoy_ext_authz_grpc

Open Policy Agent Envoy 外掛程式。

Compose 文件中的環境變數.

有關使用 Docker Compose 環境變數的更多資訊。