mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-06-30 01:16:35 +00:00
Compare commits
3 Commits
4fd0d864ee
...
1d7ca0cd22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d7ca0cd22 | ||
| a610ffd276 | |||
| 5800ad713d |
|
|
@ -41,6 +41,17 @@ def run_cmd(cmd: list, timeout: int = 60) -> tuple:
|
|||
return "", str(e), 1
|
||||
|
||||
|
||||
def run_priv(cmd: list, timeout: int = 60) -> tuple:
|
||||
"""Run a host privileged command via the read/lifecycle sudo grant.
|
||||
|
||||
The aggregator mounts this module in-process as the unprivileged `secubox`
|
||||
user, which cannot see root's /var/lib/lxc containers — bare `lxc-ls`
|
||||
returns nothing, so the dashboard reported 0 containers (#601). The grant
|
||||
in /etc/sudoers.d/secubox-vm covers read + lifecycle only.
|
||||
"""
|
||||
return run_cmd(["sudo", "-n"] + cmd, timeout=timeout)
|
||||
|
||||
|
||||
def is_libvirt_running() -> bool:
|
||||
"""Check if libvirtd is running."""
|
||||
_, _, code = run_cmd(["systemctl", "is-active", "--quiet", "libvirtd"])
|
||||
|
|
@ -81,7 +92,9 @@ def get_virsh_vms() -> list:
|
|||
def get_lxc_containers() -> list:
|
||||
"""List all LXC containers."""
|
||||
containers = []
|
||||
stdout, _, code = run_cmd(["lxc-ls", "-f", "-F", "NAME,STATE,IPV4,MEMORY"])
|
||||
# NB: the memory column key is `RAM` — `MEMORY` is rejected by lxc-ls
|
||||
# ("Invalid key") and yields zero output (#601).
|
||||
stdout, _, code = run_priv(["lxc-ls", "-f", "-F", "NAME,STATE,IPV4,RAM"])
|
||||
|
||||
if code != 0:
|
||||
return containers
|
||||
|
|
@ -122,7 +135,7 @@ def get_lxc_info(name: str) -> dict:
|
|||
"""Get detailed LXC container info."""
|
||||
info = {"name": name, "type": "lxc"}
|
||||
|
||||
stdout, _, code = run_cmd(["lxc-info", "-n", name])
|
||||
stdout, _, code = run_priv(["lxc-info", "-n", name])
|
||||
if code == 0:
|
||||
for line in stdout.strip().split('\n'):
|
||||
if ':' in line:
|
||||
|
|
@ -319,7 +332,7 @@ def start_vm(name: str):
|
|||
if is_lxc_available():
|
||||
for c in get_lxc_containers():
|
||||
if c["name"] == name:
|
||||
stdout, stderr, code = run_cmd(["lxc-start", "-n", name])
|
||||
stdout, stderr, code = run_priv(["lxc-start", "-n", name])
|
||||
if code != 0:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to start: {stderr}")
|
||||
return {"status": "started", "name": name}
|
||||
|
|
@ -347,7 +360,7 @@ def stop_vm(name: str, force: bool = False):
|
|||
cmd = ["lxc-stop", "-n", name]
|
||||
if force:
|
||||
cmd.append("-k")
|
||||
stdout, stderr, code = run_cmd(cmd)
|
||||
stdout, stderr, code = run_priv(cmd)
|
||||
if code != 0:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to stop: {stderr}")
|
||||
return {"status": "stopped", "name": name}
|
||||
|
|
@ -371,8 +384,8 @@ def restart_vm(name: str):
|
|||
if is_lxc_available():
|
||||
for c in get_lxc_containers():
|
||||
if c["name"] == name:
|
||||
run_cmd(["lxc-stop", "-n", name])
|
||||
stdout, stderr, code = run_cmd(["lxc-start", "-n", name])
|
||||
run_priv(["lxc-stop", "-n", name])
|
||||
stdout, stderr, code = run_priv(["lxc-start", "-n", name])
|
||||
if code != 0:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to restart: {stderr}")
|
||||
return {"status": "restarted", "name": name}
|
||||
|
|
@ -404,9 +417,11 @@ def delete_vm(name: str):
|
|||
for c in get_lxc_containers():
|
||||
if c["name"] == name:
|
||||
if c.get('state') == 'running':
|
||||
run_cmd(["lxc-stop", "-n", name, "-k"])
|
||||
run_priv(["lxc-stop", "-n", name, "-k"])
|
||||
|
||||
stdout, stderr, code = run_cmd(["lxc-destroy", "-n", name])
|
||||
# lxc-destroy is intentionally NOT in the sudo grant — deleting
|
||||
# containers from an unauthenticated endpoint stays root-only.
|
||||
stdout, stderr, code = run_priv(["lxc-destroy", "-n", name])
|
||||
if code != 0:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to delete: {stderr}")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,16 @@
|
|||
secubox-vm (1.0.1-1) stable; urgency=medium
|
||||
|
||||
* fix(lxc): /vm/ reported 0 containers though the host runs 20 LXC
|
||||
containers (#601). The aggregator mounts this module in-process as the
|
||||
unprivileged `secubox` user, so bare `lxc-ls` could not see root's
|
||||
/var/lib/lxc → empty list. LXC read + lifecycle now go through `sudo -n`
|
||||
via a new read-only-ish grant (/etc/sudoers.d/secubox-vm: lxc-ls/info/
|
||||
start/stop, visudo-validated). lxc-create/lxc-destroy stay root-only.
|
||||
postinst reloads secubox-aggregator so the in-process module refreshes.
|
||||
(KVM/libvirt readings were already correct: no /dev/kvm, libvirtd off.)
|
||||
|
||||
-- Gerald KERMA <devel@cybermind.fr> Mon, 15 Jun 2026 13:00:00 +0200
|
||||
|
||||
secubox-vm (1.0.0-1) stable; urgency=low
|
||||
|
||||
* Initial release
|
||||
|
|
|
|||
|
|
@ -5,6 +5,19 @@ case "$1" in
|
|||
install -d -o root -g root -m 755 /var/lib/secubox/vm
|
||||
install -d -o root -g root -m 755 /var/lib/secubox/vm/iso
|
||||
install -d -o root -g root -m 755 /var/lib/secubox/vm/disks
|
||||
# #601 — validate the read+lifecycle cscli/lxc sudo grant; drop it if
|
||||
# malformed so a bad drop-in can never break sudo for the whole system.
|
||||
SUDOERS=/etc/sudoers.d/secubox-vm
|
||||
if [ -f "$SUDOERS" ]; then
|
||||
chmod 0440 "$SUDOERS" || true
|
||||
if command -v visudo >/dev/null 2>&1 && ! visudo -cf "$SUDOERS" >/dev/null 2>&1; then
|
||||
echo "secubox-vm: invalid sudoers drop-in, removing" >&2
|
||||
rm -f "$SUDOERS"
|
||||
fi
|
||||
fi
|
||||
# The aggregator mounts this module in-process; reload it so the new code
|
||||
# + LXC listing take effect (the per-module service is not the live path).
|
||||
systemctl try-reload-or-restart secubox-aggregator.service 2>/dev/null || true
|
||||
systemctl daemon-reload
|
||||
systemctl enable secubox-vm.service
|
||||
systemctl start secubox-vm.service || true
|
||||
|
|
|
|||
|
|
@ -14,3 +14,7 @@ override_dh_auto_install:
|
|||
install -m 644 menu.d/903-vm.json $(CURDIR)/debian/secubox-vm/usr/share/secubox/menu.d/
|
||||
install -d $(CURDIR)/debian/secubox-vm/usr/lib/systemd/system
|
||||
install -m 644 debian/secubox-vm.service $(CURDIR)/debian/secubox-vm/usr/lib/systemd/system/
|
||||
# #601 — read+lifecycle sudo grant so LXC enumeration works under the
|
||||
# unprivileged `secubox` user the aggregator mounts this module as.
|
||||
install -d $(CURDIR)/debian/secubox-vm/etc/sudoers.d
|
||||
install -m 0440 debian/sudoers.d/secubox-vm $(CURDIR)/debian/secubox-vm/etc/sudoers.d/secubox-vm
|
||||
|
|
|
|||
9
packages/secubox-vm/debian/sudoers.d/secubox-vm
Normal file
9
packages/secubox-vm/debian/sudoers.d/secubox-vm
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# SecuBox VM module — host virtualization management as the `secubox` user.
|
||||
# The aggregator mounts this module in-process as `secubox`, which cannot see
|
||||
# root's /var/lib/lxc containers without sudo. READ + container LIFECYCLE only.
|
||||
# lxc-create / lxc-destroy are deliberately NOT granted — creating/deleting
|
||||
# containers stays root-only (these endpoints carry no JWT). CSPN least-priv.
|
||||
secubox ALL=(root) NOPASSWD: /usr/bin/lxc-ls *
|
||||
secubox ALL=(root) NOPASSWD: /usr/bin/lxc-info *
|
||||
secubox ALL=(root) NOPASSWD: /usr/bin/lxc-start *
|
||||
secubox ALL=(root) NOPASSWD: /usr/bin/lxc-stop *
|
||||
Loading…
Reference in New Issue
Block a user