Skip to content

Commit

Permalink
feat(apigw_manager/drf): update to support multiple stages (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
wklken authored Oct 25, 2024
1 parent 0446ffc commit 4e169d6
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 128 deletions.
22 changes: 11 additions & 11 deletions sdks/apigw-manager/docs/jwt-explain.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# jwt 说明

后端服务接入网关时, 接口可能开启了应用认证/用户认证, 此时调用方需要传认证header头 `X-Bkapi-Authorization`, 网关认证通过后, 会生成一个 `X-Bkapi-JWT` 头给到后端服务, 里面包含了认证结果信息, 这是一个 jwt token
后端服务接入网关时接口可能开启了应用认证/用户认证,此时调用方需要传认证 header 头 `X-Bkapi-Authorization`, 网关认证通过后会生成一个 `X-Bkapi-JWT` 头给到后端服务里面包含了认证结果信息这是一个 jwt token

![img](./images/jwt.png)

## 如何获取网关公钥
## 1. 如何获取网关公钥

后端服务如需解析 API 网关发送的请求头 X-Bkapi-JWT,需要提前获取该网关的公钥。获取网关公钥,有以下方案。

### 1. 根据 SDK 提供的 Django Command 拉取
### 1.1 根据 SDK 提供的 Django Command 拉取

在同步网关数据时,直接添加以下 Command 拉取网关公钥。网关公钥将保存在 model Context 对应的库表 apigw_manager_context 中,SDK 提供的 Django 中间件将从表中读取网关公钥。

Expand All @@ -20,14 +20,14 @@ python manage.py fetch_apigw_public_key
python manage.py fetch_apigw_public_key --gateway-name my-gateway
```

### 2. 直接获取网关公钥,配置到项目配置文件
### 1.2 直接获取网关公钥,配置到项目配置文件

服务仅需接入一些固定的网关部署环境时,可在网关管理端,网关基本信息中查询网关公钥,并配置到项目配置文件。

蓝鲸官方网关,需要自动注册并获取网关公钥,可联系蓝鲸官方运营同学,在服务部署前,由官方提前创建网关,并设置网关公钥、私钥,同时将网关公钥同步给后端服务。
具体可参考 helm-charts 仓库的 README。

### 3. 通过网关公开接口,拉取网关公钥
### 1.3 通过网关公开接口,拉取网关公钥

API 网关提供了公钥查询接口,后端服务可按需根据接口拉取网关公钥,接口信息如下:

Expand All @@ -53,9 +53,9 @@ curl -X GET 'https://bkapi.example.com/api/bk-apigateway/prod/api/v1/apis/{gatew

- 拉取公钥时,不能实时拉取,需要添加缓存(实时拉取会导致整体接口性能下降)

## 校验请求来自 API 网关
## 2. 校验请求来自 API 网关

### 场景一:Django 项目
### 2.1 场景一:Django 项目

要在后端服务中认证 API 网关传递过来的请求头 `X-Bkapi-JWT`,可以通过在 settings 中的 MIDDLEWARE 中添加以下 Django 中间件。这样,在请求处理过程中,会自动解析请求头中的 X-Bkapi-JWT,并将相关信息添加到 request 对象中。

Expand Down Expand Up @@ -86,7 +86,7 @@ AUTHENTICATION_BACKENDS += [

- SDK model Context (库表 apigw_manager_context),需提前执行 `python manage.py fetch_apigw_public_key` 拉取并保存网关公钥

- settings.APIGW_PUBLIC_KEY,可在网关基本页面/API公钥通过点击`复制`按钮或者`下载`获取公钥,并配置到 settings 中。
- settings.APIGW_PUBLIC_KEY,可在网关基本页面/API 公钥通过点击`复制`按钮或者`下载`获取公钥,并配置到 settings 中。

> 公钥示例:
> ```shell
Expand All @@ -113,7 +113,7 @@ AUTHENTICATION_BACKENDS += [
##### ApiGatewayJWTUserMiddleware
根据 `request.jwt`,在 `request` 中注入 `user` 对象:
根据 `request.jwt`,在 `request` 中注入 `user` 对象
- 如果用户通过认证:其为一个 Django User Model 对象,用户名为当前请求用户的用户名
- 如果用户未通过认证,其为一个 Django AnonymousUser 对象,用户名为当前请求用户的用户名
Expand Down Expand Up @@ -157,7 +157,7 @@ APIGW_MANAGER_DUMMY_PAYLOAD_APP_CODE # JWT payload 中的 app_code
APIGW_MANAGER_DUMMY_PAYLOAD_USERNAME # JWT payload 中的 username
```

### 场景二:非 Django 项目
### 2.2 场景二:非 Django 项目

非 Django 项目,需要项目获取网关公钥,并解析请求头中的 X-Bkapi-JWT;获取网关公钥的方案请参考上文。

Expand Down Expand Up @@ -188,4 +188,4 @@ APIGW_MANAGER_DUMMY_PAYLOAD_USERNAME # JWT payload 中的 username
"nbf": 1701399303, # Not Before 时间
"iss": "APIGW" # 签发者
}
```
```
33 changes: 21 additions & 12 deletions sdks/apigw-manager/docs/plugin-use-guide.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# 插件配置说明

插件配置支持主要在 `stage`(definition.yaml) 和 `resource`(resource.yaml) 两个维度上,资源配置的插件优先级最高。
> 注意:所有配置均以 yaml 配置同步为主,举例来说: 如果通过yaml配置的插件配置则会覆盖掉用户在网关管理页面创建的插件配置,如果 yaml 没有配置该插件,则也不会移除
> 用户之前在页面创建的插件配置,不过 yaml 如果没有配置上一次yaml配置的插件,则会移除上一次 yaml 配置的插件。
> `CORS` 插件和 `IP 访问保护插件` 不推荐在yaml配置绑定在环境上。
> 注意:所有配置均以 yaml 配置同步为主,举例来说:如果通过 yaml 配置的插件配置则会覆盖掉用户在网关管理页面创建的插件配置,如果 yaml 没有配置该插件,则也不会移除
> 用户之前在页面创建的插件配置,不过 yaml 如果没有配置上一次 yaml 配置的插件,则会移除上一次 yaml 配置的插件。
> `CORS` 插件和 `IP 访问保护插件` 不推荐在 yaml 配置绑定在环境上。
## 1. 跨域资源共享(CORS)插件

## 跨域资源共享(CORS)插件
### 1.1 参数说明

| 参数 | 类型 | 默认值 | 描述 |
| ---------------- | ------ | ------ | ------------------------------------------------------------ |
Expand All @@ -15,7 +18,7 @@
| max_age | 整数 | 86400 | 浏览器缓存 CORS 结果的最大时间,单位为秒。 |
| allow_credential | 布尔值 | true | 是否允许跨域访问的请求方携带凭据(如 Cookie 等)。 |

### 配置例子
### 1.2 配置例子

```yaml
- type: bk-cors
Expand All @@ -28,14 +31,16 @@
allow_credential: false
```
## Header 转换插件
## 2. Header 转换插件
### 2.1 参数说明
| 参数 | 类型 | 默认值 | 描述 |
| ------ | ---- | ------ | ---------------------------- |
| set | 数组 | [] | 设置的请求头,包括键和值。 |
| remove | 数组 | [] | 删除的请求头,只需要提供键。 |
### 配置例子
### 2.2 配置例子
```yaml
- type: bk-header-rewrite
Expand All @@ -46,15 +51,17 @@
remove: []
```
## IP 访问保护插件
## 3. IP 访问保护插件
### 3.1 参数说明
| 参数 | 类型 | 默认值 | 描述 |
| --------- | ------ | ------ | -------------------------------------- |
| whitelist | 字符串 | "" | 白名单中的 IP 地址,支持 CIDR 表示法。 |
| blacklist | 字符串 | "" | 黑名单中的 IP 地址,支持 CIDR 表示法。 |
| message | 字符串 | "" | 当 IP 地址不被允许时显示的消息。 |
### 配置例子
### 3.2 配置例子
```yaml
- type: bk-ip-restriction
Expand All @@ -64,16 +71,18 @@
message: 'Your IP is not allowed'
```
## 频率控制插件
## 4. 频率控制插件
### 4.1 参数说明
| 参数 | 类型 | 默认值 | 描述 |
| ----------- | ------ | ------ | ------------------------------------------------ |
| rates | 对象 | {} | 包含默认频率限制和特殊应用频率限制的对象。 |
| default | 对象 | {} | 单个应用的默认频率限制,包括次数和时间范围。 |
| specials | 数组 | [] | 特殊应用频率限制,对指定应用设置单独的频率限制。 |
| bk_app_code | 字符串 | "" | 蓝鲸应用ID,用于特殊应用频率限制。 |
| bk_app_code | 字符串 | "" | 蓝鲸应用 ID,用于特殊应用频率限制。 |
### 配置例子
### 4.2 配置例子
```yaml
- type: bk-rate-limit
Expand Down
26 changes: 15 additions & 11 deletions sdks/apigw-manager/docs/sync-apigateway-with-django.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
### 直接使用 Django Command 同步网关
# 直接使用 Django Command 同步网关

项目安装 SDK apigw-manager 后,可以直接执行 SDK 提供的 Django Command。

- 准备文件的样例 [examples/django/use-custom-script](../examples/django/use-custom-script)

#### 步骤1. 准备自定义同步脚本
## 步骤 1. 准备自定义同步脚本

创建一个 bash 脚本,如 `sync-apigateway.sh`,使用 SDK 提供的 Django Command 定义网关配置的同步脚本,样例如下:

```shell
#!/bin/bash

Expand All @@ -31,7 +33,7 @@ python manage.py sync_apigw_config --gateway-name=${gateway_name} --file="${defi
python manage.py sync_apigw_stage --gateway-name=${gateway_name} --file="${definition_file}"

# 同步网关资源
#
#
# --delete: 当资源在服务端存在,却未出现在资源定义文件中时,指定本参数会强制删除这类资源,以保证服务端资源和文件内容完全一致。
# 如果未指定本参数,将忽略未出现的资源
# --doc_language: en/zh 是否生成接口文档(中文/英文)
Expand All @@ -54,6 +56,7 @@ echo "gateway sync definition end"
```

如果需要更灵活的控制,也可以采用自定义 Django Command 的方案,例如:

```python
from django.conf import settings
from django.core.management.base import BaseCommand
Expand All @@ -64,7 +67,7 @@ class Command(BaseCommand):
def handle(self, *args, **kwargs):
if not getattr(settings, "SYNC_APIGATEWAY_ENABLED", True):
return

# 待同步网关名,需修改为实际网关名;直接指定网关名,则不需要配置 Django settings BK_APIGW_NAME
gateway_name = "bk-demo"

Expand All @@ -81,15 +84,15 @@ class Command(BaseCommand):
call_command("fetch_apigw_public_key", f"--gateway-name={gateway_name}")
```

#### 步骤2. 添加 SDK apigw-manager
## 步骤 2. 添加 SDK apigw-manager

将 SDK apigw-manager 添加到项目依赖中,如 pyproject.toml 或 requirements.txt。

#### 步骤3. 将准备的网关配置文件,添加到项目
## 步骤 3. 将准备的网关配置文件,添加到项目

将准备的网关配置文件:definition.yaml, resources.yaml, apidocs (可选),添加到项目

#### 步骤4. 更新 Django settings 配置
## 步骤 4. 更新 Django settings 配置

在 Django settings.py 中定义网关名称和接口地址模板:

Expand All @@ -104,7 +107,7 @@ BK_APIGW_NAME = "my-gateway-name"
# 需将 bkapi.example.com 替换为真实的云 API 域名;
# 在 PaaS 3.0 部署的应用,可从环境变量中获取 BK_API_URL_TMPL,不需要额外配置;
# 实际上,SDK 将调用网关 bk-apigateway 接口将数据同步到 API 网关
BK_API_URL_TMPL = "http://bkapi.example.com/api/{api_name}/" ## 例如:网关host是:`bkapi.example.com`,则对应的值为:http://bkapi.example.com/api/{api_name} 注意:{api_name} 这个是占位符。
BK_API_URL_TMPL = "http://bkapi.example.com/api/{api_name}/" ## 例如:网关 host 是:`bkapi.example.com`,则对应的值为:http://bkapi.example.com/api/{api_name} 注意:{api_name} 这个是占位符。
```

在 INSTALLED_APPS 中加入以下配置,SDK 将创建表 `apigw_manager_context` 用于存储一些中间数据:
Expand All @@ -115,9 +118,10 @@ INSTALLED_APPS += [
]
```

#### 步骤5. 同步网关数据到 API 网关
## 步骤 5. 同步网关数据到 API 网关

chart 部署方案,可采用 K8S Job 同步,样例如下:

```yaml
apiVersion: batch/v1
kind: Job
Expand All @@ -140,12 +144,12 @@ spec:
```
二进制部署方案,在部署阶段直接执行 sync-apigateway.sh 脚本:
```shell
bash support-files/bin/sync-apigateway.sh
```


### 支持的 Django Command 列表
## 支持的 Django Command 列表

```bash
# 可选,为网关添加关联应用,关联应用可以通过网关 bk-apigateway 提供的接口管理网关数据
Expand Down
Loading

0 comments on commit 4e169d6

Please sign in to comment.