Metadata-Version: 2.4
Name: ctyun-kms-sdk
Version: 1.0.0
Summary: CTYun KMS Python SDK
Home-page: 
Author: CTYun
Author-email: 
License: MIT
Project-URL: Homepage, https://github.com/ctyun/ctyun-kms-sdk-python
Project-URL: Documentation, https://github.com/ctyun/ctyun-kms-sdk-python/blob/main/README.md
Project-URL: Repository, https://github.com/ctyun/ctyun-kms-sdk-python.git
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.31.0
Requires-Dist: cryptography>=41.0.0
Dynamic: requires-python

# CTYun KMS Python SDK

## 概述

CTYun KMS Python SDK 提供与天翼云密钥管理服务（KMS）交互的 Python 接口。

## Python版本支持

**重要提示**：本SDK仅支持Python 3.7及以上版本，不支持Python 2。

- 最低要求：Python 3.7
- 推荐版本：Python 3.8及以上
- 已测试版本：Python 3.7, 3.8, 3.9, 3.10, 3.11

如果您仍在使用Python 2，请考虑升级到Python 3，或者使用其他兼容Python 2的KMS客户端解决方案。

### 特性

- 🔐 完整的 KMS API 支持
- 🚀 连接池和会话复用
- 🔄 自动重试机制
- 📊 详细的耗时统计
- 🛡️ 线程安全的单例模式
- ✅ 完整的类型提示
- 🏗️ 模块化架构设计
- 📦 清晰的服务分类

## 目录结构

```
ctyun-kms-sdk-python/
├── ctyun_kms/              # SDK主包
│   ├── __init__.py
│   ├── client.py           # 客户端
│   ├── profile.py          # 配置
│   ├── signer.py           # 签名
│   ├── models/             # 数据模型
│   └── services/          # 服务模块
│       ├── symmetric/      # 对称加密
│       ├── asymmetric/    # 非对称操作
│       ├── key_management/ # 密钥管理
│       ├── datakey/        # 数据密钥
│       ├── certificate/    # 证书管理
│       ├── random/         # 随机数
│       └── rotation_policy/ # 轮转策略
├── docs/                   # API文档
├── examples/              # 使用示例
├── pyproject.toml         # 包配置
├── setup.py              # 包配置
└── requirements.txt      # 依赖
```

## 安装

### 前置要求

- Python 3.7 或更高版本（不支持Python 2）
- pip 包管理器

### 离线安装

如需离线安装，请先安装依赖，再安装SDK：

```bash
# 安装依赖
pip install requests>=2.31.0 cryptography>=41.0.0

# 安装SDK
pip install ctyun_kms_sdk-1.0.0-py3-none-any.whl
```

wheel 包位于 `dist/ctyun_kms_sdk-1.0.0-py3-none-any.whl`。

### 依赖配置

将SDK添加到您的项目依赖，有以下方式：

**方式一：通过 requirements.txt**

```txt
# requirements.txt
ctyun-kms-sdk==1.0.0
requests>=2.31.0
cryptography>=41.0.0
```

**方式二：通过 pyproject.toml**

```toml
[project]
dependencies = [
    "ctyun-kms-sdk==1.0.0",
    "requests>=2.31.0",
    "cryptography>=41.0.0",
]
```

**方式三：离线环境指定本地路径**

```txt
# requirements.txt
D:/libs/ctyun_kms_sdk-1.0.0-py3-none-any.whl
requests>=2.31.0
cryptography>=41.0.0
```

安装：
```bash
pip install -r requirements.txt
```

### 从私有制品库安装

如果您的组织配置了私有 Python 制品库，可以从私有源安装：

```bash
pip install ctyun-kms-sdk
```

或者指定版本：

```bash
pip install ctyun-kms-sdk==1.0.0
```

### 从源码安装

如果需要从源码安装：

```bash
# 进入项目目录
cd ctyun-kms-sdk-python

# 安装依赖
pip install -r requirements.txt

# 安装包
pip install .
```

### 依赖项

- Python >= 3.7
- requests >= 2.31.0
- cryptography >= 41.0.0

> **注意**：由于依赖的第三方库已不再支持Python 2，本SDK无法在Python 2环境中运行。

## 快速开始

> **提示**：在开始使用前，请确保您的Python版本为3.7或更高版本。您可以通过运行`python --version`或`python3 --version`来检查。

```python
import os
from ctyun_kms import DefaultProfile, DefaultKmsClient
from ctyun_kms.services.symmetric import encrypt

# 初始化配置对象
profile = DefaultProfile(
    region_id="cn-north-1",
    access_key_id=os.getenv("CTYUN_ACCESS_KEY_ID"),
    access_key_secret=os.getenv("CTYUN_ACCESS_KEY_SECRET")
)

# 创建客户端
client = DefaultKmsClient(profile)

# 发起加密请求
request = encrypt.EncryptRequest()
request.plaintext = "your-plaintext-data"
request.cmk_uuid = "your-cmk-uuid"

response = client.do_action(request)

if response.code == 0:
    print(f"Encrypted: {response.data.ciphertext_blob}")
else:
    print(f"Error: {response.msg}")
```

## 配置说明

### Profile 配置

使用 `DefaultProfile.builder()` 构建配置对象：

## 服务模块结构

SDK 采用模块化设计，按照功能将 API 分为不同的服务模块：

```
ctyun_kms/
├── services/
│   ├── symmetric/         # 对称加密相关操作
│   │   ├── encrypt.py     # 加密
│   │   └── decrypt.py     # 解密
│   ├── datakey/           # 数据密钥操作
│   │   └── generate_data_key.py  # 生成数据密钥
│   ├── asymmetric/        # 非对称密钥操作
│   │   ├── create_key_pair.py    # 创建密钥对
│   │   ├── get_public_key.py     # 获取公钥
│   │   ├── sign.py               # 签名
│   │   └── verify.py             # 验证签名
│   ├── key_management/    # 密钥管理
│   │   ├── create_key.py         # 创建密钥
│   │   ├── enable_key.py         # 启用密钥
│   │   ├── disable_key.py        # 禁用密钥
│   │   ├── schedule_key_deletion.py  # 计划删除密钥
│   │   ├── cancel_key_deletion.py    # 取消密钥删除
│   │   └── list_keys.py            # 列出密钥
│   ├── certificate/       # 证书管理
│   │   ├── import_certificate.py    # 导入证书到 UK
│   │   └── verify_certificate.py    # 证书公钥验签
│   └── random/            # 随机数生成
│       └── generate_random.py       # 生成随机数
```

每个模块都包含相应的 Request 和 Response 类，便于类型提示和代码补全。

### 使用示例

```python
# 导入特定服务模块
from ctyun_kms.services.symmetric import encrypt, decrypt
from ctyun_kms.services.key_management import create_key
from ctyun_kms.services.asymmetric import sign, verify
from ctyun_kms.services.certificate import import_certificate, verify_certificate

# 使用对称加密
encrypt_request = encrypt.EncryptRequest()
encrypt_request.plaintext = "sensitive data"
encrypt_request.cmk_uuid = "your-cmk-uuid"

# 使用密钥管理
create_key_request = create_key.CreateKeyRequest()
create_key_request.alias = "my-key"
create_key_request.description = "My test key"

# 使用非对称签名
sign_request = sign.SignRequest()
sign_request.message = "message to sign"
sign_request.key_id = "asymmetric-key-id"
sign_request.signing_algorithm = "RSASSA_PKCS1_V1_5_SHA_256"

# 使用证书管理
import_cert_request = import_certificate.ImportCertificateForUKRequest()
import_cert_request.cert = "base64-encoded-cert"
import_cert_request.uk_name = "my-uk-key"
import_cert_request.algorithm = "RSA_2048"

# 使用证书验签
verify_cert_request = verify_certificate.CertificatePublicKeyVerifyForUsbKeyRequest()
verify_cert_request.certificate_id = "cert-id"
verify_cert_request.message = "base64-encoded-message"
verify_cert_request.signature_value = "base64-encoded-signature"
verify_cert_request.algorithm = "RSA_2048"
```

```python
profile = DefaultProfile.builder() \\
    .access_key("ak")          # 必填：访问密钥
    .security_key("sk")        # 必填：安全密钥
    .ip_port("host:port")      # 必填：服务地址
    .region_id("1")            # 可选：区域ID，默认为"1"
    .ca_cert_path("/path/to/ca.pem")  # 可选：CA证书路径
    .trust_all_ssl(False)      # 可选：信任所有SSL证书（默认为True，生产环境建议设为False）
    .disable_hostname_verification(False)  # 可选：禁用主机名验证（默认为True，生产环境建议设为False）
    .build()
```

### HTTPS 配置

#### 生产环境（推荐）

```python
profile = DefaultProfile.builder() \\
    .access_key("ak") \\
    .security_key("sk") \\
    .ip_port("kms.example.com:443") \\
    .ca_cert_path("/path/to/ca-bundle.pem") \\
    .build()
```

#### 测试环境

```python
profile = DefaultProfile.builder() \\
    .access_key("ak") \\
    .security_key("sk") \\
    .ip_port("host:port") \\
    .trust_all_ssl(True) \\
    .disable_hostname_verification(True) \\
    .build()
```

**注意**：默认情况下，`trust_all_ssl` 和 `disable_hostname_verification` 已设置为 `True`，适用于测试环境。生产环境建议显式设置为 `False` 并配置正确的 CA 证书路径。

## API 示例

### 加密操作

```python
from ctyun_kms.services.symmetric import encrypt

request = encrypt.EncryptRequest()
request.cmk_uuid = "your-cmk-uuid"
request.plaintext = "sensitive data"

response = client.do_action(request)
if response.code == 0:
    ciphertext = response.data.ciphertext_blob
    print(f"Ciphertext: {ciphertext}")
```

### 解密操作

```python
from ctyun_kms.services.symmetric import decrypt

request = decrypt.DecryptRequest()
request.ciphertext_blob = "encrypted-data"

response = client.do_action(request)
if response.code == 0:
    plaintext = response.data.plaintext
    print(f"Plaintext: {plaintext}")
```

## 单例模式

SDK 使用单例模式管理客户端实例，以复用连接池和 TLS 会话：

```python
# 推荐：使用单例获取客户端
client = DefaultKmsClient.get_instance(profile)

# 配置兼容时复用现有实例
client2 = DefaultKmsClient.get_instance(profile)  # 返回相同实例

# 配置变更时自动重建
new_profile = DefaultProfile.builder() \\
    .access_key("new-ak") \\
    .security_key("new-sk") \\
    .ip_port("new-host:port") \\
    .build()
client3 = DefaultKmsClient.get_instance(new_profile)  # 创建新实例
```

### 自定义 Session

```python
import requests

# 创建自定义 Session
custom_session = requests.Session()
custom_session.timeout = 60

# 注入自定义 Session
client = DefaultKmsClient.get_instance(profile, session=custom_session)
```

## 日志配置

SDK 使用 Python 标准 `logging` 模块，提供详细的调试信息来帮助诊断问题和优化性能。

### 基本配置

最简单的配置方式是启用全局 DEBUG 日志：

```python
import logging

# 启用 DEBUG 级别日志查看详细耗时统计
logging.basicConfig(level=logging.DEBUG)
```

或者只针对 SDK 启用 DEBUG 日志：

```python
import logging

# 或仅启用 SDK 的 DEBUG 日志
logger = logging.getLogger('ctyun_kms')
logger.setLevel(logging.DEBUG)

# 添加处理器（如果还没有的话）
if not logger.handlers:
    handler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
```

### 详细配置示例

对于更精细的控制，您可以使用以下配置：

```python
import logging
import sys

# 配置 SDK 日志记录器显示调试信息
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[logging.StreamHandler(sys.stdout)]
)

# 获取 SDK 日志记录器并设置为 DEBUG 级别
sdk_logger = logging.getLogger('ctyun_kms')
sdk_logger.setLevel(logging.DEBUG)
```

### 日志输出示例

当您使用上述配置运行 KMS 操作时，您将看到如下详细输出：

```
2025-11-26 10:30:45,123 - ctyun_kms.client - DEBUG - [KMS SDK] 耗时统计(毫秒):
2025-11-26 10:30:45,124 - ctyun_kms.client - DEBUG -  - 参数准备: 0.15 ms
2025-11-26 10:30:45,125 - ctyun_kms.client - DEBUG -  - HMAC计算: 0.82 ms
2025-11-26 10:30:45,170 - ctyun_kms.client - DEBUG -  - https发送与接收: 45.23 ms
2025-11-26 10:30:45,171 - ctyun_kms.client - DEBUG -  - 结果解析: 0.31 ms
2025-11-26 10:30:45,172 - ctyun_kms.client - DEBUG - 总耗时: 46.51 ms
2025-11-26 10:30:45,173 - ctyun_kms.client - DEBUG - [KMS SDK] 请求URL: https://kms.ctyunapi.cn:443/ctyunKmsService/keyCompute/encrypt
2025-11-26 10:30:45,174 - ctyun_kms.client - DEBUG - [KMS SDK] 请求头: {'requestDate': 'Wed, 26 Nov 2025 02:30:45 GMT', 'hmac': '...', 'accessKey': '...', 'Content-Type': 'application/json'}
2025-11-26 10:30:45,175 - ctyun_kms.client - DEBUG - [KMS SDK] 请求体: {"cmkUuid": "your-cmk-uuid", "plaintext": "Hello, CTYun KMS!", "userId": "your-user-id", "regionId": "1", "accessKey": "your-access-key"}
2025-11-26 10:30:45,215 - ctyun_kms.client - DEBUG - [KMS SDK] 响应体: {"code": 0, "errorCode": "OK", "msg": "success", "data": {"ciphertextBlob": "...", "cmkUuid": "your-cmk-uuid", "keyVersionId": "1", "requestId": "req-123"}}
```

### 日志内容说明

日志提供了以下有价值的信息：

1. **耗时统计**：每个请求阶段的精确时间测量，有助于性能优化
2. **请求详情**：完整的请求 URL、头部和主体内容
3. **响应数据**：从 KMS 服务返回的完整响应
4. **错误诊断**：请求失败时的详细错误信息

### 更多示例

查看 `examples/` 目录下的日志示例：
- `simple_logging_example.py` - 简单的日志配置示例
- `logging_example.py` - 完整的日志配置和说明示例

这些日志对于以下场景非常有价值：
- 调试连接问题
- 排查认证错误
- 性能优化
- 理解 SDK 行为

## 最佳实践

1. **环境变量管理敏感信息**
   ```python
   import os
   
   profile = DefaultProfile.builder() \\
       .access_key(os.environ.get('CTYUN_AK')) \\
       .security_key(os.environ.get('CTYUN_SK')) \\
       .ip_port(os.environ.get('CTYUN_KMS_ENDPOINT')) \\
       .build()
   ```

2. **使用单例获取客户端**
   - 复用连接池，减少 TLS 握手开销
   - 避免内存泄漏和资源浪费

3. **不可变配置**
   - `DefaultProfile` 为不可变对象，线程安全
   - 需要变更配置时，使用 Builder 重新构建

4. **错误处理**
   ```python
   try:
       response = client.do_action(request)
       if response.code == 0:
           # 处理成功响应
           process_success(response.data)
       else:
           # 处理业务错误
           print(f"Business error: {response.error_code} - {response.msg}")
   except RuntimeError as e:
       # 处理网络错误或其他异常
       print(f"Request failed: {e}")
   ```

## 测试

### 重置单例（仅测试）

```python
# 在测试中重置单例以确保隔离
DefaultKmsClient.reset_singleton_for_testing()
```

## 故障排除

### SSL 证书验证失败

如果遇到 SSL 证书验证问题：

1. **生产环境**：使用正确的 CA 证书路径
   ```python
   .ca_cert_path("/etc/ssl/certs/ca-bundle.crt")
   ```

2. **测试环境**：临时禁用验证
   ```python
   .trust_all_ssl(True)
   .disable_hostname_verification(True)
   ```

### 主机名验证失败

使用 IP 地址访问时，可能需要禁用主机名验证：

```python
.disable_hostname_verification(True)
```

## 许可证

MIT License

## 问题反馈

如需更多示例或功能扩展，欢迎提出需求。
