Skip to main content

tkzs config service client,get config or env from Configuration Center

Project description

tkzs_config_service

一个轻量级配置中心,解决多项目手动维护 .env 文件的烦恼。

  • 服务端(Go):用户认证(JWT)+ 配置管理(CRUD)+ SQLite存储
  • 客户端(Python):注册/登录 + 配置上传/下载 + AES+RSA双重加密

新版本 v0.5.0 更新

⚠️ 不兼容性更新 (Breaking Changes)

本次更新对以下 API 进行了不兼容性修改:

方法 变更
upload_config() 形参顺序调整:file_path 移至第一位,config_name 移至第二位
update_config() 形参顺序调整:file_path 移至第一位,config_name 移至第二位
get_config() 形参顺序调整:save_dir 移至 save_path 之前
temp_env_loader 用户回调抛出的异常现在会传播出去(之前仅记录日志)

主要特性

  • 用户注册/登录:支持用户名密码注册,JWT Token认证
  • 配置管理:上传、更新、删除、下载配置文件
  • 双重加密:AES-256-GCM本地加密 + RSA-OAEP传输加密
  • 权限隔离:用户只能管理自己的配置文件

安全特性

  • 密码使用bcrypt加密存储
  • JWT Token认证(24小时有效期)
  • 本地AES-256-GCM加密配置文件
  • 服务端使用用户RSA公钥分块二次加密AES密钥
  • 登录执行"三要素校验":username + password + public_key 必须同时匹配

快速开始

1. 服务端部署

cd service

# 拉取依赖(首次或依赖变更后)
go mod tidy

# 运行服务
go run .

# 编译服务端
go build -ldflags="-s -w" -o ../tkzs-config-service .

当前服务端使用 modernc.org/sqlite(纯 Go 驱动),无需 CGO 即可构建。

服务将启动在 http://0.0.0.0:8443

环境变量(可选):

export PORT=8080  # 自定义端口

2. 客户端安装

# 使用 uv
uv add tkzs-config-service-client

# 使用 pip
pip install tkzs-config-service-client

3. 客户端使用

from tkzs_config_service_client import ConfigServiceClient, configure_client

# 可选:运行时修改全局默认配置(适用于 uv add / pip install 后)
configure_client(
    service_url="http://localhost:8443",
    private_key_path="D:/secure_keys/my_private.pem",  # 全局默认私钥路径
)

# 初始化客户端
client = ConfigServiceClient(
    config_service_url="http://localhost:8443"
)

# 注册(首次使用)
# 方式1:不提供密钥,客户端自动生成RSA密钥对
client.register("my_username", "my_password")

# 方式2:仅提供自备RSA私钥(公钥由私钥推导)
client.register(
    "my_username",
    "my_password",
    user_private_key_path="D:/secure_keys/my_username_private.pem",
)

# 方式3:使用自备RSA公私钥(会校验格式和匹配关系)
client.register(
    "my_username",
    "my_password",
    user_private_key_path="D:/secure_keys/my_username_private.pem",
    user_public_key_path="D:/secure_keys/my_username_public.pem",
)

# 登录(支持本次登录显式指定私钥路径,优先级最高)
client.login("my_username", "my_password", private_key_path="D:/secure_keys/my_private.pem")

# 上传配置(两种写法)
client.upload_config("/path/to/mysql.env")  # config_name 自动取 mysql.env
client.upload_config("/path/to/mysql.env", config_name="mysql.env")

# 查看配置列表
configs = client.list_configs()
for cfg in configs:
    print(f"- {cfg['config_name']} (更新于 {cfg['updated_at']})")

# 下载配置到文件(会自动创建目录)
client.get_config("mysql.env", load_to_env="none", save_dir="./tmp")  # 保存为 ./tmp/mysql.env
client.get_config("mysql.env", load_to_env="none", save_path="./tmp/mysql.env")  # 完整路径

# 下载并加载到环境变量
client.get_config("app.toml", load_to_env="set_temp_env")

# 下载并自定义写环境变量逻辑(例如支持 yaml/json)
def my_temp_env_loader(data: bytes, config_name: str) -> None:
    # 用户自定义解析逻辑
    pass

client.get_config("app.yaml", load_to_env="set_temp_env", temp_env_loader=my_temp_env_loader)

# 更新配置(两种写法)
client.update_config("/path/to/new_mysql.env")
client.update_config("/path/to/new_mysql.env", config_name="mysql.env")

# 删除配置
client.delete_config("old_config.env")

# 注销当前登录用户(逻辑删除,不物理删除)
client.deactivate_user()

# 退出登录
client.logout()

case 示例

  • 基础流程示例:case/simple_case.py
  • 注销重注册示例:case/deactivate_re_register_case.py
  • 私钥优先级示例:case/private_key_priority_case.py
  • API 易用性示例:case/client_api_ergonomics_case.py

运行示例:

uv run python ./case/private_key_priority_case.py

登录私钥路径优先级

客户端登录前会先解析私钥,并据此确定本次登录上送服务端的公钥。私钥路径遵循以下优先级(从高到低):

  1. client.login(...) 登录参数层(最高优先级)
    • 同层规则:private_key_path > private_key_dir
  2. 类属性层(构造函数参数)
    • ConfigServiceClient(private_key_path=...) 设置的值
    • 优先级高于 configure_client(...) 全局配置
  3. configure_client(...) 全局配置层
    • 同层规则:private_key_path > private_key_dir
  4. 默认逻辑:~/.ssl/{username}_private_key.pem(最低)

优先级链示例

configure_client(private_key_path="/path/to/global.pem")  # 第3层
client = ConfigServiceClient(private_key_path="/path/to/class.pem")  # 第2层
client.login("user", "pass", private_key_path="/path/to/login.pem")  # 第1层
# 结果:使用 login.pem

private_key_dir 仅表示私钥文件父目录,文件名会按规则自动拼接: {normalized_username}{private_key_suffix},默认后缀为 _private_key.pem

登录时公钥处理规则:

  1. 若本地已存在 ~/.ssl/{username}_public_key.pem
    会校验"本地公钥"与"私钥推导公钥"是否一致;一致才继续登录。
  2. 若本地不存在该公钥文件:
    客户端会从私钥推导公钥并自动写入本地,再将该公钥发送给服务端。
  3. 服务端登录校验:
    只有 username + password + public_key 三者都与服务端记录一致,才会签发 token。

服务地址(URL)优先级

客户端最终使用的 config_service_url 优先级如下:

  1. ConfigServiceClient(config_service_url=...) 构造参数(最高优先级)
  2. configure_client(service_url=...) 运行时全局配置
  3. 环境变量 CONFIG_SERVICE_URL
  4. 包内默认值

示例:

from tkzs_config_service_client import ConfigServiceClient, configure_client

configure_client(service_url="http://global-service:8443")
client = ConfigServiceClient()  # 使用 http://global-service:8443

client2 = ConfigServiceClient(config_service_url="http://explicit-service:8443")
# client2 使用 http://explicit-service:8443(覆盖全局配置)

encrypted_aes_key 参数说明

upload_config / update_config 里的 encrypted_aes_key 不是"私钥"也不是"要上传的公钥",而是:

  1. 客户端每次上传时临时生成一个随机 AES 会话密钥;
  2. 用 RSA 公钥加密这个 AES 会话密钥;
  3. 将这个密文(Base64)作为 encrypted_aes_key 上传。

因此这个字段的本质是"被加密后的会话密钥密文"。
客户端绝不会上传私钥;注册时上传的公钥用于服务端绑定用户身份和后续二次加密流程。


API 端点

公开接口(无需认证)

方法 路径 描述
POST /api/register 用户注册
POST /api/login 用户登录
GET /health 健康检查

认证接口(需JWT)

方法 路径 描述
GET /api/configs 获取配置列表
DELETE /api/user/deactivate 注销当前用户(逻辑删除)
POST /api/config/upload 上传配置
GET /api/config?name={name} 下载配置
PUT /api/config?name={name} 更新配置
DELETE /api/config?name={name} 删除配置

说明:配置读写接口同时兼容路径参数形式:/api/config/{name}(GET/PUT/DELETE)。

认证接口请求字段(关键)

  • POST /api/register
    • username(必填)
    • password(必填,至少 6 位)
    • public_key(必填,RSA 公钥 PEM)
  • POST /api/login
    • username(必填)
    • password(必填)
    • public_key(必填,必须与该账号注册公钥一致)

数据库

服务端使用SQLite存储数据(tkzs_service.db):

-- 用户表
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE NOT NULL,
    original_username TEXT,      -- 初始用户名(用于逻辑删除追溯)
    password_hash TEXT NOT NULL,  -- bcrypt加密
    public_key TEXT NOT NULL,     -- RSA公钥PEM
    is_deleted INTEGER NOT NULL DEFAULT 0,  -- 0:有效 1:已注销
    deleted_at TIMESTAMP NULL,    -- 注销时间
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 配置表
CREATE TABLE configs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    config_name TEXT NOT NULL,
    aes_key_encrypted_with_public_key BLOB NOT NULL,  -- 二次加密的AES密钥
    encrypted_content BLOB NOT NULL,                    -- 加密的配置文件
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id),
    UNIQUE(user_id, config_name)
);

驱动说明:

  • 使用 modernc.org/sqlite(纯 Go)
  • 适合跨平台构建(如 Windows 构建 Linux 目标)

加密流程

上传配置

1. 客户端生成随机 AES-256 密钥
2. 使用 AES-GCM 加密文件内容
3. 使用客户端 RSA 公钥加密 AES 密钥
4. 上传到服务端(encrypted_content + encrypted_aes_key)
5. 服务端使用用户 RSA 公钥分块二次加密 AES 密钥
6. 服务端存储到 SQLite

下载配置

1. 服务端返回 (encrypted_content, double_encrypted_aes_key)
2. 客户端使用 RSA 私钥按块解密得到 first_encrypted_aes_key
3. 客户端再次使用 RSA 私钥解密得到 AES 密钥
4. 使用 AES 密钥解密文件内容并返回原始数据

客户端密钥文件说明

  • 注册成功后会按用户名保存密钥文件,避免不同用户互相覆盖:
    • ~/.ssl/{username}_private_key.pem
    • ~/.ssl/{username}_public_key.pem
  • 若注册时未提供RSA文件,客户端会自动生成并提示私钥保存位置,请务必离线备份。
  • 若注册时仅提供私钥,客户端会自动推导公钥并完成注册。
  • 若注册时同时提供公私钥,客户端会校验PEM格式并校验公私钥是否匹配。
  • 登录时若检测到该用户密钥文件,会自动切换到该用户密钥进行解密与登录校验。
  • 若仅有账号密码但私钥缺失,登录会被拒绝(无法构造/验证登录公钥)。
  • 若私钥与该用户公钥不匹配,登录会被拒绝。
  • 更换设备时,必须同步配置原账号对应的私钥文件,否则无法解密历史配置。

用户注销(逻辑删除)

  • 接口:DELETE /api/user/deactivate(需 JWT)
  • 客户端调用:client.deactivate_user()
  • 行为说明:
    • 用户不会被物理删除,而是标记为已注销
    • 已注销用户的旧 token 会失效(后续请求会被拒绝)
    • 同名可重新注册,且会分配新的 user_id

文件夹结构

tkzs_config_service/
├── service/                 # Go 服务端
│   ├── main.go             # 主入口
│   ├── database.go         # SQLite 数据库操作
│   ├── auth.go             # JWT 认证
│   ├── handlers.go         # HTTP 处理器
│   ├── crypto.go           # 加密工具
│   └── configs/            # 配置文件目录(按用户ID)
│       ├── 1/
│       │   ├── mysql.env
│       │   └── app.toml
│       └── 2/
│           └── ...
├── src/tkzs_config_service_client/  # Python 客户端
│   ├── __init__.py
│   ├── client.py           # 主客户端类
│   ├── api.py              # API 通信
│   ├── auth.py             # Token 管理
│   ├── crypto.py           # 加密工具
│   └── config.py           # 配置管理(运行时配置、默认值)
├── case/                   # 示例用例
│   ├── simple_case.py              # 基础流程示例
│   ├── private_key_priority_case.py # 私钥优先级示例
│   ├── deactivate_re_register_case.py # 注销重注册示例
│   └── template.env               # 示例配置文件
├── docs/
│   └── configuration-priority.md   # 配置优先级详细说明
├── pyproject.toml
└── README.md

环境变量

服务端

变量 说明 默认值
PORT 服务端口 8443

客户端

变量 说明 默认值
CONFIG_SERVICE_URL 配置服务地址 http://localhost:8443

测试环境变量(case 和 tests 目录)

变量 说明 默认值
CASE_CONFIG_SERVICE_URL case 示例服务地址 http://localhost:8443
TEST_CONFIG_SERVICE_URL 测试服务地址 http://unit-test
TEST_RUNTIME_CONFIG_URL 测试运行时配置地址 http://runtime-config-service

版本历史

v0.5.1 (2026)

配置优先级优化

  • 修复登录私钥路径优先级逻辑,添加类属性检查层
  • 新优先级链login参数 > 类属性 > configure_client全局配置 > 默认值
  • 修复 __init__ 中密钥路径初始化逻辑,正确处理全局配置的优先级
  • 新增完整优先级链测试用例

v0.5.0 (2026)

  • 登录增强为账号/密码/公钥三要素校验
  • 客户端登录时支持"公钥缺失则由私钥推导并落盘"
  • 完善 private_key_path/private_key_dir 的同层与跨层优先级
  • 补充运行时配置 configure_client(...) 场景
  • case 和测试支持环境变量配置服务地址(CASE_CONFIG_SERVICE_URL 等)

v0.3.0 (2024)

  • 新增用户注册/登录功能
  • 新增配置上传/更新/删除功能
  • 改用JWT Token认证
  • 实现AES+RSA双重加密
  • SQLite数据库存储

v0.2.x

  • HMAC-SHA256 + 时间戳 + nonce 防重放
  • IP动态限流

v0.1.x

  • 基础RSA加密认证

License

LGPL-2.1


更多配置优先级与加密参数说明见:docs/configuration-priority.md

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tkzs_config_service_client-0.5.0.tar.gz (82.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tkzs_config_service_client-0.5.0-py3-none-any.whl (35.4 kB view details)

Uploaded Python 3

File details

Details for the file tkzs_config_service_client-0.5.0.tar.gz.

File metadata

  • Download URL: tkzs_config_service_client-0.5.0.tar.gz
  • Upload date:
  • Size: 82.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for tkzs_config_service_client-0.5.0.tar.gz
Algorithm Hash digest
SHA256 2cce8b440a91c7cef67cd7fc2079fc5ab3343788fb4d7d8aac6f8463034fca65
MD5 b5ffb6ae7c2dc6e5d8e1f7cf86d044d4
BLAKE2b-256 53928ff458d692e44187eeff40e1beb8784962a63d95d43e70864fb8d8b22a5f

See more details on using hashes here.

File details

Details for the file tkzs_config_service_client-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: tkzs_config_service_client-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 35.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for tkzs_config_service_client-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 910a9ba830075c8526bd0a92bbe52adaa4573d4e6acf999950d29f89a30c1dae
MD5 e35a2400a91a62d4be059cb7eeb785c2
BLAKE2b-256 4e38e2c0278608ff88efc7bd46d4515360d138e02a0c2de0416ccbb908bd251b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page