Metadata-Version: 2.4
Name: sangfor-af-api
Version: 0.1.0
Summary: Document-driven Python SDK for Sangfor AF 8.0.107 REST APIs
Author: NAXG
License-Expression: MIT
Project-URL: Homepage, https://github.com/NAXG/sangfor-af-api
Project-URL: Repository, https://github.com/NAXG/sangfor-af-api
Project-URL: Issues, https://github.com/NAXG/sangfor-af-api/issues
Keywords: sangfor,sangfor-af,firewall,sdk,rest-api,network-security
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Networking :: Firewalls
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: requests<3,>=2.33
Dynamic: license-file

# sangfor-af-api

这是一个面向深信服 AF 8.0.107 REST API 的**非官方** Python SDK，由
《AF8.0.107 API 中文文档》自动抽取并生成。项目兼容基线为 AF 8.0.107。

## 免责声明

- 本项目为社区驱动的非官方 SDK，**与深信服科技有限公司（Sangfor Technologies Inc.）及其关联公司不存在任何隶属、赞助、支持或背书关系**。
- 项目中打包的 API 接口目录（`src/sangfor_sdk/data/api_catalog.json`）及生成代码中的接口路径、参数说明、中文标题均从深信服官方文档提取，仅用于实现互操作性。**原始文档、API Schema、产品名称的著作权与商标权归相关权利人所有**。
- "Sangfor"、"深信服" 等标识为深信服科技有限公司的注册商标，本项目中的使用仅为描述与识别产品，不代表任何官方关联。
- 本项目按 MIT 许可证分发，使用风险由使用者自行承担。

文档中的每个 `API请求数据` 主定义都对应 Catalog 中的一个 operation，并对应生成类中的一个显式 Python 方法。当前覆盖校验结果：

| 章节 | 接口数 |
| --- | ---: |
| 2 认证鉴权 | 3 |
| 3 监控 | 72 |
| 4 对象 | 121 |
| 5 网络 | 489 |
| 6 策略 | 313 |
| 7 系统 | 141 |
| 8 运营中心 | 44 |
| 9 状态中心 | 14 |
| 10 虚拟系统 | 18 |
| 11 扩展 API | 20 |
| **合计** | **1,235** |

HTTP 方法分布：GET 522、POST 290、PATCH 207、DELETE 122、PUT 94。

## 安装

从 PyPI 安装（发布后）：

```bash
python3 -m pip install sangfor-af-api
```

从源码安装或使用开发模式：

```bash
python3 -m pip install .
python3 -m pip install -e .
```

PyPI 分发名是 `sangfor-af-api`，Python 导入名保持为 `sangfor_sdk`。

## 快速开始

```python
from sangfor_sdk import AFAPI, SangforClient

client = SangforClient(
    "https://192.168.1.1",
    namespace="public",
    username="admin",
    password="your-password",
    token_cache=True,
    verify="/path/to/internal-ca.pem",
)
api = AFAPI(client)

# 6.2.1.2 获取安全防护策略
security_policies = api.policies.get_6_2_1_2(
    query={"_start": 0, "_length": 200}
)

# 8.2.1 获取黑名单
blacklist = api.operations_center.get_8_2_1(
    query={"type": "BLACK", "_start": 0, "_length": 200}
)
```

SDK 默认拒绝明文 HTTP。设备使用自签名证书时，优先传入内部 CA 文件。只有在隔离测试环境中
才使用 `verify=False`；如测试设备确实只提供 HTTP，还必须显式设置
`allow_insecure_http=True`，此时密码和 Token 不具备传输加密保护。

## 方法命名

生成方法名称由 HTTP 方法和文档章节组成：

```text
get_6_2_1_2       -> 6.2.1.2 获取安全防护策略
get_6_3_1_1_1     -> 6.3.1.1.1 获取应用控制策略列表
get_8_2_1         -> 8.2.1 全量获取符合过滤条件的黑白 IP
post_8_2_4        -> 8.2.4 批量添加黑白名单
```

这种命名与 PDF 章节一一对应，避免中文标题重复或翻译造成歧义。

## 参数传递

所有生成方法采用统一参数：

- `path_params`：替换路径中的 `{name}`、`{uuid}`、`{url}` 等变量；`namespace` 默认使用 Client 配置。
- `query`：URL 查询参数。
- `body`：JSON 请求体。
- `headers`：额外请求头。
- 其他关键字参数会透传给 `requests.Session.request()`。

```python
# 6.1.1.4 获取单条 NAT 策略
nat = api.policies.get_6_1_1_4(
    path_params={"name": "NAT策略名称"}
)

# 8.2.3 添加黑名单
created = api.operations_center.post_8_2_3(
    body={
        "type": "BLACK",
        "url": "203.0.113.10",
        "enable": True,
        "description": "SDK example",
    }
)
```

路径参数会进行 URL 编码。例如 `example.com/a` 会编码为 `example.com%2Fa`，不会破坏 API 路径。

文档 URL 中固定的查询参数会由 SDK 自动携带。比如批量删除接口记录为
`POST ...?_method=delete` 时，调用方不需要手工传 `_method`，且不能把它覆盖成其他值。

## API Catalog

完整 Catalog 位于 `src/sangfor_sdk/data/api_catalog.json`，包含：

- operation ID、章节、中文标题、PDF 页码；
- HTTP 方法、路径、批量接口标记；
- 路径、查询、Header、Body 参数；
- 返回字段和功能说明。

Body 元数据中的 `body_root` 是 PDF 参数表使用的 schema 根标签（如 `obj`、`objs`），
不是请求 JSON 必须额外包裹的一层；`body_root_wrapped=false` 表示直接发送对象或数组。
文档中的 `nil.*` 匿名根字段已规范化，原字段名保存在 `documented_name`。当
`body_shape=none` 时不应发送正文，即使 Catalog 为忠实记录文档冲突而保留了参数表。

```python
from sangfor_sdk import OperationCatalog

catalog = OperationCatalog.load_default()

for operation in catalog.find("黑白名单", section_prefix="8.2"):
    print(operation.operation_id, operation.method, operation.path)

operation = catalog.get("get_8_2_1")
print(operation.metadata["query_params"])
print(operation.metadata["response_params"])
```

也可以不使用章节类，直接通过 operation ID 调用：

```python
result = api.call(
    "get_8_2_2",
    path_params={"url": "example.com"},
)
```

生成方法默认返回响应中的 `data`。需要检查完整的 `code/message/data` 时，可传入
`return_result=True`。

## 分页

```python
operation = api.operation("get_8_2_1")

for item in client.paginate(
    operation,
    query={"type": "BLACK"},
    page_size=200,
):
    print(item)
```

`iter_pages()` 返回包含 `items`、`start`、`length` 和 `total` 的页对象。

分页默认只允许逻辑上的 GET 操作。为了避免同一个写操作被按页重复执行，其他方法会被拒绝；
只有明确确认服务端语义后，Python 调用方才能设置 `allow_repeated_writes=True`。

## 认证与 Token

SDK 按 8.0.107 文档使用：

```http
Cookie: token=<token>
```

默认只发送文档规定的 Cookie。只有旧设备确实要求兼容 Header 时才显式开启：

```python
client = SangforClient(host, legacy_token_header=True)
```

文档中另外明确要求 `x-sangfor-token` 的 7 个状态查询接口，也会根据 Catalog
自动发送当前 Token；自动重新登录后该 Header 会同步更新。

设备返回 `1003` 或 `1012` 时，如果配置了用户名和密码，SDK 会重新登录并重试一次。Token 缓存采用原子写入，权限为 `0600`；读取时会拒绝符号链接、非普通文件、非当前用户所有或向组/其他用户开放的文件。

可以直接使用 `client.login()`、`client.keepalive()`、`client.logout()`。章节 2 对应的
三个生成方法也会委托给这些专用方法，因此登录会安装 Token，注销会清理本地 Token 与缓存。
`client.close()` 和上下文管理器退出时不会向设备发送注销请求，但会清除内存中的密码、Token、
CSRF Token 和登录响应认证数据，并保留磁盘 Token 缓存供后续会话使用。

为避免认证信息被重定向到其他主机，SDK 不跟随 HTTP 重定向，并拒绝向
`base_url` 之外的域名发送认证请求。

异常对象会脱敏常见的密码、Token、Cookie、Authorization 和 API Key 字段，HTTP
响应原文不会保存在异常中。应用仍应避免记录完整请求正文、成功响应或自行传入的敏感字段。

## 示例

搜索内置 Catalog（不连接设备）：

```bash
python3 examples/search_catalog.py
```

读取安全防护、应用控制、NAT 策略和黑名单统计：

```bash
export SANGFOR_AF_HOST='https://192.168.1.1'
export SANGFOR_AF_USERNAME='admin'
export SANGFOR_AF_PASSWORD='password'
export SANGFOR_AF_CA_BUNDLE='/path/to/internal-ca.pem'
python3 examples/read_only_inventory.py
```

`read_only_inventory.py` 会登录设备并执行四个 GET 查询，不会新增、修改或删除策略。

## 重新从 PDF 生成

```bash
python3 tools/generate_api_catalog.py \
  --pdf '/path/to/AF8.0.107-API中文文档.pdf'
```

只校验、不写文件：

```bash
python3 tools/generate_api_catalog.py \
  --pdf '/path/to/AF8.0.107-API中文文档.pdf' \
  --validate-only
```

检查生成结果是否可复现：

```bash
python3 tools/generate_api_catalog.py \
  --pdf '/path/to/AF8.0.107-API中文文档.pdf' \
  --check
```

如需输出校验报告，可额外指定 `--report-out <path>`。

## 测试

```bash
PYTHONPATH=src \
python3 -m unittest discover -s tests -v
```

测试会验证 1,229 个 Catalog operation 与 1,229 个生成方法完全一致，不会连接真实防火墙。

## 版本说明

SDK 以 AF 8.0.107 文档为源。较旧设备可能不具备新增接口或字段，应根据实际设备版本、许可证和管理员权限处理 `1002`、`1004`、`13` 等返回码。
