fix: set SSH key ownership to container user with mode 600

- Mount SSH keys as bind (not ro) so docker exec --user root can chown
- Add apply_ssh_permissions() to permission_fixer.py
- Call apply_ssh_permissions() after container start for all instance types
- Derive container user from home_dir (/root → root, /home/user → user)
- Tests: apply_ssh_permissions unit tests + start_instance integration tests

Quality gates: pytest 236 passed (6 pre-existing failures), tsc --noEmit clean
This commit is contained in:
Alex Blank
2026-05-29 14:04:52 +02:00
parent ceaed9af66
commit 03d22c4d06
4 changed files with 374 additions and 3 deletions
+63
View File
@@ -104,6 +104,69 @@ def apply_mount_permissions(
return results
def apply_ssh_permissions(
container_id: str,
ssh_target: str,
container_user: str,
timeout: int = 10,
) -> dict[str, Any]:
"""Fix SSH directory ownership and permissions in a running container.
Runs chown and chmod on the ~/.ssh directory so the container user
can use the keys (SSH requires the private key to be owned by the
user with mode 600).
Args:
container_id: Docker container ID or name.
ssh_target: Absolute path to the .ssh directory inside the container.
container_user: The container user that should own the keys.
timeout: Max seconds per docker exec command.
Returns:
Result dict with keys: success, error.
"""
result: dict[str, Any] = {"success": True, "error": None}
try:
# Ensure directory is owned by the container user
_run_in_container(
container_id,
["chown", "-R", f"{container_user}:{container_user}", ssh_target],
timeout,
)
# Set directory permissions
_run_in_container(
container_id,
["chmod", "700", ssh_target],
timeout,
)
# Set private key permissions
_run_in_container(
container_id,
[
"sh",
"-c",
f"find {ssh_target} -name 'id_*' -type f -exec chmod 600 {{}} +",
],
timeout,
)
logger.debug(
"Applied SSH permissions for user %s on %s in container %s",
container_user,
ssh_target,
container_id,
)
except PermissionFixError as exc:
result["success"] = False
result["error"] = str(exc)
logger.warning(
"SSH permission fix failed for container %s (target=%s): %s",
container_id,
ssh_target,
exc,
)
return result
class PermissionFixError(Exception):
"""Raised when a permission fix command fails."""