fix: prepare SSH keys with container UID/GID on host before mounting
- Extend prepare_ssh_key_files() with optional uid/gid parameters - Call os.chown on created files when uid/gid are provided - Gracefully handle PermissionError if API process is not root - In start_instance, extract container user UID/GID from manifest - Pass container UID/GID when preparing instance-level SSH key mounts - Legacy clone-mode SSH keys continue to use root (0,0) - Add unit tests for prepare_ssh_key_files ownership logic - Keep apply_ssh_permissions() as fallback for cases where host chown fails Quality gates: pytest 239 passed (6 pre-existing failures), tsc --noEmit clean
This commit is contained in:
@@ -208,7 +208,11 @@ def apply_ssh_permissions(
|
||||
)
|
||||
key_stat = _exec_and_log(
|
||||
container_id,
|
||||
["sh", "-c", f"stat -c '%U:%G %a %n' {ssh_target}/id_* 2>/dev/null || echo 'no id_* files found'"],
|
||||
[
|
||||
"sh",
|
||||
"-c",
|
||||
f"stat -c '%U:%G %a %n' {ssh_target}/id_* 2>/dev/null || echo 'no id_* files found'",
|
||||
],
|
||||
timeout,
|
||||
"verify-stat-keys",
|
||||
)
|
||||
|
||||
@@ -19,13 +19,21 @@ def _get_fernet() -> Fernet:
|
||||
return Fernet(key)
|
||||
|
||||
|
||||
def prepare_ssh_key_files(instance_dir: str, ssh_key, subdir: str = ".ssh") -> str:
|
||||
def prepare_ssh_key_files(
|
||||
instance_dir: str,
|
||||
ssh_key,
|
||||
subdir: str = ".ssh",
|
||||
uid: int | None = None,
|
||||
gid: int | None = None,
|
||||
) -> str:
|
||||
"""Decrypt and write SSH key files to instance directory for container mounting.
|
||||
|
||||
Args:
|
||||
instance_dir: Path to instance directory
|
||||
ssh_key: SSHKey model instance with encrypted private key
|
||||
subdir: Subdirectory within instance_dir to write to (default: ".ssh")
|
||||
uid: Optional UID to own the files (for bind-mount into non-root container)
|
||||
gid: Optional GID to own the files
|
||||
|
||||
Returns:
|
||||
Path to the .ssh directory
|
||||
@@ -58,6 +66,20 @@ def prepare_ssh_key_files(instance_dir: str, ssh_key, subdir: str = ".ssh") -> s
|
||||
config_path.write_text(config_content)
|
||||
os.chmod(config_path, 0o644)
|
||||
|
||||
# Set ownership to target container user if requested
|
||||
if uid is not None or gid is not None:
|
||||
effective_uid = uid if uid is not None else -1
|
||||
effective_gid = gid if gid is not None else -1
|
||||
try:
|
||||
os.chown(ssh_dir, effective_uid, effective_gid)
|
||||
os.chown(private_key_path, effective_uid, effective_gid)
|
||||
os.chown(public_key_path, effective_uid, effective_gid)
|
||||
os.chown(config_path, effective_uid, effective_gid)
|
||||
except PermissionError:
|
||||
# API process may not be running as root; permission fixer will
|
||||
# handle this post-start if the mount is read-write
|
||||
pass
|
||||
|
||||
return str(ssh_dir)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user