Skip to content

Latest commit

 

History

History
2882 lines (2205 loc) · 86.2 KB

File metadata and controls

2882 lines (2205 loc) · 86.2 KB

Project Changes Log


KMS Beta 加固 (2026-03-03 13:47)

  • 移除 p256-m C 库(TA crash 根因)
  • CA 端 Rate Limit + Circuit Breaker + Input Validation
  • 生产 API 性能基准写入文档
  • 旧钱包数据清理(DB + secure storage)
  • TLS/防护层架构文档

🧹 清理无效的助记词备份恢复功能 (2025-10-16 20:55)

删除的功能

由于发现架构缺陷(用户提供的助记词与 TA 实际生成的助记词不匹配),删除以下无法正常工作的恢复功能:

  • ❌ 删除脚本: scripts/kms-restore-wallets.sh
  • ❌ 删除文档: docs/KMS-BACKUP-GUIDE.md
  • ❌ 删除文档: docs/KMS-Wallet-Persistence.md
  • ❌ 清理其他脚本中对恢复功能的引用

新的备份方案

计划采用 ExportKey + 私钥备份 方案:

  1. 创建钱包后使用 ExportKey API 导出真实私钥
  2. 将 KeyId + Address + 私钥存储到 JSON 备份文件
  3. 恢复时使用私钥重新导入钱包

此方案绕过助记词问题,使用 TA 实际生成的私钥,可以完全恢复钱包。

已清理的文件

  • 测试页面已移除固定钱包信息
  • 部署脚本已移除恢复功能示例
  • 初始化脚本已更新提示信息(钱包会在 QEMU 重启后丢失)

🔄 KMS 钱包自动备份系统上线 (2025-10-16 17:30)

功能更新

新增自动备份 Cron 任务系统,确保钱包数据安全:

  1. 安装脚本: scripts/kms-install-backup-cron.sh

    • 自动添加 cron 任务,每小时备份一次
    • 智能检测重复任务并提供替换选项
    • 支持交互式和非交互式模式
    • 使用绝对路径避免执行错误
  2. 卸载脚本: scripts/kms-uninstall-backup-cron.sh

    • 安全移除 cron 任务
    • 支持确认提示和强制模式
    • 保留历史备份文件
  3. 完整文档: docs/KMS-BACKUP-GUIDE.md

    • 安装与管理指南
    • 备份文件格式说明
    • 安全建议(加密、异地备份、权限设置)
    • 故障排查指南
    • Cron 时间格式参考

Cron 任务配置

# 每小时的第0分钟执行备份
0 * * * * /path/to/scripts/kms-backup-wallets.sh >> /path/to/logs/kms-backup-cron.log 2>&1

备份信息

  • 备份位置: ~/.kms-backup/
  • 日志位置: logs/kms-backup-cron.log
  • 备份格式: JSON (包含 wallet_id, address, derivation_path, mnemonic)

管理命令

# 安装自动备份
./scripts/kms-install-backup-cron.sh

# 查看 cron 任务
crontab -l | grep kms-backup

# 查看执行日志
tail -f logs/kms-backup-cron.log

# 手动执行备份
./scripts/kms-backup-wallets.sh

# 卸载自动备份
./scripts/kms-uninstall-backup-cron.sh

安全建议

  1. 定期检查备份文件完整性
  2. 使用 GPG 加密敏感备份
  3. 配置异地备份到远程服务器
  4. 限制备份目录权限为 700

相关文件

  • scripts/kms-install-backup-cron.sh - Cron 任务安装脚本
  • scripts/kms-uninstall-backup-cron.sh - Cron 任务卸载脚本
  • docs/KMS-BACKUP-GUIDE.md - 完整备份指南

Commit

  • ce5450e - feat: 添加 KMS 钱包自动备份 cron 任务系统

✨ SignHash API 增强 - 支持 KeyId-only 模式 (2025-10-16 16:05)

功能更新

SignHash API 现在支持三种调用模式:

  1. Address 模式 (优先级最高)

    {
      "Address": "0x35cfbc5170465721118b4798fd7ef25055ebe6e7",
      "Hash": "0x1234...cdef"
    }

    从 address_cache 自动查找 wallet_id 和 derivation_path

  2. KeyId + DerivationPath 模式 (向后兼容)

    {
      "KeyId": "862ae409-843f-456a-83c8-ebd8f884d1e1",
      "DerivationPath": "m/44'/60'/0'/0/0",
      "Hash": "0x1234...cdef"
    }

    手动指定派生路径

  3. KeyId only 模式 (新增)

    {
      "KeyId": "862ae409-843f-456a-83c8-ebd8f884d1e1",
      "Hash": "0x1234...cdef"
    }

    自动从 metadata_store 读取默认派生路径

设计原理

  • 符合 v2.0 架构: CreateKey 自动返回 Address,用户无需管理 DerivationPath
  • 向后兼容: 仍支持手动指定 DerivationPath 的旧调用方式
  • 简化调用: KeyId-only 模式让 API 调用更简单

实现细节

// kms/host/src/api_server.rs:428-459
// 从 metadata_store 读取默认路径
let store = self.metadata_store.read().await;
let metadata = store.get(key_id)?;

let derivation_path = req.derivation_path
    .or_else(|| metadata.derivation_path.clone())
    .ok_or_else(|| anyhow!("No derivation path available"))?;

提交信息

  • Commit: 3d5a66a
  • 文件: kms/host/src/api_server.rs

🎨 KMS 测试页面更新 (2025-10-16 14:37)

更新内容

新增 API 测试界面:

  1. SignHash API - 直接签名 32 字节哈希
    • KeyId + DerivationPath 模式
    • Address 模式(通过地址查询)
  2. Sign API 增强 - 拆分为三种模式
    • 消息签名模式 (Message)
    • 交易签名模式 (Transaction)
    • 地址签名模式 (Address)

测试钱包信息展示:

1. dev-wallet-1 (0x35cfbc5170465721118b4798fd7ef25055ebe6e7)
   KeyId: 862ae409-843f-456a-83c8-ebd8f884d1e1
   Private: 0x29fec7da916c64ef96ea140f3baec501572f213c304f610875a11fba9affd268

2. dev-wallet-2 (0x54ff96c162441cf489598dc6e42da52fea3da3d4)
   KeyId: 38f39e59-f2da-4007-a197-a7eeed3352bf
   Private: 0xb186a6cb03115860a62313809f892f4336b26e7888d75e799f34d61e5a9be4ad

3. dev-wallet-3 (0x4cb9b4bce794d00b3035d9700a9a5c3e089d4cbe)
   KeyId: c4a501d2-2075-488d-98f1-b7c6dfb37ff3
   Private: 0x0b9e79cbc0353ac69235d19d9fced53ce288ae45e8a9e81cac4fb7b5c6b30ad5

测试页面访问

部署

./scripts/kms-deploy.sh  # 自动同步并部署测试页面到 QEMU

🚀 KMS v2.0 生产环境部署成功 (2025-10-02 11:14)

部署概况

使用模式1 (自动化模式) 成功部署到生产环境 https://kms.aastar.io

部署步骤:

# 1. 清理
./scripts/kms-cleanup.sh

# 2. 编译部署
./scripts/kms-deploy.sh clean

# 3. 一键启动 (自动化模式)
./scripts/kms-auto-start.sh

# 4. Cloudflare tunnel
cloudflared tunnel run kms-tunnel

生产验证结果

API 健康检查

// https://kms.aastar.io/health
{
  "endpoints": {
    "GET": ["/health"],
    "POST": [
      "/CreateKey", "/DescribeKey", "/ListKeys",
      "/DeriveAddress", "/Sign", "/SignHash", "/DeleteKey"
    ]
  },
  "service": "kms-api",
  "status": "healthy",
  "ta_mode": "real",
  "version": "0.1.0"
}

v2.0 功能测试

1. 创建新钱包

{
  "KeyId": "c9ff2117-2fe4-4f6e-8c3a-a197cf74ad07",
  "Address": "0xf424e314aa58d2c881eb89facb4dd807e6f8e7d8",
  "PublicKey": "0x022ddd417dd88fbf9e42452324d39fa05fb6d7d9ba73f0c4068bf118846ba43e38",
  "DerivationPath": "m/44'/60'/0'/0/0"  // ✅ 第一个地址
}

2. 添加第二个地址

{
  "KeyId": "c9ff2117-2fe4-4f6e-8c3a-a197cf74ad07",
  "Address": "0x61968822ad395eb8f78292d60a3a0491c45d4296",
  "PublicKey": "0x021580b31196ff9c4dc4203dafffc665b8c55f21af12adb057dd07036479e1dd50",
  "DerivationPath": "m/44'/60'/0'/0/1"  // ✅ 自动递增到 index 1
}

3. 使用 Address 参数签名

curl -X POST https://kms.aastar.io/Sign \
  -d '{"Address":"0x61968822ad395eb8f78292d60a3a0491c45d4296","Message":"0x1234567890abcdef",...}'

# ✅ 成功返回签名
{
  "Signature": "be65e9738d63c338e0562019c192ee91d6d7a10f88de4650f9b6efec19869c2e1d6118e89d4523e827ccd0ec20840793bc5bbea01bcddcce59394da204f4458d1c",
  "TransactionHash": "[TX_HASH_OR_MESSAGE_HASH]"
}

v2.0 核心特性确认

  1. 自动地址派生: CreateKey 自动返回 Address, PublicKey, DerivationPath
  2. 地址自动递增: 同一钱包新地址 index 自动递增 (0→1)
  3. Address Cache: Normal World 缓存 Address → (wallet_id, path) 映射
  4. Address-based 签名: 支持 {"Address":"0x..."} 参数签名

部署环境

  • 本地访问: http://localhost:3000
  • 公网访问: https://kms.aastar.io
  • 模式: 自动化模式 (Mode 1)
  • 启动时间: ~45秒

已知问题

  • ⚠️ HTML 测试页面返回 500 错误 (warp 静态文件路由问题)
  • ✅ 核心 API 功能全部正常

✅ 钱包地址自动管理系统部署成功 (2025-10-02 03:52)

部署验证结果

本次部署完成以下验证:

  1. 编译成功: 修复所有编译错误(模块导入、类型匹配、未使用变量)
  2. 部署成功: 新二进制文件正确部署到 /opt/teaclave/shared/ta/
  3. API 启动: Health endpoint 显示新的 /SignHash 端点
  4. CreateKey 测试: 返回 Address, PublicKey, DerivationPath
  5. 地址递增测试: 同一钱包创建两个地址,路径正确递增
  6. Address-based 签名: 使用 Address 参数成功签名

测试结果:

// 第一个地址
{
  "KeyId": "48c8d60e-0134-4488-926a-5521accb9e14",
  "Address": "0xad365342c8ee4a951251c10fff8f840cbdf1dd4e",
  "DerivationPath": "m/44'/60'/0'/0/0"
}

// 第二个地址(同一钱包)
{
  "KeyId": "48c8d60e-0134-4488-926a-5521accb9e14",
  "Address": "0xc6ba2ba8537eb5aed7a049d5e51ca7bb08279ff9",
  "DerivationPath": "m/44'/60'/0'/0/1"  ✅ 自动递增
}

// Address-based 签名
curl -X POST /Sign -d '{"Address":"0xad...","Message":"Hello"}'
// ✅ 成功返回签名,无需 DerivationPath

修复的问题

1. 部署脚本问题 (scripts/kms-deploy.sh)

问题: .ta 文件只复制到根目录,expect 脚本期望 ta/ 子目录

修复:

# 添加 ta/ 子目录部署
mkdir -p /opt/teaclave/shared/ta
cp *.ta /opt/teaclave/shared/ta/

影响: 确保 mount --bind ta/ 能正确挂载 TA 文件

2. 模块导入错误 (host/src/api_server.rs)

问题: error[E0433]: use of undeclared crate or module kms_host

修复:

// 添加正确的导入
use kms::address_cache::{update_address_entry, lookup_address};

// 移除错误的调用
// kms_host::update_address_entry(...)  ❌
update_address_entry(...)

3. 类型不匹配错误 (host/src/api_server.rs)

问题: expected (Uuid, String), found (Uuid, &String)

修复:

// Line 351: contains_key 需要引用
if !store.contains_key(&key_id.to_string()) {

// Line 357: 转换为 String
(wallet_uuid, path.to_string())  // 不是 path.clone()

根本原因: path&String 类型,.clone() 在某些上下文中不会自动解引用

4. 未使用的 mut 变量 (ta/src/main.rs)

问题: TA 编译时 -D unused-mut 导致错误

修复:

// Line 153: 移除外部 mut(内部已重新声明)
let (wallet_id, wallet, address_index) = if ...

开发流程优化

简化前 (9 步):

  1. 停止 Docker
  2. 启动 Cloudflare
  3. 清理进程
  4. 部署编译
  5. 启动 Terminal 3
  6. 启动 Terminal 2
  7. 启动 Terminal 1
  8. 手动挂载和启动 API
  9. 测试

简化后 (4 步):

  1. 清理: ./scripts/kms-cleanup.sh
  2. 部署: ./scripts/kms-deploy.sh clean
  3. 只启动 Terminal 2: ./scripts/terminal2-guest-vm.sh
  4. 测试: curl http://localhost:3000/health

关键发现:

  • ✅ Terminal 2 的 expect 脚本自动完成所有挂载和启动
  • ✅ 无需手动执行步骤 8
  • ✅ Terminal 1 和 3 是可选的(仅用于调试)

文档更新

新增文档:

  1. docs/KMS-README.md - 文档导航和快速决策
  2. docs/KMS-Quick-Start.md - 快速开始指南(自动化模式 - 4步)
  3. docs/KMS-Development-Guide-Manual.md - 三终端手动模式(查看日志 - 9步)
  4. docs/KMS-Development-Mode-Comparison.md - 两种模式详细对比
  5. docs/KMS-Development-Workflow.md - 完整开发流程和经验总结

两种开发模式:

模式 1: 自动化模式(快速开发)

  • 适用场景: 日常开发、快速测试
  • 步骤: 4 步(清理 → 部署 → 启动 Terminal 2 → 测试)
  • 文档: docs/KMS-Quick-Start.md

模式 2: 三终端手动模式(调试监控)

  • 适用场景: 查看实时日志、调试问题、监控 TA/CA 输出
  • 步骤: 9 步(包含三终端监控)
  • 文档: docs/KMS-Development-Guide-Manual.md
  • 特点:
    • ✅ Terminal 3: 查看 Secure World (TA) 日志
    • ✅ Terminal 2: 查看 Guest VM (CA) 日志 + 交互式 shell
    • ✅ Terminal 1: 查看 QEMU 系统日志
    • ✅ 步骤 8 增强: 虽然自动化,但保留手动操作说明用于调试

文档内容:

  • 成功经验总结
  • 问题排查指南
  • 两种开发模式对比
  • 一键部署脚本示例
  • 常见问题解答
  • 三终端日志监控指南

关键文件变更

新增文件:

  • kms/host/src/address_cache.rs - 地址缓存模块

修改文件:

  • kms/proto/src/lib.rs - 添加 DeriveAddressAuto 命令
  • kms/proto/src/in_out.rs - 添加 Input/Output 结构
  • kms/ta/src/wallet.rs - 添加计数器字段和方法
  • kms/ta/src/main.rs - 实现 derive_address_auto
  • kms/host/src/lib.rs - 导出 address_cache 模块
  • kms/host/src/ta_client.rs - 添加 derive_address_auto 方法
  • kms/host/src/api_server.rs - 重构 CreateKey 和 Sign API
  • scripts/kms-deploy.sh - 修复 ta 子目录部署

下次开发

快速命令:

# 修改代码后
vim kms/host/src/api_server.rs

# 一键部署测试
./scripts/kms-cleanup.sh && \
./scripts/kms-deploy.sh clean && \
./scripts/terminal2-guest-vm.sh

参考文档: docs/KMS-Quick-Start.md


✅ 实现钱包地址自动管理系统 (2025-10-02 00:11)

实现内容

1. TEE 层实现

  • ✅ 扩展 Wallet 结构体:添加 next_address_indexnext_account_index 字段
  • ✅ 实现 increment_address_index() 方法:自动递增并检查限制(MAX_ADDRESSES_PER_WALLET = 100)
  • ✅ 添加 DeriveAddressAuto 命令:支持创建新钱包或使用已有钱包递增地址
  • ✅ 实现地址自动派生逻辑:m/44'/60'/0'/0/{index}

核心文件

  • kms/proto/src/lib.rs: 添加 DeriveAddressAuto 命令
  • kms/proto/src/in_out.rs: 添加 DeriveAddressAutoInput/Output 结构
  • kms/ta/src/wallet.rs: 添加计数器和限制检查方法
  • kms/ta/src/main.rs: 实现 derive_address_auto() 处理函数

2. Host 层实现

  • ✅ 实现 address_cache.rs 模块:管理 address_map.json 缓存
  • ✅ 添加 TaClient::derive_address_auto() 方法
  • ✅ 修改 CreateKey API:
    • 支持可选 KeyId 参数(None = 新钱包,Some = 已有钱包)
    • 自动派生地址并返回 Address, PublicKey, DerivationPath
    • 更新 address_map.json 缓存
  • ✅ 修改 Sign API:
    • 支持 Address 参数(优先使用)
    • 保留 KeyId + DerivationPath 参数(向后兼容)
    • 实现缓存查询和一致性验证

核心文件

  • kms/host/src/address_cache.rs: 新建,管理地址缓存
  • kms/host/src/ta_client.rs: 添加 derive_address_auto() 方法
  • kms/host/src/api_server.rs: 修改 CreateKeySign API

3. API 变化

CreateKey API (改进后):

Request:
{
    "KeyId": "optional-uuid",  // 可选,不提供则创建新钱包
    "Description": "...",
    "KeyUsage": "SIGN_VERIFY",
    "KeySpec": "ECC_SECG_P256K1",
    "Origin": "AWS_KMS"
}

Response:
{
    "KeyMetadata": {
        "KeyId": "uuid-xxx",
        "Address": "0x1234...",          // ✅ 新增
        "PublicKey": "0x04...",          // ✅ 新增
        "DerivationPath": "m/44'/60'/0'/0/0",  // ✅ 新增
        ...
    }
}

Sign API (改进后):

Request (新方式):
{
    "Address": "0x1234...",  // ✅ 优先使用
    "Message": "base64..."
}

Request (旧方式 - 向后兼容):
{
    "KeyId": "uuid-xxx",
    "DerivationPath": "m/44'/60'/0'/0/0",
    "Message": "base64..."
}

技术细节

  1. 确定性派生:所有地址可从 (wallet_id, entropy, next_address_index) 重新计算
  2. 地址限制:开发阶段限制每个钱包 100 个地址(编译时常量)
  3. 缓存机制address_map.json 存储 address → (wallet_id, derivation_path) 映射
  4. 一致性验证:Sign API 查询缓存后会验证地址是否匹配,防止缓存污染
  5. 恢复能力:缓存丢失后可通过 kms-recovery-cli 工具从 wallet_id 恢复

待完成工作

  • 创建 kms-recovery-cli 工具
    • rebuild-cache 命令:从 wallet_id 重建缓存
    • list-addresses 命令:列出钱包所有地址
    • verify-cache 命令:验证缓存一致性
  • Docker 环境编译测试
  • 端到端功能测试

下一步

用户可以在 Docker 环境中编译测试新功能:

# 1. 进入 Docker
docker exec -it teaclave_dev_env bash

# 2. 编译 TA
cd /root/shared/kms
make ta

# 3. 编译 Host
make host

# 4. 部署和测试(three-terminal 模式)
# Terminal 1: 启动 QEMU
# Terminal 2: 启动 CA
# Terminal 3: 测试新 API

📋 设计讨论:钱包地址管理系统优化 (2025-10-01 23:46)

背景

当前 KMS 系统要求用户在每次 API 调用时都提供 DerivationPath 参数,使用体验复杂。讨论了自动化地址管理和简化 API 的设计方案。

设计方案关键点

  1. 存储架构优化

    • TEE Secure Storage:最小化存储,仅保存 (wallet_id, entropy, next_address_index, next_account_index) (56字节/钱包)
    • 确定性推导:所有历史地址可从 entropy 重新计算,无需存储完整地址列表
    • 反向索引:新增 address → (wallet_id, derivation_path) 映射用于快速查询和恢复
    • Normal World 缓存:使用 JSON 文件存储地址映射(可损坏可重建)
  2. API 改进

    • CreateKey:支持自动递增 address_index,返回 Address/PublicKey/DerivationPath
    • Sign:支持直接使用 Address 参数,隐藏 derivation_path 细节
    • 向后兼容:保留旧参数 KeyId + DerivationPath
  3. 恢复机制

    • 场景 1:Normal World 损坏 → 从 TEE address_lookup 重建缓存
    • 场景 2:已知 wallet_id → 根据 next_address_index 重新派生所有地址
    • 场景 3:仅记得地址 → 通过 TEE 反向索引查询 wallet_id
    • 场景 4:完全遗忘 → 列出所有钱包供用户识别
  4. 容量分析

    • 单钱包(100地址):~5.66 KB
    • 1000 钱包:~5.66 MB
    • 10000 钱包:~56.6 MB
    • 结论:OP-TEE 典型容量(16-64 MB)足够支持数千钱包
  5. 安全决策

    • 完全禁用 ExportMnemonic API(Mnemonic 可从 entropy 实时计算,无需导出)
    • Normal World 缓存需验证一致性(防止缓存污染攻击)

待确认问题

  • ✅ TEE 存储容量:确认计数器方案可完全推导所有地址
  • ✅ Mnemonic 导出:完全禁用
  • ✅ 兼容性策略:先保留旧参数
  • ✅ Normal World 缓存:开发阶段使用 JSON,后续迁移 SQLite

文档输出

  • 创建详细设计文档:docs/KMS-Wallet-Address-Management-Design.md

下一步

  • 等待用户确认设计细节后进入实现阶段

Project Changes Log

🎉 完全修复端口转发和自动启动 (2025-10-01 17:28, 最终验证: 2025-10-01 17:39)

问题:Docker 重启后 curl localhost:3000/health 返回 Connection reset

症状

  • QEMU 启动后 curl http://localhost:3000/health 返回 "Connection reset by peer"
  • 用户说 "kms-api-server is running, ta copied",但 Mac 无法访问

根本原因

  1. QEMU 端口转发配置缺少 3000 端口

    • 检查发现:hostfwd=:127.0.0.1:54433-:4433 (只有 4433,没有 3000)
    • 即使 QEMU 内 API Server 在运行,没有端口转发就无法从 Mac 访问
  2. expect 脚本没有自动启动 API Server

    • listen_on_guest_vm_shell 只做了挂载和 TA 绑定
    • QEMU 重启后需要手动启动 kms-api-server

解决方案

1. 修改 expect 脚本自动启动 API Server

文件: /opt/teaclave/bin/listen_on_guest_vm_shell (Docker 内)

修改内容:在 interact 之前添加自动启动命令:

expect "# $"
send -- "./kms-api-server > kms-api.log 2>&1 &\r"
expect "# $"
send -- "echo 'KMS API Server started'\r"
expect "# $"
interact

效果

  • ✅ QEMU 启动后自动登录
  • ✅ 自动挂载共享目录到 /root/shared
  • ✅ 自动绑定 TA 目录到 /lib/optee_armtz
  • 自动启动 kms-api-server
  • ✅ 进入交互模式供手动调试

2. 验证 QEMU 端口转发配置

检查命令

docker exec teaclave_dev_env ps aux | grep qemu | grep hostfwd

正确输出应该包含

hostfwd=:127.0.0.1:54433-:4433,hostfwd=tcp:0.0.0.0:3000-:3000

关键点

  • 0.0.0.0:3000 而不是 127.0.0.1:3000 (允许 Docker 端口映射)
  • 两个 hostfwd 配置用逗号分隔

3. 完整重启流程(验证通过)

# 1. 停止 QEMU
docker exec teaclave_dev_env pkill -f qemu-system-aarch64

# 2. 停止并重启 expect 脚本(应用新修改)
docker exec teaclave_dev_env pkill -f listen_on_guest_vm_shell
docker exec -d teaclave_dev_env bash -l -c "listen_on_guest_vm_shell"

# 3. 等待 3 秒让监听器启动
sleep 3

# 4. 启动 QEMU(使用修复后的 SDK 脚本)
docker exec -d teaclave_dev_env bash -c "cd /root/teaclave_sdk_src && IMG_DIRECTORY=/opt/teaclave/images IMG_NAME=x86_64-optee-qemuv8-ubuntu-24.04-expand-ta-memory QEMU_HOST_SHARE_DIR=/opt/teaclave/shared LISTEN_MODE=1 ./scripts/runtime/bin/start_qemuv8 > /tmp/qemu.log 2>&1"

# 5. 等待 45 秒让 QEMU 启动和 API Server 自动启动
sleep 45

# 6. 验证端口转发
docker exec teaclave_dev_env ps aux | grep qemu | grep hostfwd

# 7. 测试 Mac 访问
curl http://localhost:3000/health

# 8. 测试公网访问(如果 cloudflared 已启动)
curl https://kms.aastar.io/health

验证结果

$ curl http://localhost:3000/health
{
  "service": "kms-api",
  "status": "healthy",
  "version": "0.1.0",
  "ta_mode": "real",
  "endpoints": {
    "GET": ["/health"],
    "POST": ["/CreateKey", "/DescribeKey", "/ListKeys", "/DeriveAddress", "/Sign", "/DeleteKey"]
  }
}

$ curl https://kms.aastar.io/health
{
  "service": "kms-api",
  "status": "healthy",
  "version": "0.1.0",
  "ta_mode": "real",
  "endpoints": {
    "GET": ["/health"],
    "POST": ["/CreateKey", "/DescribeKey", "/ListKeys", "/DeriveAddress", "/Sign", "/DeleteKey"]
  }
}

所有测试通过!

更新:完善自动启动脚本 (2025-10-01 17:45)

发现的问题

  • Docker 重启后,54321 端口(Secure World Console)的监听器没有自动启动
  • QEMU 启动失败,错误:Failed to connect to 'localhost:54321': Connection refused

修复:修改 scripts/kms-auto-start.sh,添加 54321 端口监听器启动:

# 启动 Secure World 监听器(端口 54321)
docker exec -d teaclave_dev_env bash -c "socat TCP-LISTEN:54321,reuseaddr,fork -,raw,echo=0 > /dev/null 2>&1"
sleep 1

# 启动 Guest VM 监听脚本(端口 54320)
docker exec -d teaclave_dev_env bash -l -c "listen_on_guest_vm_shell"

验证结果

# 重启 Docker 后测试
$ docker restart teaclave_dev_env
$ sleep 10
$ ./scripts/kms-auto-start.sh

🔄 停止旧的 QEMU 和监听器...
🚀 启动 Secure World 监听器(端口 54321)...
🚀 启动 Guest VM 监听脚本(端口 54320)...
🖥️  启动 QEMU(带 3000 端口转发)...
⏳ 等待 45 秒让 QEMU 和 API Server 启动...
✅ 验证端口转发配置...
hostfwd=:127.0.0.1:54433-:4433,hostfwd=tcp:0.0.0.0:3000-:3000
✅ 测试 Mac 本地访问...
{
  "service": "kms-api",
  "status": "healthy",
  "ta_mode": "real",
  "version": "0.1.0"
}
✅ 所有服务已启动!

🎉 Docker 重启后一键启动完全成功!

更新 3:添加端口清理和开发流程改进 (2025-10-01 18:15)

问题:端口占用导致启动失败

错误信息

2025/10/01 10:12:03 socat[3001] E bind(14, {AF=2 0.0.0.0:54321}, 16): Address already in use

修复

  1. 修改 terminal2-guest-vm.sh:启动前自动清理 54320 端口

    docker exec teaclave_dev_env pkill -f "listen_on_guest_vm_shell"
    docker exec teaclave_dev_env pkill -f "TCP-LISTEN:54320"
    docker exec teaclave_dev_env bash -c "lsof -ti:54320 | xargs -r kill -9 2>/dev/null || true"
  2. 修改 terminal3-secure-log.sh:启动前自动清理 54321 端口

    docker exec teaclave_dev_env pkill -f "listen_on_secure_world_log"
    docker exec teaclave_dev_env pkill -f "TCP-LISTEN:54321"
    docker exec teaclave_dev_env bash -c "lsof -ti:54321 | xargs -r kill -9 2>/dev/null || true"
  3. 修改 kms-auto-start.sh:启动前强制清理所有相关端口

开发流程改进

问题发现:POST API 返回 {"error":"Internal server error"} 不是真正的错误,而是缺少 AWS KMS 兼容的 HTTP header。

解决方案

正确的 API 调用方式

# 需要添加 x-amz-target header
curl -X POST http://localhost:3000/CreateKey \
  -H "Content-Type: application/json" \
  -H "x-amz-target: TrentService.CreateKey" \
  -d '{"Description":"Test","KeyUsage":"SIGN_VERIFY","KeySpec":"ECC_SECG_P256K1","Origin":"AWS_KMS"}'

完整开发流程

  1. 修改代码:编辑 kms/host/src/api_server.rs
  2. 部署./scripts/kms-deploy.sh(自动编译 + 复制到共享目录)
  3. 重启 API./scripts/kms-restart-api.sh(新增脚本)
  4. 测试:使用带正确 header 的 curl 命令

新增脚本

  • scripts/kms-restart-api.sh - 重启 QEMU 内的 API Server
  • scripts/kms-monitor.sh - 在 auto-start 后监控各种日志
  • ✅ 所有 terminal 脚本现在会自动清理端口

更新 4: 修复 Cloudflared IPv6 连接错误 (2025-10-01 17:23)

问题:Cloudflared 日志中不断出现:

read tcp [::1]:50823->[::1]:3000: read: connection reset by peer

根本原因

  • Cloudflared 配置使用 http://localhost:3000
  • 系统优先尝试 IPv6 ([::1])
  • 但 KMS API Server 只绑定 IPv4 (0.0.0.0:3000)

解决方案

  1. 修改 ~/.cloudflared/config.yml:

    service: http://127.0.0.1:3000  # 明确使用 IPv4
  2. 重启 cloudflared:

    pkill cloudflared
    cloudflared tunnel run kms-tunnel > /tmp/cloudflared.log 2>&1 &

结果:✅ 不再出现 IPv6 连接错误

更新 4: 新增日志监控脚本

问题:用户担心使用 kms-auto-start.sh 后无法监控 TA/CA 日志

解决方案:创建 scripts/kms-monitor.sh 脚本

功能

  • 选项 1:监控 Secure World 日志 (TA)
  • 选项 2:监控 Guest VM Shell (CA)
  • 选项 3:查看 QEMU 日志
  • 选项 4:查看 API Server 日志
  • 选项 5:查看 Cloudflared 日志

使用方法

# 先启动服务
./scripts/kms-auto-start.sh

# 等待启动完成后,在另一个终端运行
./scripts/kms-monitor.sh

更新 4: 完整工作流程澄清

推荐工作流程 A:使用终端脚本(可实时监控)

docker start teaclave_dev_env
./scripts/terminal3-secure-log.sh    # Terminal 3: TA 日志
./scripts/terminal2-guest-vm.sh      # Terminal 2: CA 日志
./scripts/terminal1-qemu.sh          # Terminal 1: QEMU + API 自动启动
# 等待 45 秒后测试
curl http://localhost:3000/health

推荐工作流程 B:使用自动启动(更快速)

docker start teaclave_dev_env
./scripts/kms-auto-start.sh
# 脚本会自动等待 45 秒并测试
# 如需监控日志,另开终端运行:./scripts/kms-monitor.sh

关键点

  • ✅ API Server 会自动启动(expect 脚本实现)
  • ✅ 无需手动重启 API Server
  • ✅ 两种方式都支持完整功能
  • ✅ 可以在 auto-start 后使用 monitor 脚本查看日志

更新 5: 修复 QEMU hostfwd 协议错误 (2025-10-01 17:32)

问题:terminal1 脚本启动 QEMU 失败:

qemu-system-aarch64: Could not set up host forwarding rule ':127.0.0.1:54433-:4433'

根本原因

  • SDK 脚本 /root/teaclave_sdk_src/scripts/runtime/bin/start_qemuv8 第 68 行
  • hostfwd=:127.0.0.1:54433-:4433 缺少协议类型 (tcp/udp)
  • 正确格式应为 hostfwd=tcp:127.0.0.1:54433-:4433

解决方案

# 修复 SDK 脚本
docker exec teaclave_dev_env sed -i '68s/hostfwd=:127.0.0.1:54433-:4433/hostfwd=tcp:127.0.0.1:54433-:4433/' /root/teaclave_sdk_src/scripts/runtime/bin/start_qemuv8

修复后的配置

-netdev user,id=vmnic,hostfwd=tcp:127.0.0.1:54433-:4433,hostfwd=tcp:0.0.0.0:3000-:3000

结果

  • ✅ terminal1 脚本现在可以正常启动 QEMU
  • ✅ 两个端口转发都正确配置
  • ✅ kms-auto-start.sh 也使用相同的修复

更新 6: 统一 terminal1 和 auto-start 脚本 (2025-10-01 17:41)

问题:terminal1 脚本无法正常启动 QEMU,但 auto-start 可以

根本原因

  • terminal1 使用 bash -l -c "LISTEN_MODE=ON start_qemuv8"(依赖环境变量)
  • auto-start 使用完整路径和显式环境变量

解决方案: 修改 scripts/terminal1-qemu.sh 使用与 auto-start 相同的启动方式:

docker exec -it teaclave_dev_env bash -c "cd /root/teaclave_sdk_src && IMG_DIRECTORY=/opt/teaclave/images IMG_NAME=x86_64-optee-qemuv8-ubuntu-24.04-expand-ta-memory QEMU_HOST_SHARE_DIR=/opt/teaclave/shared LISTEN_MODE=1 ./scripts/runtime/bin/start_qemuv8"

新增启动指南脚本

  • scripts/kms-startup-guide.sh - 显示系统状态和启动说明
  • 自动检查 Docker、Cloudflared、QEMU、API Server 状态
  • 提供两种启动方式的详细说明

结果

  • ✅ terminal1 和 auto-start 现在使用相同的启动逻辑
  • ✅ 两种方式都能正常工作
  • ✅ 新增启动指南方便用户使用

最终验证 (2025-10-01 17:41)

所有功能已完全验证正常:

✅ 本地访问

$ curl http://localhost:3000/health
{"status":"healthy","service":"kms-api","version":"0.1.0"}

✅ 公网访问

$ curl https://kms.aastar.io/health
{"status":"healthy","service":"kms-api","version":"0.1.0"}

✅ 创建密钥

$ curl -X POST https://kms.aastar.io/CreateKey \
  -H "Content-Type: application/json" \
  -H "x-amz-target: TrentService.CreateKey" \
  -d '{"Description":"Test","KeyUsage":"SIGN_VERIFY","KeySpec":"ECC_SECG_P256K1","Origin":"AWS_KMS"}'
{"KeyMetadata":{...},"Mnemonic":"[MNEMONIC_IN_SECURE_WORLD]"}

✅ Cloudflared

  • IPv6 连接错误已修复
  • 自 10:35 重启后无新错误
  • 稳定运行超过 5 分钟

✅ 启动流程

  • Docker 重启后一键启动: ./scripts/kms-auto-start.sh
  • 手动三终端启动: terminal3 → terminal2 → terminal1
  • 两种方式都正常工作

诊断过程总结

  1. 检查 QEMU 端口转发配置 → 发现缺少 3000 端口
  2. 确认 Docker 内访问失败docker exec teaclave_dev_env curl http://127.0.0.1:3000 也失败
  3. 尝试通过 socat 连接 QEMU → 超时(QEMU 可能还在启动)
  4. 测试 Mac localhost:3000 → "Empty reply from server"(端口转发工作,但服务未运行)
  5. 意识到问题:端口转发正确,但 API Server 在 QEMU 重启后没有自动启动
  6. 修改 expect 脚本 → 添加自动启动 kms-api-server
  7. 重启整个流程 → 成功!

关键经验

  1. Docker 重启后的完整启动顺序

    • 先启动 expect 监听脚本
    • 再启动 QEMU
    • expect 自动登录并启动 API Server
  2. 端口转发调试方法

    # 检查 QEMU 配置
    docker exec teaclave_dev_env ps aux | grep qemu | grep hostfwd
    
    # 测试 Docker 内访问
    docker exec teaclave_dev_env curl http://127.0.0.1:3000/health
    
    # 测试 Mac 访问
    curl http://localhost:3000/health
  3. "Empty reply from server" vs "Connection reset"

    • Empty reply: 端口转发正常,但服务未运行
    • Connection reset: 端口转发有问题或端口未开放

🔧 监控系统稳定性修复 (2025-09-30 20:20)

解决 Terminal 2/3 在 tmux 中无日志显示的问题

✅ 创建稳定的监控脚本,完全避免 socat 在 tmux 环境中的不稳定问题!

问题诊断

用户报告:在使用 ./scripts/monitor-all-tmux.sh 时,Terminal 2 (CA) 和 Terminal 3 (TA) 没有显示日志。

根本原因:

  • 原始监控脚本使用 socat 连接到 QEMU 串口 (tcp:localhost:54320)
  • socat 在 tmux 伪终端(pty)环境中不稳定
  • I/O 缓冲导致命令发送后阻塞或超时
  • QEMU 串口的 TCP server 模式只接受单个连接,多个 socat 会冲突

解决方案

创建了三个新的替代监控脚本 + 详细的故障排查文档:

1. monitor-terminal2-ca-alt.sh (CA 监控替代方案)

原理: 从 Cloudflared debug 日志提取 API 调用信息

优势:

  • ✅ 完全稳定,不使用 socat
  • ✅ 显示完整的 HTTP 方法、路径、时间戳
  • ✅ 自动映射 API 端点到 TA 操作
  • ✅ 显示响应状态码和大小

监控输出示例:

[2025-09-30T12:08:47Z] 📨 POST /CreateKey
   └─ 正在调用 TA: 创建新钱包
   ✅ 响应: 200 OK (size: 512 bytes)

[2025-09-30T12:09:15Z] 📨 POST /Sign
   └─ 正在调用 TA: 签名消息
   ✅ 响应: 200 OK (size: 256 bytes)
2. monitor-terminal3-ta-alt.sh (TA 监控替代方案)

原理: 显示 TA 支持的命令列表和状态信息(不依赖实时日志)

为什么不显示实时 TA 日志?

  1. OP-TEE TA 默认不输出详细日志: Secure World 日志需要在编译时启用 trace
  2. dmesg 只有框架级别日志: 例如 "session opened", "invoke command"
  3. TA 内部操作应该是安全的: 加密操作不应输出到系统日志

监控输出:

TA 状态: ✅ 已加载到 /lib/optee_armtz/
TA UUID: 4319f351-0b24-4097-b659-80ee4f824cdd

📋 TA 支持的命令:
   - CMD_CREATE_WALLET (0x1001): 创建新钱包
   - CMD_DERIVE_KEY (0x2001): 派生子密钥
   - CMD_SIGN_MESSAGE (0x3001): 签名消息
   ... (完整列表)

💡 TA 操作可以通过以下方式推断:
   - Terminal 2: 看到哪个 API 被调用
   - Terminal 4: 看到请求和响应
3. monitor-all-tmux-v2.sh (稳定版统一监控)

特性:

  • 使用 monitor-terminal2-ca-alt.sh 代替原始的 CA 监控
  • 使用 monitor-terminal3-ta-alt.sh 代替原始的 TA 监控
  • 保持 Terminal 1 (QEMU) 和 Terminal 4 (Cloudflared) 不变

启动命令:

# 推荐使用 V2(稳定版)
./scripts/monitor-all-tmux-v2.sh

# 原版(可能在 tmux 中不稳定)
./scripts/monitor-all-tmux.sh
4. docs/Monitoring-Troubleshooting.md (故障排查指南)

内容:

  • 详细解释为什么 socat 在 tmux 中不稳定
  • 对比原版和 V2 监控脚本的优缺点
  • 如何在需要时手动查看 QEMU 内的真实日志
  • 如何在 TA 代码中启用 trace 日志
  • 完整的监控工作流建议

技术细节

socat 在 tmux 中不稳定的原因
  1. tmux 面板使用伪终端(pty): 不是真正的 tty
  2. socat 需要持续的双向通信: pty 的 I/O 缓冲可能导致阻塞
  3. QEMU 串口 TCP 模式: -serial tcp:localhost:54320,server,nowait 只接受一个连接
  4. 交互式 shell 的限制: docker exec -it 在 tmux 面板中行为不一致
替代方案的优势
方面 原版 (socat) V2 (替代方案)
稳定性 ❌ 在 tmux 中不稳定 ✅ 完全稳定
CA 日志 真实的 Rust 日志 API 调用摘要
TA 日志 dmesg 输出 命令参考
易用性 容易卡住 即开即用
调试价值 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐

结论: V2 方案对于日常开发测试已经足够,深度调试时可以手动使用 socat。

完整的调用链监控

使用 V2 脚本可以看到完整的 API 调用流程:

[Terminal 4 - Cloudflared]
  2025-09-30T12:08:47Z DBG POST https://kms.aastar.io/CreateKey HTTP/1.1

[Terminal 2 - CA 操作推断]
  📨 POST /CreateKey
  └─ 正在调用 TA: 创建新钱包 (CMD_CREATE_WALLET)

[Terminal 3 - TA 状态]
  TA 支持 CMD_CREATE_WALLET: 生成助记词和主密钥

[Terminal 2 - 响应]
  ✅ 响应: 200 OK (size: 512 bytes)

[Terminal 4 - Cloudflared]
  2025-09-30T12:08:48Z DBG 200 OK content-length=512

使用方法

推荐流程(稳定版)
# Step 1: 启用 cloudflared debug 日志
./scripts/start-cloudflared-debug.sh

# Step 2: 启动 V2 监控(稳定版)
./scripts/monitor-all-tmux-v2.sh

# Step 3: 在浏览器测试
# 访问 https://kms.aastar.io/test

# Step 4: 观察所有四个面板
# ✅ Terminal 1: QEMU 系统状态
# ✅ Terminal 2: API 调用 + TA 操作描述
# ✅ Terminal 3: TA 命令参考
# ✅ Terminal 4: HTTP 请求/响应
深度调试(需要真实 CA 日志)
# 在单独的终端连接到 QEMU Guest
socat - TCP:localhost:54320

# 登录 (通常 root 无密码)
# 用户名: root

# 查看实时 CA 日志
tail -f /tmp/kms.log

# 查看 OP-TEE 内核日志
dmesg | grep -i "optee\|tee" | tail -30

注意: 手动 socat 连接会占用 QEMU 串口,导致监控脚本无法工作。

文件清单

新增文件:

  • scripts/monitor-terminal2-ca-alt.sh - CA 监控(从 cloudflared 日志提取)
  • scripts/monitor-terminal3-ta-alt.sh - TA 监控(显示命令参考)
  • scripts/monitor-all-tmux-v2.sh - 稳定版统一监控脚本
  • docs/Monitoring-Troubleshooting.md - 详细的故障排查指南

保留文件:

  • scripts/monitor-terminal2-ca.sh - 原版(可能不稳定)
  • scripts/monitor-terminal3-ta.sh - 原版(可能不稳定)
  • scripts/monitor-all-tmux.sh - 原版(可能不稳定)

已知限制

  1. V2 的 Terminal 2 看不到 Rust 日志: 例如 log::info!("...") 的输出

    • 解决: 手动 socat 连接查看
  2. V2 的 Terminal 3 不显示实时 TA 日志: 这是 OP-TEE 的设计

    • 解决: 在 TA 代码中添加 trace_println!() 并重新编译
  3. 原版脚本在单独终端中可用: 不在 tmux 中使用时是稳定的

    • 使用场景: 单独打开 4 个终端窗口运行

下一步

  • ✅ 监控系统稳定性问题已解决
  • ✅ 用户可以看到完整的 API 调用链
  • ⏳ 考虑添加日志文件持久化方案(通过 9p 共享目录)
  • ⏳ 考虑在 KMS API Server 中添加更详细的日志输出

此次修复彻底解决了监控系统在 tmux 环境中的稳定性问题,提供了可靠的日常开发监控方案!

最后更新: 2025-09-30 20:20 +07


📊 完整监控系统实现和交互式 Web UI 部署 (2025-09-30 18:53)

实现从 Web UI 到 OP-TEE Secure World 的完整调用链可视化

✅ 成功部署交互式 KMS API 测试页面和四层监控系统!

核心成就

1. 交互式 Web UI 测试页面

公网访问地址:

页面特性:

  • 🎨 美观的渐变紫色界面
  • 🔧 8个 API 端点的交互式测试表单
  • ⚡ 实时响应显示和错误提示
  • 📋 预填充示例数据
  • ⏱️ 请求时间统计
  • 🌐 完整的中文界面

实现方式:

// kms/host/src/api_server.rs
let test_ui = warp::path("test")
    .and(warp::get())
    .map(|| {
        match std::fs::read_to_string("/root/shared/kms-test-page.html") {
            Ok(html) => warp::reply::html(html),
            Err(_) => warp::reply::html("<html><body><h1>Test UI not available</h1></body></html>")
        }
    });

部署路径:

  • 开发源文件: docs/kms-test-page.html
  • Docker 路径: /opt/teaclave/shared/kms-test-page.html
  • QEMU Guest 路径: /root/shared/kms-test-page.html (通过 9p virtio 挂载)
2. 四层监控系统架构

监控调用链:

┌─────────────────────────────────────────────────────┐
│ Web UI: https://kms.aastar.io/test                 │
│ 用户在浏览器中测试 API                                │
└──────────────┬──────────────────────────────────────┘
               │ HTTPS Request
               ↓
┌─────────────────────────────────────────────────────┐
│ Terminal 4: Cloudflared Tunnel                      │
│ - 监控公网 HTTPS 请求进入                             │
│ - 隧道连接状态                                        │
│ - 请求/响应日志                                       │
└──────────────┬──────────────────────────────────────┘
               │ HTTP (localhost:3000)
               ↓
┌─────────────────────────────────────────────────────┐
│ Terminal 2: KMS API Server (CA - Normal World)      │
│ - HTTP 请求解析                                      │
│ - API 端点路由                                       │
│ - CA → TA 调用                                       │
│ - 响应返回                                           │
└──────────────┬──────────────────────────────────────┘
               │ TEEC API
               ↓
┌─────────────────────────────────────────────────────┐
│ Terminal 3: OP-TEE TA (Secure World)                │
│ - TA 会话管理                                        │
│ - 密钥管理操作                                       │
│ - 加密签名执行                                       │
│ - Secure World 日志                                 │
└──────────────┬──────────────────────────────────────┘
               │ Hardware TEE
               ↓
┌─────────────────────────────────────────────────────┐
│ Terminal 1: QEMU Guest VM                           │
│ - 系统启动日志                                       │
│ - 内核消息                                           │
│ - QEMU 运行状态                                      │
└─────────────────────────────────────────────────────┘
3. 监控脚本实现

新增文件:

  • scripts/monitor-terminal1-qemu.sh - QEMU Guest VM 监控
  • scripts/monitor-terminal2-ca.sh - KMS API Server (CA) 监控
  • scripts/monitor-terminal3-ta.sh - OP-TEE TA (Secure World) 监控
  • scripts/monitor-terminal4-cloudflared.sh - Cloudflared Tunnel 监控
  • scripts/monitor-all-tmux.sh - 一键启动全部监控(tmux 四分屏)
  • scripts/start-monitoring.sh - 监控系统使用说明
  • scripts/test-monitoring.sh - 自动化测试脚本
  • docs/Monitoring-Guide.md - 完整监控指南文档 (12KB, 430行)

Terminal 1: QEMU 监控

# 监控 QEMU 进程和 Guest VM 日志
docker exec -it teaclave_dev_env bash -c "
echo '📊 QEMU 进程信息:'
ps aux | grep qemu-system-aarch64 | grep -v grep
echo '📝 最近的 QEMU 日志:'
tail -f /tmp/qemu.log
"

Terminal 2: CA 监控

# 通过 socat 连接到 QEMU 串口,监控 KMS API Server
docker exec -it teaclave_dev_env bash -c "
(
echo 'ps aux | grep kms-api-server | grep -v grep'
sleep 2
echo 'tail -f /tmp/kms.log'
sleep 1
) | socat - TCP:localhost:54320
"

Terminal 3: TA 监控

# 监控 OP-TEE 相关的内核日志
docker exec -it teaclave_dev_env bash -c "
(
while true; do
    echo 'clear'
    echo 'dmesg | grep -i -E \"(optee|teec|tee)\" | tail -30'
    echo 'sleep 3'
    sleep 2
done
) | socat - TCP:localhost:54320
"

Terminal 4: Cloudflared 监控

# 监控 Cloudflare Tunnel 公网流量
docker exec -it teaclave_dev_env bash -c "
echo '📊 Cloudflared 进程信息:'
ps aux | grep cloudflared | grep -v grep
echo '📝 Cloudflared 隧道日志:'
tail -f /tmp/cloudflared.log
"
4. Tmux 统一监控界面

一键启动:

./scripts/monitor-all-tmux.sh

四分屏布局:

┌──────────────────┬──────────────────┐
│   Terminal 1     │   Terminal 2     │
│     QEMU         │      CA          │
│   Guest VM       │  KMS API Server  │
├──────────────────┼──────────────────┤
│   Terminal 3     │   Terminal 4     │
│      TA          │   Cloudflared    │
│  Secure World    │     Tunnel       │
└──────────────────┴──────────────────┘

Tmux 快捷键:

  • Ctrl+B, 方向键 - 在面板间切换
  • Ctrl+B, [ - 进入滚动模式(q 退出)
  • Ctrl+B, d - 断开会话(监控继续运行)
  • Ctrl+B, & - 关闭整个会话
5. 完整监控指南文档

docs/Monitoring-Guide.md 包含:

  • 监控架构详细说明
  • 两种启动方式(tmux / 独立终端)
  • 每个监控层的详细解释
  • 三个完整的测试场景示例
  • 故障排查指南
  • 高级监控技巧
  • 性能分析方法

测试场景示例:

  1. 创建钱包: CreateKey → 观察四层调用链
  2. 派生地址: DeriveAddress → 验证路径解析
  3. 签名交易: Sign → 追踪签名执行
6. 技术难点解决

问题 1: 大文件嵌入导致链接错误

// ❌ 失败方案
const HTML: &str = include_str!("kms-test-page.html");

// 错误: ld returned 1 exit status
// /usr/bin/ld: file in wrong format

解决方案: 运行时从文件系统读取

// ✅ 成功方案
std::fs::read_to_string("/root/shared/kms-test-page.html")

问题 2: QEMU 串口自动化

使用 socat 连接到 QEMU TCP 串口 (localhost:54320):

# 自动发送命令
(echo 'command1'; sleep 1; echo 'command2') | socat - TCP:localhost:54320

# 交互式连接
socat - TCP:localhost:54320

问题 3: Docker 内运行 cloudflared

由于 Docker for Mac 网络限制,cloudflared 必须运行在容器内部访问 localhost:3000。

使用说明

启动监控系统

方案 A: 一键启动(推荐)

./scripts/monitor-all-tmux.sh

方案 B: 独立终端窗口

# 在 4 个独立终端中分别运行
./scripts/monitor-terminal1-qemu.sh
./scripts/monitor-terminal2-ca.sh
./scripts/monitor-terminal3-ta.sh
./scripts/monitor-terminal4-cloudflared.sh
测试完整调用链
  1. 启动监控系统(上述任一方案)
  2. 访问 https://kms.aastar.io/test
  3. 点击 "CreateKey - 创建密钥"
  4. 观察四个监控面板的实时日志输出:
    • Terminal 4: 看到 HTTPS 请求从公网进入
    • Terminal 2: KMS API Server 解析请求并调用 TA
    • Terminal 3: OP-TEE TA 在 Secure World 执行密钥生成
    • Terminal 4: 响应通过隧道返回到公网
自动化测试
./scripts/test-monitoring.sh

该脚本会:

  • 检查所有服务状态(QEMU, KMS API Server, Cloudflared)
  • 发送 CreateKey 测试请求
  • 验证日志记录
  • 生成测试报告

实际验证结果

API 测试成功:

$ curl -X POST https://kms.aastar.io/CreateKey \
  -H "Content-Type: application/json" \
  -H "X-Amz-Target: TrentService.CreateKey" \
  -d '{"Description":"monitor-test","KeyUsage":"SIGN_VERIFY","KeySpec":"ECC_SECG_P256K1","Origin":"AWS_KMS"}'

✅ HTTP 200 OK
✅ KeyId: 3f2cd804-ec78-4ec7-8468-0964a382b8a6
✅ 响应时间: ~300ms

服务状态验证:

✅ QEMU: 运行中
✅ KMS API Server: 运行中 (http://0.0.0.0:3000)
✅ Cloudflared: 隧道已连接 (4个边缘节点)
✅ Web UI: 可访问 (https://kms.aastar.io/test)

监控脚本验证:

✅ 所有监控脚本已创建并设置可执行权限
✅ Tmux 统一监控脚本可用
✅ 文档完整 (docs/Monitoring-Guide.md)

开发流程更新

新的完整测试流程:

1. 📝 开发/修改代码
   └── vim kms/host/src/api_server.rs

2. 🔨 构建部署
   └── ./scripts/kms-deploy.sh

3. 📊 启动监控
   └── ./scripts/monitor-all-tmux.sh

4. 🌐 测试 API
   ├── 浏览器: https://kms.aastar.io/test
   └── curl: curl -X POST https://kms.aastar.io/CreateKey ...

5. 👀 观察调用链
   ├── Terminal 4: 公网请求进入
   ├── Terminal 2: CA 处理请求
   ├── Terminal 3: TA 执行操作
   └── Terminal 4: 响应返回

文件结构更新

AirAccount/
├── docs/
│   ├── kms-test-page.html       # 交互式 Web UI (NEW)
│   └── Monitoring-Guide.md      # 监控指南 (NEW)
│
├── scripts/
│   ├── monitor-terminal1-qemu.sh        # QEMU 监控 (NEW)
│   ├── monitor-terminal2-ca.sh          # CA 监控 (NEW)
│   ├── monitor-terminal3-ta.sh          # TA 监控 (NEW)
│   ├── monitor-terminal4-cloudflared.sh # Cloudflared 监控 (NEW)
│   ├── monitor-all-tmux.sh              # Tmux 统一监控 (NEW)
│   ├── start-monitoring.sh              # 使用说明 (NEW)
│   └── test-monitoring.sh               # 自动化测试 (NEW)
│
└── kms/host/src/
    └── api_server.rs            # 添加 / 和 /test 路由 (MODIFIED)

技术要点总结

1. Web UI 部署方式
  • 使用 Warp 框架的文件服务功能
  • 运行时读取 HTML 文件(避免编译时嵌入大文件)
  • 优雅降级(文件不存在时显示错误页面)
2. 多层监控技术
  • Docker exec: 在容器内执行监控命令
  • socat: 连接到 QEMU TCP 串口 (localhost:54320)
  • tail -f: 实时监控日志文件
  • dmesg: 监控内核和 OP-TEE 消息
3. Tmux 会话管理
  • 自动创建四分屏布局
  • 每个面板运行独立的监控脚本
  • 支持断开/重连(监控持续运行)
4. 日志文件位置
  • QEMU 日志: /tmp/qemu.log (Docker 内)
  • KMS API 日志: /tmp/kms.log (QEMU Guest 内)
  • Cloudflared 日志: /tmp/cloudflared.log (Docker 内)
  • OP-TEE 日志: dmesg (QEMU Guest 内)

性能和可用性

  • Web UI 响应: < 100ms (本地加载)
  • API 响应: 200-300ms (端到端)
  • 监控延迟: < 1s (实时日志流)
  • 系统可用性: 24/7 (所有服务持久运行)

下一步计划

短期任务:
  1. ✅ Web UI 部署完成
  2. ✅ 监控系统完成
  3. ⏳ 添加更多 API 测试用例
  4. ⏳ 性能优化(减少响应时间)
长期任务:
  1. ⏳ 实现完整的 AWS KMS API 兼容
  2. ⏳ 添加 API 认证和访问控制
  3. ⏳ 监控告警和自动恢复
  4. ⏳ 部署到真实 Raspberry Pi 5 硬件

此次更新提供了完整的开发和测试体验,从用户友好的 Web UI 到深入的系统级监控,为后续功能开发和性能优化奠定了坚实基础!

最后更新: 2025-09-30 18:53 +07


🌐 KMS API 成功发布到公网 https://kms.aastar.io (2025-09-30 19:05)

完成 KMS API Server 在 QEMU + OP-TEE 环境中的完整部署

✅ KMS API 已成功发布到公网,通过 Cloudflare Tunnel 提供 24/7 访问!

核心成就

1. 网络架构设计与实现
Internet → kms.aastar.io (Cloudflare)
  ↓
Cloudflared (运行在 Docker 内)
  ↓
Docker:3000 (端口映射 -p 3000:3000)
  ↓
QEMU Guest VM:3000 (QEMU hostfwd)
  ↓
KMS API Server (Actix-web, Rust)
  ↓
OP-TEE Client API (TEEC)
  ↓
Secure World: eth_wallet TA
  (UUID: 4319f351-0b24-4097-b659-80ee4f824cdd)
2. Docker 容器配置更新

修改: scripts/kms-dev-env.sh

  • 添加端口映射: -p 3000:3000
  • 支持 KMS API 从 QEMU 到 Docker 的端口转发

配置内容:

docker run -d \
    --name $CONTAINER_NAME \
    -p 3000:3000 \
    -v "$SDK_PATH:/root/teaclave_sdk_src" \
    -w /root/teaclave_sdk_src \
    $DOCKER_IMAGE \
    tail -f /dev/null
3. QEMU 启动配置优化

串口配置: 从 -serial stdio 改为 -serial tcp:localhost:54320

  • 允许通过 socat 自动发送命令
  • 支持非交互式脚本部署

端口转发: 添加 KMS API 端口

-netdev user,id=vmnic,\
  hostfwd=:127.0.0.1:54433-:4433,\
  hostfwd=tcp:127.0.0.1:3000-:3000
4. Cloudflared 容器内部署

关键发现: Docker for Mac 端口映射限制

  • Mac 无法直接访问 localhost:3000(Docker 容器端口)
  • 解决方案:cloudflared 运行在 Docker 容器内部

部署步骤:

# 1. 在 Docker 内安装 cloudflared
docker exec teaclave_dev_env bash -c \
  "curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \
   -o /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared"

# 2. 复制配置文件到容器
docker cp ~/.cloudflared/config.yml teaclave_dev_env:/root/.cloudflared/
docker cp ~/.cloudflared/<tunnel-id>.json teaclave_dev_env:/root/.cloudflared/

# 3. 修改配置路径(Mac → Docker)
docker exec teaclave_dev_env bash -c \
  "sed 's|/Users/nicolasshuaishuai/.cloudflared/|/root/.cloudflared/|' \
   /root/.cloudflared/config.yml > /root/.cloudflared/config-docker.yml"

# 4. 启动 cloudflared
docker exec -d teaclave_dev_env bash -c \
  "cloudflared tunnel --config /root/.cloudflared/config-docker.yml run kms-tunnel \
   > /tmp/cloudflared.log 2>&1"
5. 自动化部署脚本

新增文件:

  • scripts/connect-to-qemu-shell.sh: 连接到 QEMU Guest VM
  • scripts/publish-kms-complete.sh: 完整发布流程(待完善)
  • docs/KMS-Development-Guide.md: 详细开发指南

核心部署命令:

# 在 QEMU 中自动部署 KMS
docker exec teaclave_dev_env bash -l -c "
(
echo 'root'
sleep 2
echo ''
sleep 2
echo 'mkdir -p /root/shared'
sleep 1
echo 'mount -t 9p -o trans=virtio host /root/shared'
sleep 2
echo 'cp /root/shared/*.ta /lib/optee_armtz/'
sleep 1
echo 'cd /root/shared'
sleep 1
echo './kms-api-server > /tmp/kms.log 2>&1 &'
sleep 3
) | socat - TCP:localhost:54320
"
6. 测试验证成功

公网访问测试:

$ curl -s https://kms.aastar.io/health | jq .
{
  "endpoints": {
    "GET": ["/health"],
    "POST": [
      "/CreateKey",
      "/DescribeKey",
      "/ListKeys",
      "/DeriveAddress",
      "/Sign",
      "/DeleteKey"
    ]
  },
  "service": "kms-api",
  "status": "healthy",
  "ta_mode": "real",
  "version": "0.1.0"
}

Docker 内测试 (可用):

docker exec teaclave_dev_env curl -s http://127.0.0.1:3000/health

Mac localhost 测试 (不可用,预期行为):

curl http://localhost:3000/health  # ❌ Connection refused (Docker for Mac 限制)

技术要点总结

1. Docker for Mac 网络限制

问题:

  • -p 3000:3000 端口映射在 Mac 上不直接可用
  • --network host 在 Docker for Mac 不支持

原因:

  • Docker for Mac 使用虚拟机(HyperKit/QEMU)
  • Rosetta 2 翻译层影响端口转发

解决方案:

  • ✅ cloudflared 运行在 Docker 内(访问 Docker 内的 localhost:3000)
  • ✅ 公网通过 Cloudflare Tunnel 访问
  • ✅ 测试使用 docker exec ... curl
2. 9p virtio 文件共享

配置:

# QEMU 参数
-fsdev local,id=fsdev0,path=/opt/teaclave/shared,security_model=none
-device virtio-9p-device,fsdev=fsdev0,mount_tag=host

# Guest VM 挂载
mount -t 9p -o trans=virtio host /root/shared

用途:

  • Docker /opt/teaclave/shared/ → QEMU Guest /root/shared/
  • 传递编译产物(kms-api-server, *.ta)
3. TA 部署流程
# 1. 构建(在 Docker 中)
cd /root/teaclave_sdk_src/projects/web3/kms
make

# 2. 同步到共享目录
cp host/target/.../kms-api-server /opt/teaclave/shared/
cp ta/target/.../*.ta /opt/teaclave/shared/

# 3. 在 QEMU Guest 中部署
mount -t 9p -o trans=virtio host /root/shared
cp /root/shared/*.ta /lib/optee_armtz/  # TA 部署到系统目录
./kms-api-server  # 运行 CA (Client Application)
4. 串口自动化

TCP 串口连接:

# 自动发送命令
echo 'ls -la' | socat - TCP:localhost:54320

# 交互式连接
socat - TCP:localhost:54320

优势:

  • 支持脚本自动化部署
  • 无需手动在 QEMU 中输入命令

开发流程更新

新的开发流程 (Docker + QEMU + Cloudflared)
1. 📝 修改代码
   ├── vim kms/host/src/api_server.rs
   └── vim kms/host/src/ta_client.rs

2. 🔨 构建
   └── ./scripts/kms-dev-env.sh build

3. 📦 同步
   └── ./scripts/kms-dev-env.sh sync

4. 🚀 部署到 QEMU
   ├── 启动 QEMU(如未运行)
   ├── 挂载共享目录
   ├── 部署 TA
   └── 启动 KMS API Server

5. ✅ 测试
   ├── Docker 内测试: docker exec teaclave_dev_env curl http://127.0.0.1:3000/health
   └── 公网测试: curl https://kms.aastar.io/health
测试方式对比
测试方式 命令 可用性 说明
Mac localhost curl http://localhost:3000/health Docker for Mac 限制
Docker 内部 docker exec teaclave_dev_env curl http://127.0.0.1:3000/health 推荐本地测试
公网访问 curl https://kms.aastar.io/health 生产环境测试

目录结构更新

AirAccount/
├── docs/
│   └── KMS-Development-Guide.md  # 完整开发指南(NEW)
├── scripts/
│   ├── kms-dev-env.sh            # 更新:添加 -p 3000:3000
│   ├── connect-to-qemu-shell.sh  # 连接 QEMU(NEW)
│   └── publish-kms-complete.sh   # 完整发布(NEW,待完善)
└── kms/
    ├── host/src/
    │   ├── api_server.rs         # KMS HTTP API
    │   └── ta_client.rs          # TA 通信
    └── ta/src/
        └── lib.rs                # TA 实现(保持不变)

已知问题和限制

1. Mac 本地无法直接访问 localhost:3000
  • 原因: Docker for Mac 网络限制
  • 影响: 开发时无法在 Mac 上直接 curl localhost
  • 解决: 使用 docker exec 或公网测试
2. cloudflared 必须运行在 Docker 内
  • 原因: Mac 无法访问 Docker 容器的端口
  • 影响: 无法在 Mac 上直接运行 cloudflared
  • 解决: 已实现容器内 cloudflared 部署
3. QEMU 启动较慢
  • 现象: 需要等待 8-10 秒
  • 影响: 部署流程时间较长
  • 优化: 可考虑保持 QEMU 持久运行

性能指标

  • 部署时间: ~30 秒(QEMU 启动 + KMS 部署)
  • 响应时间: ~200-300ms(公网访问)
  • 可用性: 24/7(cloudflared + Docker)
  • 并发支持: ✅(Actix-web 多线程)

下一步

短期任务:
  1. ✅ 完成公网发布
  2. ⏳ 优化 publish-kms-complete.sh 一键部署
  3. ⏳ 添加健康监控和自动重启
  4. ⏳ 完善错误处理和日志
长期任务:
  1. ⏳ 实现 GetPublicKey API
  2. ⏳ 添加 API 认证和访问控制
  3. ⏳ 性能优化(减少响应时间)
  4. ⏳ 部署到真实 Raspberry Pi 5 硬件

此次部署成功解决了 Docker for Mac 网络限制问题,实现了完整的 TEE-based KMS API 公网服务!

最后更新: 2025-09-30 19:05 +07


🏗️ KMS项目重构与STD模式完整集成 (2025-09-30 14:45)

重大架构调整:建立正确的开发和部署流程

✅ 完成KMS项目从原型到生产级开发环境的完整重构!

核心成就

1. 正确的项目目录结构
AirAccount/
├── kms/                          # 开发源码目录(日常开发在这里)
│   ├── host/src/
│   │   ├── main.rs              # CLI工具
│   │   ├── api_server.rs        # HTTP API服务器
│   │   ├── ta_client.rs         # TA通信客户端
│   │   ├── cli.rs               # 命令行接口
│   │   ├── tests.rs             # 测试模块
│   │   └── lib.rs               # 共享库(NEW)
│   ├── ta/                      # TA源码
│   ├── proto/                   # 协议定义
│   └── uuid.txt                 # 新UUID: 4319f351-0b24-4097-b659-80ee4f824cdd
│
├── third_party/teaclave-trustzone-sdk/
│   └── projects/web3/kms/       # SDK构建目录(脚本自动同步)
│
└── scripts/
    ├── kms-deploy.sh            # 部署脚本(增强版)
    └── kms-dev-env.sh           # 开发环境管理
2. 双二进制架构实现
  • kms (CLI工具): 命令行操作,测试接口
  • kms-api-server (HTTP服务): AWS KMS兼容API

Cargo.toml配置:

[[bin]]
name = "kms"
path = "src/main.rs"

[[bin]]
name = "kms-api-server"
path = "src/api_server.rs"
3. STD模式依赖初始化

关键发现: STD模式需要手动初始化rust/libc依赖

解决方案:

# 在Docker容器中运行
docker exec teaclave_dev_env bash -l -c "cd /root/teaclave_sdk_src && ./setup_std_dependencies.sh"

初始化内容:

  • rust源码: github.com/DemesneGH/rust (optee-xargo分支)
  • libc库: github.com/DemesneGH/libc (optee分支)
4. 依赖版本兼容性调整

为了兼容Docker镜像中的Rust 1.80 nightly,降级了API依赖:

# API server dependencies (compatible with Rust 1.80)
tokio = { version = "1.38", features = ["full"] }
warp = "0.3.6"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
chrono = { version = "0.4.35", features = ["serde"] }
env_logger = "0.10.2"
log = "0.4.21"
num_enum = "0.7.3"

# Pinned transitive dependencies for Rust 1.80 compatibility
idna = "=0.5.0"
url = "=2.5.0"
5. 代码修复

host/src/ta_client.rs:47 - UUID clone修复:

let mut session = self.ctx.open_session(self.uuid.clone())  // 添加.clone()

host/src/api_server.rs - 签名API修复:

// 构造 EthTransaction
let data = if req.transaction.data.is_empty() {
    vec![]
} else {
    hex::decode(&req.transaction.data.trim_start_matches("0x"))?
};

let transaction = proto::EthTransaction {
    chain_id: req.transaction.chain_id,
    nonce: req.transaction.nonce as u128,
    to: Some(to_array),
    value: u128::from_str_radix(&req.transaction.value.trim_start_matches("0x"), 16)?,
    gas_price: u128::from_str_radix(&req.transaction.gas_price.trim_start_matches("0x"), 16)?,
    gas: req.transaction.gas as u128,
    data,
};

// 调用 TaClient SignTransaction
let mut ta_client = TaClient::new()?;
let signature = ta_client.sign_transaction(wallet_uuid, &req.derivation_path, transaction)?;
6. Makefile更新

支持双二进制strip操作:

NAME := kms
API_SERVER_NAME := kms-api-server

strip: host
	@$(OBJCOPY) --strip-unneeded $(OUT_DIR)/$(NAME) $(OUT_DIR)/$(NAME)
	@$(OBJCOPY) --strip-unneeded $(OUT_DIR)/$(API_SERVER_NAME) $(OUT_DIR)/$(API_SERVER_NAME)
7. 部署脚本增强

scripts/kms-deploy.sh - 新增自动同步功能:

# Step 0: 同步开发源码到SDK
log_step "0/4 同步开发源码到SDK..."
log_info "从 kms/ 同步到 third_party/teaclave-trustzone-sdk/projects/web3/kms/"
rsync -av --delete "$KMS_DEV_DIR/" "$KMS_SDK_DIR/"
log_info "✅ 源码同步完成"

# 构建KMS
log_step "2/4 构建KMS项目(Host + TA)..."
docker exec teaclave_dev_env bash -l -c "cd /root/teaclave_sdk_src/projects/web3/kms && make"

# 部署到QEMU共享目录
log_step "3/4 部署到QEMU共享目录..."
docker exec teaclave_dev_env bash -l -c "
    mkdir -p /opt/teaclave/shared && \
    cp /root/teaclave_sdk_src/projects/web3/kms/host/target/aarch64-unknown-linux-gnu/release/kms /opt/teaclave/shared/kms && \
    cp /root/teaclave_sdk_src/projects/web3/kms/host/target/aarch64-unknown-linux-gnu/release/kms-api-server /opt/teaclave/shared/kms-api-server && \
    cp /root/teaclave_sdk_src/projects/web3/kms/ta/target/aarch64-unknown-optee/release/*.ta /opt/teaclave/shared/
"

开发流程说明

正确的开发流程
1. 日常开发
   📝 编辑: kms/ 目录下的代码

2. 构建部署
   🚀 运行: ./scripts/kms-deploy.sh

   自动流程:
   ├─ 同步: kms/ → third_party/.../projects/web3/kms/
   ├─ 编译: Docker中构建 (aarch64-unknown-linux-gnu + aarch64-unknown-optee)
   └─ 部署: 二进制和TA复制到 /opt/teaclave/shared/

3. QEMU测试
   🖥️ 在QEMU Guest VM中:
   ├─ 挂载共享目录: mount -t 9p -o trans=virtio host shared
   ├─ 部署TA: cp shared/*.ta /lib/optee_armtz/
   ├─ 运行CLI: cd shared && ./kms --help
   └─ 运行API服务: cd shared && ./kms-api-server
为什么这样设计?

关于之前的设计问题:

  1. 错误: 直接在SDK内创建kms目录
  2. 错误: kms_api_server.rs放在根目录(不符合CA规范)
  3. 错误: 没有自动同步机制

正确的设计:

  1. AirAccount/kms/: 开发源,版本控制
  2. SDK/projects/web3/kms/: 构建目标,临时文件
  3. 自动rsync同步: 保持两者一致
  4. 双二进制在host/src/: 符合OP-TEE规范

CA部署说明:

  • CA (Client Application) = Host应用
  • 部署时自动复制到共享目录
  • QEMU中直接运行,无需特殊安装
  • TA需要复制到/lib/optee_armtz/由OP-TEE动态加载

编译验证结果

# Host编译成功
-rwxr-xr-x   2 root root 707K kms              # CLI工具
-rwxr-xr-x   2 root root 2.8M kms-api-server   # API服务器

# TA编译成功
-rw-r--r-- 1 root root 595K 4319f351-0b24-4097-b659-80ee4f824cdd.ta

技术要点总结

1. 路径配置
# kms/host/Cargo.toml
[dependencies]
proto = { path = "../proto" }
optee-teec = { path = "../../../../optee-teec" }  # 从SDK根目录算
2. 环境要求
  • STD模式: 需要setup_std_dependencies.sh初始化rust/libc
  • Rust版本: 1.80 nightly (Docker镜像版本)
  • 交叉编译: aarch64-unknown-linux-gnu (Host) + aarch64-unknown-optee (TA)
3. UUID管理
  • 开发环境: 可以共用eth_wallet的UUID进行测试
  • 生产环境: 每个TA应该有唯一UUID避免冲突
  • 当前UUID: 4319f351-0b24-4097-b659-80ee4f824cdd

问题回答

Q1: 为何之前编译成功,这次失败? A: 之前Docker镜像预装了rust/libc,重置SDK后需要重新运行setup_std_dependencies.sh

Q2: 为何kms_api_server.rs之前在根目录? A: 初期设计错误。正确位置应该在kms/host/src/作为第二个binary

Q3: CA是自动加载吗? A: 是的,Host应用(CA)是普通Linux程序,复制到共享目录后可直接运行

Q4: 开发流程是什么? A:

开发 (AirAccount/kms)
  ↓ (脚本自动rsync)
构建 (SDK/projects/web3/kms)
  ↓ (Docker编译)
部署 (/opt/teaclave/shared)
  ↓ (QEMU运行)
测试 (Guest VM)

Q5: 需要在哪开发? A: 在AirAccount/kms/开发,脚本会自动同步到SDK并编译

系统状态

  • Docker容器: teaclave_dev_env 运行中
  • 编译环境: STD模式完全初始化
  • 双二进制: kms + kms-api-server 编译成功
  • 部署脚本: 完整的自动化流程
  • 开发流程: 文档化并验证

下一步

基于这个稳定的开发环境:

  1. 继续开发KMS API功能
  2. 在QEMU中测试完整工作流
  3. 优化性能和错误处理
  4. 准备向真实硬件部署

现在拥有了一个符合OP-TEE开发规范的、自动化的、可重复的KMS开发环境!

最后更新: 2025-09-30 14:45 +07


🚀 Cloudflare 隧道重新授权和 KMS API 公网部署成功 (2025-09-29 22:40)

成功完成隧道重新授权和 DNS 配置

✅ 完整的 Cloudflare 隧道重新部署和 KMS API 公网访问!

主要成就:

1. Cloudflare 账户重新授权
  • 成功执行 cloudflared tunnel login 重新授权流程
  • 清理旧的授权凭证和隧道配置
  • 获得新的账户访问权限
2. 新隧道创建和配置
  • 隧道名称: kms-tunnel
  • 隧道ID: 5ed57b7d-92e7-4877-a975-f14a9f10ebdb
  • 配置文件: /Users/nicolasshuaishuai/.cloudflared/config.yml
  • 凭证文件: /Users/nicolasshuaishuai/.cloudflared/5ed57b7d-92e7-4877-a975-f14a9f10ebdb.json
3. DNS 记录配置成功
  • 公网域名: https://kms.aastar.io
  • DNS 类型: CNAME 记录
  • 目标服务: localhost:3000
  • DNS 传播状态: ✅ 完全生效
4. KMS API 完整功能验证

测试结果:

🎯 测试 https://kms.aastar.io KMS API 隧道
📅 Mon Sep 29 22:38:24 +07 2025

✅ 创建密钥成功: 72525ce6-fef8-4ab1-88f1-a18fae20756d
✅ DescribeKey: 完整元数据返回
✅ ListKeys: 密钥列表功能正常
✅ Sign: ECDSA 签名生成成功
✅ ScheduleKeyDeletion: 密钥删除调度成功
❌ GetPublicKey: 未实现 (返回空响应)

🎉 KMS API 隧道测试完成!
🌐 隧道状态: ✅ 正常运行
📍 公网访问地址: https://kms.aastar.io
🔗 本地服务地址: http://localhost:3000
5. 测试脚本规范化
  • 脚本位置: scripts/test-kms-aastar.sh
  • 功能覆盖: 6个核心 KMS API 端点
  • 自动化测试: 完整的 curl 测试套件
  • 错误处理: 结构化的测试报告

技术架构状态:

🌐 公网访问架构:

Internet → kms.aastar.io → Cloudflare Edge → Tunnel → localhost:3000 → KMS Server

🔒 API 兼容性:

  • AWS KMS 兼容: 完全符合 TrentService.* 格式
  • 标准 HTTP Headers: X-Amz-Target 头部支持
  • JSON-RPC 格式: 标准的请求/响应结构
  • 错误处理: 规范的 HTTP 状态码

📊 性能指标:

  • 响应时间: 平均 ~200-300ms
  • 成功率: 5/6 API 端点正常 (83.3%)
  • 可用性: 24/7 公网访问
  • 并发能力: 支持多客户端同时访问

下一阶段任务规划:

🔧 立即任务 (本次 TODO 列表):
  1. ✅ 移动测试脚本到 scripts/ 目录
  2. ⏳ 报告变更到 docs/Changes.md
  3. ⏳ 创建 git 标签和提交
  4. ⏳ 推送更改到远程仓库
  5. ⏳ 实现 GetPublicKey API 功能
  6. ⏳ 本地测试完善的 API
  7. ⏳ 部署到 QEMU OP-TEE 并测试
  8. ⏳ 发布到临时隧道测试
  9. ⏳ 发布到 KMS 隧道最终测试
🚀 技术提升:
  • GetPublicKey API: 需要实现公钥提取和返回
  • QEMU OP-TEE 部署: 真实 TEE 环境验证
  • 性能优化: 响应时间进一步优化
  • 监控告警: 添加服务健康监控

成功要素分析:

  1. 清理旧配置: 完全移除历史配置避免冲突
  2. 重新授权: 获得最新的账户访问权限
  3. 正确 DNS 配置: 使用账户内已有的域名 (zu.coffee)
  4. 系统化测试: 完整的 API 端点验证
  5. 文档化流程: 详细记录每个步骤和结果

此次部署实现了企业级 KMS 服务的公网可访问性,为后续真实 TEE 环境集成奠定了基础!


(以下内容省略,保持原有历史记录...)

🔧 修复 QEMU 端口转发和公网访问 (2025-10-01 16:30)

问题:502/1033 错误,无法通过 cloudflared 访问 KMS API

症状:

  • curl https://kms.aastar.io/health 返回 502 或 1033 错误
  • Docker 内部可以访问 http://127.0.0.1:3000,但 Mac 无法访问 http://localhost:3000

根本原因:

  1. QEMU 的端口转发配置为 hostfwd=tcp:127.0.0.1:3000-:3000
    • 只绑定到 Docker 容器内的 127.0.0.1
    • Docker 端口映射期望服务监听在 0.0.0.0 上才能转发到宿主机
  2. start-qemu-with-kms-port.sh 使用了错误的路径和配置方式

解决方案

1. 修改 QEMU 端口转发配置

文件: third_party/teaclave-trustzone-sdk/scripts/runtime/bin/start_qemuv8

修改(第 68 行):

# 修改前
-netdev user,id=vmnic,hostfwd=:127.0.0.1:54433-:4433,hostfwd=tcp:127.0.0.1:3000-:3000 \

# 修改后  
-netdev user,id=vmnic,hostfwd=:127.0.0.1:54433-:4433,hostfwd=tcp:0.0.0.0:3000-:3000 \

关键: 使用 0.0.0.0:3000 而不是 127.0.0.1:3000,使得 Docker 端口映射能够正常工作。

2. 修复 start-qemu-with-kms-port.sh 脚本

问题:

  • 脚本试图创建临时启动脚本,但 heredoc 转义问题导致失败
  • 使用了不存在的路径 /opt/teaclave/scripts

解决: 直接使用挂载的 SDK 脚本:

docker exec -d teaclave_dev_env bash -l -c "cd /root/teaclave_sdk_src && LISTEN_MODE=1 ./scripts/runtime/bin/start_qemuv8 > /tmp/qemu.log 2>&1"

3. 完整的网络链路

成功建立了完整的网络转发链路:

QEMU Guest (10.0.2.15:3000)
  ↓ QEMU user network + hostfwd=tcp:0.0.0.0:3000-:3000
Docker Container (0.0.0.0:3000)
  ↓ Docker port mapping -p 3000:3000
Mac Host (localhost:3000)
  ↓ cloudflared tunnel
Public Internet (https://kms.aastar.io)

验证结果

本地访问成功:

$ curl http://localhost:3000/health
{"endpoints":{"GET":["/health"],"POST":[...]},"service":"kms-api","status":"healthy","ta_mode":"real","version":"0.1.0"}

公网访问成功:

$ curl https://kms.aastar.io/health
{"endpoints":{"GET":["/health"],"POST":[...]},"service":"kms-api","status":"healthy","ta_mode":"real","version":"0.1.0"}

启动流程

完整部署流程:

# 1. 确保 Docker 容器运行
./scripts/kms-dev-env.sh status

# 2. 启动 QEMU(使用修复后的配置)
./scripts/start-qemu-with-kms-port.sh

# 3. 连接到 QEMU 并启动 API Server
./scripts/terminal2-guest-vm.sh
# 在 QEMU 内:
mount -t 9p -o trans=virtio host /root/shared
cd /root/shared && ./kms-api-server > kms-api.log 2>&1 &
# 按 Ctrl+C 退出

# 4. 在 Mac 上启动 cloudflared
cloudflared tunnel run kms-tunnel &

# 5. 测试
curl https://kms.aastar.io/health

关键教训

  1. QEMU user network hostfwd: 绑定地址很重要

    • 127.0.0.1:port 只能在容器内访问
    • 0.0.0.0:port 或不指定地址才能通过 Docker 端口映射访问
  2. Docker 端口映射: 需要服务监听 0.0.0.0,而不是 127.0.0.1

  3. 挂载的文件修改会实时同步: Docker -v 挂载的文件修改在容器内立即可见

  4. cloudflared 位置: 在 Mac 上运行 cloudflared,连接到 localhost:3000,通过 Docker 端口映射访问容器内的服务

相关文件

  • third_party/teaclave-trustzone-sdk/scripts/runtime/bin/start_qemuv8 (修改)
  • scripts/start-qemu-with-kms-port.sh (修复)
  • ~/.cloudflared/config.yml (cloudflared 配置)

📌 重要提示:SDK 修改 (2025-10-01)

修改文件(不在 git 版本控制中): third_party/teaclave-trustzone-sdk/scripts/runtime/bin/start_qemuv8

第 68 行修改

# 修改前
-netdev user,id=vmnic,hostfwd=:127.0.0.1:54433-:4433 \

# 修改后
-netdev user,id=vmnic,hostfwd=:127.0.0.1:54433-:4433,hostfwd=tcp:0.0.0.0:3000-:3000 \

重要:每次重新 clone 或更新 SDK submodule 后,需要重新应用此修改!


KMS 自动启动脚本 v2 - 串口交互模式 (2025-10-16)

背景

kms-auto-start.sh 脚本会自动启动 QEMU 并在 Guest VM 内自动启动 API Server。这导致 Guest VM 的串口控制台被 API Server 占用,无法进行交互式命令操作。

解决方案

创建了新版本 kms-auto-start-v2.sh,实现:

  1. 启动 QEMU 但不自动启动 API Server

    • Guest VM 串口(端口 54320)保持可用状态
    • Secure World 日志端口(54321)正常监听
    • QEMU 端口转发配置保持不变(3000 端口)
  2. 集成 Cloudflare Tunnel 启动

    • 自动检测并清理旧的 cloudflared 进程
    • 启动新的 tunnel 到 kms.aastar.io
    • 日志输出到 /tmp/cloudflared.log
  3. 提供交互式管理工具

    • 创建 kms-guest-interactive.sh 菜单式工具
    • 支持启动/停止 API Server
    • 支持执行自定义命令
    • 支持部署新的 TA 二进制
    • 支持查看 API Server 状态和钱包列表

脚本对比

特性 kms-auto-start.sh (v1) kms-auto-start-v2.sh (v2)
QEMU 启动 ✅ 自动启动 ✅ 自动启动
API Server ✅ 自动启动 ❌ 需手动启动
串口可用性 ❌ 被占用 ✅ 可交互
Cloudflare Tunnel 需手动启动 ✅ 自动启动
适用场景 生产环境快速部署 开发调试和监控

使用方式

# 1. 启动 KMS(不启动 API Server)
./scripts/kms-auto-start-v2.sh

# 2. 使用交互式工具
./scripts/kms-guest-interactive.sh
# 选项 3:启动 API Server
# 选项 4:停止 API Server
# 选项 7:执行自定义命令

# 3. 监控 CA 日志
./scripts/kms-qemu-terminal2-enhanced.sh

# 4. 监控 TA 日志
./scripts/kms-qemu-terminal3.sh

# 5. 直接连接 Guest VM 串口(高级)
docker exec -it teaclave_dev_env socat STDIN TCP:localhost:54320

手动启动 API Server

如果需要启动 API Server:

# 方法 1: 使用交互式工具(推荐)
./scripts/kms-guest-interactive.sh
# 选择选项 3

# 方法 2: 使用命令行
echo 'cd /root/shared && nohup ./kms_ca > api.log 2>&1 &' | \
  docker exec -i teaclave_dev_env socat - TCP:localhost:54320

# 等待 15 秒后测试
sleep 15
curl http://localhost:3000/health

关键技术点

  1. 串口监听器配置

    # 使用简单的 socat 转发,不自动执行命令
    socat TCP-LISTEN:54320,reuseaddr,fork -,raw,echo=0
  2. Cloudflare Tunnel 管理

    # 清理旧进程
    pkill -f "cloudflared tunnel run kms-tunnel"
    
    # 启动新进程
    cloudflared tunnel run kms-tunnel > /tmp/cloudflared.log 2>&1 &
  3. 交互式命令执行

    # 发送命令到 Guest VM
    echo 'COMMAND' | docker exec -i teaclave_dev_env socat - TCP:localhost:54320

相关文件

  • scripts/kms-auto-start-v2.sh - 新版启动脚本(保留 v1)
  • scripts/kms-guest-interactive.sh - 交互式管理工具
  • scripts/kms-guest-shell.sh - 简单 shell 连接工具
  • scripts/kms-guest-exec.sh - 单命令执行工具
  • scripts/kms-guest-shell-api.sh - API 方式管理工具

验证状态

# 验证 QEMU 运行
docker exec teaclave_dev_env pgrep -f qemu-system-aarch64

# 验证端口转发
docker exec teaclave_dev_env ps aux | grep qemu | grep hostfwd

# 验证 API Server(如已启动)
curl http://localhost:3000/health

# 验证 Cloudflare Tunnel
ps aux | grep cloudflared | grep -v grep

# 验证公网访问(如 API Server 已启动)
curl https://kms.aastar.io/health

Bug 修复:移除 lsof 依赖

问题:脚本尝试使用 lsof 命令清理端口占用进程,但 Docker 容器内未安装此命令,导致错误信息:

bash: line 1: lsof: command not found

修复:移除 lsof 依赖,因为之前的 pkill 命令已经足够处理进程清理:

# 修复前
docker exec teaclave_dev_env bash -c "lsof -ti:54320 | xargs -r kill -9 2>/dev/null || true"

# 修复后
# 使用 fuser 或直接 pkill(容器内可能没有 lsof)
# 如果端口仍被占用,pkill 已经处理了大部分情况
sleep 2

验证:脚本现在运行无错误,所有服务正常启动。


问题:Terminal 3 端口冲突

问题:使用 kms-auto-start-v2.sh 后,运行 kms-qemu-terminal3.sh 报错:

2025/10/16 06:07:22 socat[988] E bind(14, {AF=2 0.0.0.0:54321}, 16): Address already in use

原因

  • kms-auto-start-v2.sh 会自动启动端口 54321 的监听器(用于 Secure World 日志)
  • 旧的 kms-qemu-terminal3.sh 调用 listen_on_secure_world_log,尝试再次创建监听器
  • 导致端口冲突

解决方案:创建 kms-qemu-terminal3-v2.sh,直接连接到已有监听器而不是创建新的:

# 旧版本(会冲突)
docker exec -it teaclave_dev_env bash -l -c "listen_on_secure_world_log"
# listen_on_secure_world_log 内部执行: socat TCP-LISTEN:54321,reuseaddr,fork -,raw,echo=0

# v2 版本(兼容)
docker exec -it teaclave_dev_env socat - TCP:localhost:54321
# 直接连接,不创建新的监听器

使用方式

# 启动 KMS v2
./scripts/kms-auto-start-v2.sh

# 使用 v2 版本的 terminal3(推荐)
./scripts/kms-qemu-terminal3-v2.sh

# 或者仍可使用旧版本 terminal3,但需要先不启动 v2 自带的监听器

脚本对应关系

启动脚本 Terminal 3 脚本 说明
kms-auto-start.sh (v1) kms-qemu-terminal3.sh 原版本,自己管理监听器
kms-auto-start-v2.sh kms-qemu-terminal3-v2.sh v2 版本,连接已有监听器

相关文件

  • scripts/kms-qemu-terminal3-v2.sh - 新创建,适配 v2 启动脚本
  • scripts/kms-qemu-terminal3.sh - 保留,适配 v1 或手动启动
  • /opt/teaclave/bin/listen_on_secure_world_log - 容器内的原始监听器脚本

KMS 钱包持久化解决方案 (2025-10-16)

问题

QEMU 重启后 OP-TEE Secure Storage 数据丢失,导致:

  • 开发测试时需要重新创建钱包
  • 地址每次都不同,不方便测试
  • 无法保留重要的测试数据

解决方案

提供三个工具解决持久化问题:

1. 开发测试钱包(推荐)

脚本: scripts/kms-init-dev-wallets.sh

使用固定助记词创建测试钱包,重启后地址保持不变:

./scripts/kms-auto-start.sh
sleep 15
./scripts/kms-init-dev-wallets.sh

固定的测试钱包:

  1. dev-wallet-1: test test test test test test test test test test test junk
  2. dev-wallet-2: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
  3. dev-wallet-3: zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong

2. 钱包备份与恢复

备份: scripts/kms-backup-wallets.sh 恢复: scripts/kms-restore-wallets.sh

导出所有钱包到 JSON 文件(包含明文私钥和助记词):

# 备份
./scripts/kms-backup-wallets.sh
# 文件: ~/.kms-backup/wallets_backup_YYYYMMDD_HHMMSS.json

# 恢复
./scripts/kms-restore-wallets.sh ~/.kms-backup/wallets_backup_*.json

⚠️ 安全警告: 备份文件包含明文私钥,仅用于开发测试!

3. 一键启动 + 自动初始化

脚本: scripts/kms-auto-start-with-wallets.sh

一条命令启动 KMS 并初始化测试钱包:

./scripts/kms-auto-start-with-wallets.sh

自动完成:

  1. ✅ 启动 QEMU + API Server
  2. ✅ 等待 API Server 就绪
  3. ✅ 创建固定的测试钱包
  4. ✅ 启动 Cloudflare Tunnel

使用场景

日常开发测试(推荐):

# 一键启动
./scripts/kms-auto-start-with-wallets.sh

# 开发测试...

# 重启时重复相同命令即可

保留重要测试数据:

# 备份
./scripts/kms-backup-wallets.sh

# 重启后恢复
./scripts/kms-auto-start.sh && sleep 15
./scripts/kms-restore-wallets.sh ~/.kms-backup/wallets_backup_latest.json

技术细节

  • 相同助记词生成相同的 wallet_id(从助记词派生)
  • 恢复时使用助记词重新创建钱包,ID 和地址完全一致
  • 备份文件为 JSON 格式,包含 wallet_id、address、private_key、mnemonic

生产环境方案

⚠️ 以上方案仅适用于开发测试!

生产环境应使用:

  1. 持久化 Secure Storage(配置 OP-TEE 持久化后端)
  2. 硬件 TEE (Raspberry Pi 5 真实硬件)
  3. 加密备份 + HSM + 多重签名

相关文件

  • scripts/kms-init-dev-wallets.sh - 初始化固定测试钱包
  • scripts/kms-backup-wallets.sh - 备份所有钱包
  • scripts/kms-restore-wallets.sh - 恢复钱包
  • scripts/kms-auto-start-with-wallets.sh - 一键启动 + 初始化
  • docs/KMS-Wallet-Persistence.md - 完整文档

增强:Terminal 1 自动初始化测试钱包

修改: scripts/kms-qemu-terminal1.sh

现在 Terminal 1 启动后会:

  1. ✅ 启动 QEMU(后台运行)
  2. ✅ 等待 API Server 就绪(最多 30 秒)
  3. ✅ 自动初始化 3 个固定测试钱包
  4. ✅ 显示完成状态

使用方式(三终端模式):

# Terminal 3
./scripts/kms-qemu-terminal3.sh

# Terminal 2
./scripts/kms-qemu-terminal2-enhanced.sh

# Terminal 1(自动初始化钱包)
./scripts/kms-qemu-terminal1.sh

优势:

  • 不再需要单独运行 kms-init-dev-wallets.sh
  • 三终端模式也能自动获得固定测试钱包
  • 重启后钱包自动恢复(地址不变)

改进:三终端启动流程优化

修改文件:

  • scripts/kms-qemu-terminal1.sh - 恢复为简单版本(不自动初始化钱包)
  • scripts/kms-qemu-terminal2.sh - 增强版,自动初始化测试钱包

新的三终端启动流程:

# Terminal 3: Secure World 日志
./scripts/kms-qemu-terminal3.sh

# Terminal 2: Guest VM + 自动初始化钱包(增强版)
./scripts/kms-qemu-terminal2.sh
# 会自动:
# 1. 启动 Guest VM 监听器
# 2. 等待 API Server 启动(最多 60 秒)
# 3. 自动创建 3 个固定测试钱包
# 4. 显示测试命令

# Terminal 1: QEMU
./scripts/kms-qemu-terminal1.sh

优势:

  • ✅ Terminal 2 自动初始化钱包(因为它启动 API Server)
  • ✅ Terminal 1 保持简单(只启动 QEMU)
  • ✅ 逻辑更清晰:谁启动 API,谁负责初始化钱包
  • ✅ 重启后钱包自动恢复

对比:

启动方式 钱包初始化 日志查看 复杂度
kms-auto-start-with-wallets.sh ✅ 自动 ❌ 无 TA 日志 简单
Terminal 3→2→1 ✅ 自动(T2) ✅ CA+TA 中等

2025-10-16 16:37 - KMS v2.1 钱包自动备份系统与可靠部署脚本

新增功能

  • 自动备份系统: 钱包创建时自动将助记词备份到共享目录
  • kms-deploy-clean.sh: 新增可靠的清理部署脚本,解决交叉编译问题
  • 备份文件格式 v2.0: JSON 格式包含 wallet_id, address, mnemonic, derivation_path, backup_time

技术改进

  • 🔧 修复 Rust 交叉编译环境配置(CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER)
  • 🔧 正确设置 CC/CXX 环境变量用于 aarch64 交叉编译
  • 🔧 清理增量编译缓存避免缓存导致的部署问题
  • 🔧 使用 --bin 参数代替 -p 编译特定二进制文件

备份位置

  • Guest VM: /root/shared/kms-wallets-backup/
  • Docker Host: /opt/teaclave/shared/kms-wallets-backup/

部署命令

# 标准部署(增量编译)
./scripts/kms-deploy-clean.sh

# 完全重新编译(清理所有缓存)
./scripts/kms-deploy-clean.sh --force

已知限制

  • ⚠️ 恢复功能待实现: 需要修改 TA 代码支持从助记词创建钱包
  • ⚠️ 不使用 --restart-docker: Docker 重启会导致 rustup 二进制文件损坏

Git 信息

  • Commit: a357e57
  • Tag: v2.1-wallet-backup
  • Branch: KMS