mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-01 10:47:30 +00:00
Compare commits
No commits in common. "1d7ca0cd2270bf425ee60b4d4a837bd309b20a9c" and "4fd0d864eea4b65c9c92e05886357b298108739e" have entirely different histories.
1d7ca0cd22
...
4fd0d864ee
|
|
@ -41,17 +41,6 @@ def run_cmd(cmd: list, timeout: int = 60) -> tuple:
|
||||||
return "", str(e), 1
|
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:
|
def is_libvirt_running() -> bool:
|
||||||
"""Check if libvirtd is running."""
|
"""Check if libvirtd is running."""
|
||||||
_, _, code = run_cmd(["systemctl", "is-active", "--quiet", "libvirtd"])
|
_, _, code = run_cmd(["systemctl", "is-active", "--quiet", "libvirtd"])
|
||||||
|
|
@ -92,9 +81,7 @@ def get_virsh_vms() -> list:
|
||||||
def get_lxc_containers() -> list:
|
def get_lxc_containers() -> list:
|
||||||
"""List all LXC containers."""
|
"""List all LXC containers."""
|
||||||
containers = []
|
containers = []
|
||||||
# NB: the memory column key is `RAM` — `MEMORY` is rejected by lxc-ls
|
stdout, _, code = run_cmd(["lxc-ls", "-f", "-F", "NAME,STATE,IPV4,MEMORY"])
|
||||||
# ("Invalid key") and yields zero output (#601).
|
|
||||||
stdout, _, code = run_priv(["lxc-ls", "-f", "-F", "NAME,STATE,IPV4,RAM"])
|
|
||||||
|
|
||||||
if code != 0:
|
if code != 0:
|
||||||
return containers
|
return containers
|
||||||
|
|
@ -135,7 +122,7 @@ def get_lxc_info(name: str) -> dict:
|
||||||
"""Get detailed LXC container info."""
|
"""Get detailed LXC container info."""
|
||||||
info = {"name": name, "type": "lxc"}
|
info = {"name": name, "type": "lxc"}
|
||||||
|
|
||||||
stdout, _, code = run_priv(["lxc-info", "-n", name])
|
stdout, _, code = run_cmd(["lxc-info", "-n", name])
|
||||||
if code == 0:
|
if code == 0:
|
||||||
for line in stdout.strip().split('\n'):
|
for line in stdout.strip().split('\n'):
|
||||||
if ':' in line:
|
if ':' in line:
|
||||||
|
|
@ -332,7 +319,7 @@ def start_vm(name: str):
|
||||||
if is_lxc_available():
|
if is_lxc_available():
|
||||||
for c in get_lxc_containers():
|
for c in get_lxc_containers():
|
||||||
if c["name"] == name:
|
if c["name"] == name:
|
||||||
stdout, stderr, code = run_priv(["lxc-start", "-n", name])
|
stdout, stderr, code = run_cmd(["lxc-start", "-n", name])
|
||||||
if code != 0:
|
if code != 0:
|
||||||
raise HTTPException(status_code=500, detail=f"Failed to start: {stderr}")
|
raise HTTPException(status_code=500, detail=f"Failed to start: {stderr}")
|
||||||
return {"status": "started", "name": name}
|
return {"status": "started", "name": name}
|
||||||
|
|
@ -360,7 +347,7 @@ def stop_vm(name: str, force: bool = False):
|
||||||
cmd = ["lxc-stop", "-n", name]
|
cmd = ["lxc-stop", "-n", name]
|
||||||
if force:
|
if force:
|
||||||
cmd.append("-k")
|
cmd.append("-k")
|
||||||
stdout, stderr, code = run_priv(cmd)
|
stdout, stderr, code = run_cmd(cmd)
|
||||||
if code != 0:
|
if code != 0:
|
||||||
raise HTTPException(status_code=500, detail=f"Failed to stop: {stderr}")
|
raise HTTPException(status_code=500, detail=f"Failed to stop: {stderr}")
|
||||||
return {"status": "stopped", "name": name}
|
return {"status": "stopped", "name": name}
|
||||||
|
|
@ -384,8 +371,8 @@ def restart_vm(name: str):
|
||||||
if is_lxc_available():
|
if is_lxc_available():
|
||||||
for c in get_lxc_containers():
|
for c in get_lxc_containers():
|
||||||
if c["name"] == name:
|
if c["name"] == name:
|
||||||
run_priv(["lxc-stop", "-n", name])
|
run_cmd(["lxc-stop", "-n", name])
|
||||||
stdout, stderr, code = run_priv(["lxc-start", "-n", name])
|
stdout, stderr, code = run_cmd(["lxc-start", "-n", name])
|
||||||
if code != 0:
|
if code != 0:
|
||||||
raise HTTPException(status_code=500, detail=f"Failed to restart: {stderr}")
|
raise HTTPException(status_code=500, detail=f"Failed to restart: {stderr}")
|
||||||
return {"status": "restarted", "name": name}
|
return {"status": "restarted", "name": name}
|
||||||
|
|
@ -417,11 +404,9 @@ def delete_vm(name: str):
|
||||||
for c in get_lxc_containers():
|
for c in get_lxc_containers():
|
||||||
if c["name"] == name:
|
if c["name"] == name:
|
||||||
if c.get('state') == 'running':
|
if c.get('state') == 'running':
|
||||||
run_priv(["lxc-stop", "-n", name, "-k"])
|
run_cmd(["lxc-stop", "-n", name, "-k"])
|
||||||
|
|
||||||
# lxc-destroy is intentionally NOT in the sudo grant — deleting
|
stdout, stderr, code = run_cmd(["lxc-destroy", "-n", name])
|
||||||
# containers from an unauthenticated endpoint stays root-only.
|
|
||||||
stdout, stderr, code = run_priv(["lxc-destroy", "-n", name])
|
|
||||||
if code != 0:
|
if code != 0:
|
||||||
raise HTTPException(status_code=500, detail=f"Failed to delete: {stderr}")
|
raise HTTPException(status_code=500, detail=f"Failed to delete: {stderr}")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,3 @@
|
||||||
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
|
secubox-vm (1.0.0-1) stable; urgency=low
|
||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,6 @@ 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
|
||||||
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/iso
|
||||||
install -d -o root -g root -m 755 /var/lib/secubox/vm/disks
|
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 daemon-reload
|
||||||
systemctl enable secubox-vm.service
|
systemctl enable secubox-vm.service
|
||||||
systemctl start secubox-vm.service || true
|
systemctl start secubox-vm.service || true
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,3 @@ override_dh_auto_install:
|
||||||
install -m 644 menu.d/903-vm.json $(CURDIR)/debian/secubox-vm/usr/share/secubox/menu.d/
|
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 -d $(CURDIR)/debian/secubox-vm/usr/lib/systemd/system
|
||||||
install -m 644 debian/secubox-vm.service $(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
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
# 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