Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 103 additions & 1 deletion plugins/wasm-go/extensions/ext-auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,18 @@ description: Ext 认证插件实现了调用外部授权服务进行认证鉴权
| 名称 | 数据类型 | 必填 | 默认值 | 描述 |
|--------------------------|------------------------|------|--------|--------------------------------------------------------------|
| `allowed_headers` | array of StringMatcher | 否 | - | 设置后,匹配项的客户端请求头将添加到授权服务请求中的请求头中。除了用户自定义的头部匹配规则外,授权服务请求中会自动包含 `Authorization` 这个HTTP头(`endpoint_mode` 为 `forward_auth` 时,会添加 `X-Forwarded-*` 的请求头) |
| `allowed_properties` | array of AllowedProperty | 否 | - | 设置后将把 Envoy filter state 中的 property 映射为 HTTP header 发送给授权服务 |
| `headers_to_add` | map[string]string | 否 | - | 设置将包含在授权服务请求中的请求头列表。请注意,同名的客户端请求头将被覆盖 |
| `with_request_body` | bool | 否 | false | 缓冲客户端请求体,并将其发送至鉴权请求中(HTTP Method为GET、OPTIONS、HEAD请求时不生效) |
| `max_request_body_bytes` | int | 否 | 10MB | 设置在内存中保存客户端请求体的最大尺寸。当客户端请求体达到在此字段中设置的数值时,将会返回HTTP 413状态码,并且不会启动授权过程。注意,这个设置会优先于 `failure_mode_allow` 的配置 |

`AllowedProperty` 类型每一项的配置字段说明

| 名称 | 数据类型 | 必填 | 默认值 | 描述 |
|------------|----------|------|--------|--------------------------------------------------------------|
| `path` | array of string | 是 | - | 属性路径,如 `["route_name"]` 或 `["metadata", "user_id"]` |
| `header` | string | 是 | - | 映射到的请求头名称 |

`authorization_response` 中每一项的配置字段说明

| 名称 | 数据类型 | 必填 | 默认值 | 描述 |
Expand Down Expand Up @@ -235,7 +243,52 @@ Content-Length: 0

`ext-auth` 服务返回响应头中如果包含 `x-user-id` 和 `x-auth-version`,网关调用upstream时的请求中会带上这两个请求头

#### 示例3:传递路由名称到授权服务

`ext-auth` 插件的配置:

```yaml
http_service:
authorization_request:
allowed_headers:
- exact: x-auth-version
allowed_properties:
- path: [route_name]
header: x-route-name
headers_to_add:
x-envoy-header: true
authorization_response:
allowed_upstream_headers:
- exact: x-user-id
- exact: x-auth-version
endpoint_mode: envoy
endpoint:
service_name: ext-auth.backend.svc.cluster.local
service_host: my-domain.local
service_port: 8090
path_prefix: /auth
timeout: 1000
```

使用如下请求网关,当开启 `ext-auth` 插件后:

```shell
curl -X POST http://localhost:8082/users?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5 -X GET -H "foo: bar" -H "Authorization: xxx"
```

`ext-auth` 服务将接收到如下的鉴权请求:

```
POST /auth/users?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5 HTTP/1.1
Host: my-domain.local
Authorization: xxx
X-Auth-Version: 1.0
x-envoy-header: true
Content-Length: 0
X-Route-Name: your-route-name
```

通过 `allowed_properties` 配置,可以将 Envoy filter state 中的 `route_name` 等属性映射为 HTTP header 发送给授权服务,便于授权服务根据路由信息进行鉴权决策。

### endpoint_mode为forward_auth时

Expand Down Expand Up @@ -340,4 +393,53 @@ x-envoy-header: true
Content-Length: 0
```

`ext-auth` 服务返回响应头中如果包含 `x-user-id` 和 `x-auth-version`,网关调用upstream时的请求中会带上这两个请求头
`ext-auth` 服务返回响应头中如果包含 `x-user-id` 和 `x-auth-version`,网关调用upstream时的请求中会带上这两个请求头

#### 示例3:传递路由名称到授权服务

`ext-auth` 插件的配置:

```yaml
http_service:
authorization_request:
allowed_headers:
- exact: x-auth-version
allowed_properties:
- path: [route_name]
header: x-route-name
authorization_response:
allowed_upstream_headers:
- exact: x-mse-consumer
- exact: x-ext-auth-user
endpoint_mode: forward_auth
endpoint:
service_name: ext-auth.backend.svc.cluster.local
service_port: 8090
path: /auth
request_method: POST
timeout: 1000
```

使用如下请求网关,当开启 `ext-auth` 插件后:

```shell
curl -i http://localhost:8082/users?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5 -X GET -H "foo: bar" -H "Authorization: xxx" -H "X-Auth-Version: 1.0" -H "Host: foo.bar.com"
```

`ext-auth` 服务将接收到如下的鉴权请求:

```
POST /auth HTTP/1.1
Host: my-domain.local
Authorization: xxx
X-Forwarded-Proto: HTTP
X-Forwarded-Host: foo.bar.com
X-Forwarded-Uri: /users?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5
X-Forwarded-Method: GET
X-Auth-Version: 1.0
x-envoy-header: true
X-Route-Name: your-route-name
Content-Length: 0
```

通过 `allowed_properties` 配置,可以将 Envoy filter state 中的 `route_name` 等属性映射为 HTTP header 发送给授权服务,便于授权服务根据路由信息进行鉴权决策。
106 changes: 105 additions & 1 deletion plugins/wasm-go/extensions/ext-auth/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,18 @@ Configuration fields for each item in `authorization_request`
| Name | Data Type | Required | Default Value | Description |
| --- | --- | --- | --- | --- |
| `allowed_headers` | array of StringMatcher | No | - | After setting, the client request headers that match the items will be added to the request headers in the authorization service request. In addition to the user-defined header matching rules, the `Authorization` HTTP header will be automatically included in the authorization service request (when `endpoint_mode` is `forward_auth`, the `X-Forwarded-*` request headers will be added) |
| `allowed_properties` | array of AllowedProperty | No | - | When set, Envoy filter state properties will be mapped to HTTP headers and sent to the authorization service |
| `headers_to_add` | map[string]string | No | - | Sets the list of request headers to be included in the authorization service request. Please note that the client request headers with the same name will be overwritten |
| `with_request_body` | bool | No | false | Buffer the client request body and send it to the authentication request (not effective for HTTP Method GET, OPTIONS, HEAD requests) |
| `max_request_body_bytes` | int | No | 10MB | Sets the maximum size of the client request body to be saved in memory. When the client request body reaches the value set in this field, an HTTP 413 status code will be returned and the authorization process will not be started. Note that this setting takes precedence over the `failure_mode_allow` configuration |

Configuration fields for each item of `AllowedProperty` type

| Name | Data Type | Required | Default Value | Description |
| --- | --- | --- | --- | --- |
| `path` | array of string | Yes | - | Property path, e.g., `["route_name"]` or `["metadata", "user_id"]` |
| `header` | string | Yes | - | The request header name to map the property to |

Configuration fields for each item in `authorization_response`

| Name | Data Type | Required | Default Value | Description |
Expand Down Expand Up @@ -236,6 +244,53 @@ Content-Length: 0

If the response headers returned by the `ext-auth` service contain `x-user-id` and `x-auth-version`, these two headers will be included in the request when the gateway calls the upstream.

#### Example 3: Passing Route Name to Authorization Service

Configuration of the `ext-auth` plugin:

```yaml
http_service:
authorization_request:
allowed_headers:
- exact: x-auth-version
allowed_properties:
- path: [route_name]
header: x-route-name
headers_to_add:
x-envoy-header: true
authorization_response:
allowed_upstream_headers:
- exact: x-user-id
- exact: x-auth-version
endpoint_mode: envoy
endpoint:
service_name: ext-auth.backend.svc.cluster.local
service_host: my-domain.local
service_port: 8090
path_prefix: /auth
timeout: 1000
```

When using the following request to the gateway after enabling the `ext-auth` plugin:

```shell
curl -X POST http://localhost:8082/users?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5 -X GET -H "foo: bar" -H "Authorization: xxx"
```

The `ext-auth` service will receive the following authorization request:

```
POST /auth/users?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5 HTTP/1.1
Host: my-domain.local
Authorization: xxx
X-Auth-Version: 1.0
x-envoy-header: true
Content-Length: 0
X-Route-Name: your-route-name
```

By configuring `allowed_properties`, you can map Envoy filter state properties like `route_name` to HTTP headers and send them to the authorization service, enabling the authorization service to make decisions based on routing information.

### When endpoint_mode is forward_auth

#### Example 1
Expand Down Expand Up @@ -339,4 +394,53 @@ x-envoy-header: true
Content-Length: 0
```

If the response headers returned by the `ext-auth` service contain `x-user-id` and `x-auth-version`, these two headers will be included in the request when the gateway calls the upstream.
If the response headers returned by the `ext-auth` service contain `x-user-id` and `x-auth-version`, these two headers will be included in the request when the gateway calls the upstream.

#### Example 3: Passing Route Name to Authorization Service

Configuration of the `ext-auth` plugin:

```yaml
http_service:
authorization_request:
allowed_headers:
- exact: x-auth-version
allowed_properties:
- path: [route_name]
header: x-route-name
authorization_response:
allowed_upstream_headers:
- exact: x-mse-consumer
- exact: x-ext-auth-user
endpoint_mode: forward_auth
endpoint:
service_name: ext-auth.backend.svc.cluster.local
service_port: 8090
path: /auth
request_method: POST
timeout: 1000
```

When using the following request to the gateway after enabling the `ext-auth` plugin:

```shell
curl -i http://localhost:8082/users?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5 -X GET -H "foo: bar" -H "Authorization: xxx" -H "X-Auth-Version: 1.0" -H "Host: foo.bar.com"
```

The `ext-auth` service will receive the following authorization request:

```
POST /auth HTTP/1.1
Host: my-domain.local
Authorization: xxx
X-Forwarded-Proto: HTTP
X-Forwarded-Host: foo.bar.com
X-Forwarded-Uri: /users?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5
X-Forwarded-Method: GET
X-Auth-Version: 1.0
x-envoy-header: true
X-Route-Name: your-route-name
Content-Length: 0
```

By configuring `allowed_properties`, you can map Envoy filter state properties like `route_name` to HTTP headers and send them to the authorization service, enabling the authorization service to make decisions based on routing information.
43 changes: 43 additions & 0 deletions plugins/wasm-go/extensions/ext-auth/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ type AuthorizationRequest struct {
HeadersToAdd map[string]string
WithRequestBody bool
MaxRequestBodyBytes uint32
AllowedProperties []AllowedProperty
}

type AllowedProperty struct {
Path []string
Header string
}

type AuthorizationResponse struct {
Expand Down Expand Up @@ -210,6 +216,13 @@ func parseAuthorizationRequestConfig(json gjson.Result, httpService *HttpService
}
authorizationRequest.MaxRequestBodyBytes = maxRequestBodyBytes

allowedProperties := authorizationRequestConfig.Get("allowed_properties").Array()
var err error
authorizationRequest.AllowedProperties, err = parseAllowedProperties(allowedProperties)
if err != nil {
return err
}

httpService.AuthorizationRequest = authorizationRequest
}
return nil
Expand Down Expand Up @@ -316,3 +329,33 @@ func convertToStringList(results []gjson.Result) []string {
}
return interfaces
}

func parseAllowedProperties(results []gjson.Result) ([]AllowedProperty, error) {
props := make([]AllowedProperty, 0, len(results))
for i, result := range results {
pathVal := result.Get("path")
headerVal := result.Get("header")
if !pathVal.Exists() {
return nil, fmt.Errorf("allowed_properties[%d]: missing required field 'path'", i)
}
if !headerVal.Exists() {
return nil, fmt.Errorf("allowed_properties[%d]: missing required field 'header'", i)
}
// path can be array format: [route_name] or [metadata, test]
// or single value format: route_name
var path []string
if pathVal.IsArray() {
pathVal.ForEach(func(key, value gjson.Result) bool {
path = append(path, value.String())
return true
})
} else {
path = []string{pathVal.String()}
}
props = append(props, AllowedProperty{
Path: path,
Header: headerVal.String(),
})
}
return props, nil
}
Loading
Loading