feat(chv-guest): Gitea 同步变量经 seed 进 guest-env(执行器集成)
- 新增 cloud/chv/gitea_sync.py:6 键白名单,三源合并 (宿主 CHV_GITEA_* < 任务 gitea_sync < extra_env), 必填 4 键缺失即 fail-closed,空即不同步 - ssh_transport:GITEA_TOKEN 进密钥集(argv 拒绝),其余 5 键进 guest-env 集(split_guest_env) - hostkeys.write_seed:guest_env 与 secret_env 合并写同一 条目,仍无 runcmd、0600 - config:_gitea_fragment 产 gitea_sync_env(函数内 import, 叶子模块顶层只许标准库) - executor.wake_vm:起 VMM 前合并+校验(gitea_sync_incomplete), guest-env 随 seed 投递;provision_host_key 透传 guest_env - worker:_run_attempt 仅对 CHV 执行器把同步变量并进 gateway_env - 测试:cloud/tests/test_chv_gitea_sync.py 20 项 - 边界:tasks 表无 JSON 列,DB 往返丢任务 gitea_sync; 生产主来源是宿主 CHV_GITEA_* 环境变量
This commit is contained in:
1 parent
67ca0b86cd
commit
e7f699c62b
7 files changed
+785
-37
No files matched your search
+36
-29
@@ -168,20 +168,37 @@ def build_seed_user_data(private_key_text: str, public_key_text: str) -> str:
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def _guest_env_entry(merged_env: dict) -> list:
|
||||
"""guest-env 的 write_files 条目行(0600 root,值经
|
||||
shlex.quote 引用):只能并进已有的 write_files 列表,
|
||||
绝不能再写一个 write_files: 键(YAML 重复键会覆盖掉
|
||||
host key 的两条写文件条目,预置即失效)。"""
|
||||
lines = [
|
||||
" - path: %s" % GUEST_ENV_PATH,
|
||||
" permissions: '0600'",
|
||||
" owner: root:root",
|
||||
" content: |",
|
||||
]
|
||||
for key in sorted(merged_env):
|
||||
lines.append(" %s=%s"
|
||||
% (key, shlex.quote(str(merged_env[key]))))
|
||||
return lines
|
||||
|
||||
|
||||
def write_seed(seed_dir: str, vm_name: str, private_key_text: str,
|
||||
public_key_text: str,
|
||||
secret_env: dict | None = None) -> str:
|
||||
"""写 seed 目录:meta-data + user-data(均为 0600)。
|
||||
secret_env: dict | None = None,
|
||||
guest_env: dict | None = None) -> str:
|
||||
"""写 seed 目录:meta-data + user-data(均为 0600),
|
||||
返回 seed 目录路径。调用方负责随 VM 销毁删掉它。
|
||||
|
||||
返回 seed 目录路径。seed 目录本身不含已知主机之外的
|
||||
共享数据,调用方(执行器关闭/回收)负责删除它。
|
||||
feat-chv-secfix(H2):secret_env 给定时,user-data 再
|
||||
写一个 write_files 条目,把密钥环境变量写进客内
|
||||
GUEST_ENV_PATH(0600 root),值经 shlex.quote 引用后
|
||||
才进文件内容——远程命令 source 该文件即可得到密钥
|
||||
环境,密钥值从不出现在宿主 ssh argv、宿主进程环境与
|
||||
审计明文里。secret_env 为空时不写该条目(客内文件不
|
||||
存在时远程命令也不 source 它,见执行器)。"""
|
||||
secret_env 给定时写进客内 GUEST_ENV_PATH(0600 root,
|
||||
远程命令 source 它得密钥环境,值不进宿主 argv/环境/
|
||||
审计明文)。guest_env 给定时与 secret_env 合并写同一
|
||||
个条目(secret 优先于同名键,防两行同名);guest_env
|
||||
装 boot 时要用的非密钥同步变量(GITEA_URL 等,见
|
||||
gitea_sync):只走 SSH 前缀到不了 cloud-init 时运行
|
||||
的 chv-sync boot。两者皆空时不写该条目。"""
|
||||
os.makedirs(seed_dir, exist_ok=True)
|
||||
meta_path = os.path.join(seed_dir, "meta-data")
|
||||
user_path = os.path.join(seed_dir, "user-data")
|
||||
@@ -190,24 +207,14 @@ def write_seed(seed_dir: str, vm_name: str, private_key_text: str,
|
||||
% (vm_name, vm_name))
|
||||
os.chmod(meta_path, 0o600)
|
||||
user_data = build_seed_user_data(private_key_text, public_key_text)
|
||||
if secret_env:
|
||||
# 注意:只能把条目并进已有的 write_files 列表,绝不能
|
||||
# 再写一个 write_files: 键(YAML 重复键会覆盖掉 host
|
||||
# key 的两条写文件条目,预置即失效)。seed 自 2026-11-07
|
||||
# 起不再带 runcmd 段(见 build_seed_user_data 的根因
|
||||
# 禁令),所以正常走 else 分支追加到 write_files 列表
|
||||
# 末尾;marker 分支只作防御(将来模板若恢复 runcmd,
|
||||
# 条目仍插在其前、仍属同一列表)。
|
||||
lines = [
|
||||
" - path: %s" % GUEST_ENV_PATH,
|
||||
" permissions: '0600'",
|
||||
" owner: root:root",
|
||||
" content: |",
|
||||
]
|
||||
for key in sorted(secret_env):
|
||||
lines.append(" %s=%s"
|
||||
% (key, shlex.quote(str(secret_env[key]))))
|
||||
# 条目插在 runcmd 段之前、仍属同一 write_files 列表。
|
||||
merged_env = dict(guest_env or {})
|
||||
merged_env.update(secret_env or {})
|
||||
if merged_env:
|
||||
lines = _guest_env_entry(merged_env)
|
||||
# 条目插在 runcmd 段之前、仍属同一 write_files 列表
|
||||
#(seed 自 2026-11-07 起不再带 runcmd,见
|
||||
# build_seed_user_data 的根因禁令;marker 分支只作
|
||||
# 防御,将来模板若恢复 runcmd 仍插在其前)。
|
||||
marker = "runcmd:\n"
|
||||
if marker in user_data:
|
||||
head, tail = user_data.split(marker, 1)
|
||||
|
||||
Reference in new issue
Block a user