Skip to main content

sysknife_daemon/actions/
containers.rs

1use super::{ActionMechanism, ActionSpec};
2use sysknife_types::RiskLevel;
3
4pub fn specs() -> Vec<ActionSpec> {
5    vec![
6        list_containers("testuser"),
7        create_container(
8            "testuser",
9            "sysknife-dev",
10            "registry.fedoraproject.org/fedora-toolbox:41",
11        ),
12        start_container("testuser", "sysknife-dev"),
13        stop_container("testuser", "sysknife-dev"),
14        remove_container("testuser", "sysknife-dev"),
15        get_container_info("testuser", "sysknife-dev"),
16    ]
17}
18
19/// Run fixed Podman argv after dropping to the target user.
20///
21/// Rootless Podman operates against the user's container storage, not a shared
22/// system store. The daemon runs as the `sysknife` system user whose container
23/// namespace is empty; we must switch to `username` to reach their containers.
24/// The helper sets HOME and XDG_RUNTIME_DIR for the resolved UID, resets
25/// supplementary groups, and drops GID/UID before invoking the fixed tool.
26/// Rootless Podman still requires the account's configured sub-UID/GID ranges
27/// and runtime directory. No login shell or user startup file runs as root.
28fn podman_as(username: &str, parameters: &[&str]) -> ActionMechanism {
29    let mut args = vec![
30        "/usr/lib/sysknife/action-steps".to_string(),
31        "podman".to_string(),
32        username.to_string(),
33    ];
34    args.extend(parameters.iter().map(|value| value.to_string()));
35    ActionMechanism::Command {
36        program: "sudo",
37        args,
38    }
39}
40
41pub fn list_containers(username: &str) -> ActionSpec {
42    ActionSpec {
43        action_name: "ListContainers",
44        mechanism: podman_as(username, &["ps", "--all", "--format", "json"]),
45        risk_level: RiskLevel::Low,
46        reboot_required: false,
47        rollback_available: false,
48    }
49}
50
51pub fn create_container(username: &str, name: &str, image: &str) -> ActionSpec {
52    ActionSpec {
53        action_name: "CreateContainer",
54        mechanism: podman_as(username, &["create", "--name", name, image]),
55        risk_level: RiskLevel::Medium,
56        reboot_required: false,
57        rollback_available: false,
58    }
59}
60
61pub fn start_container(username: &str, name: &str) -> ActionSpec {
62    ActionSpec {
63        action_name: "StartContainer",
64        mechanism: podman_as(username, &["start", name]),
65        risk_level: RiskLevel::Medium,
66        reboot_required: false,
67        rollback_available: false,
68    }
69}
70
71pub fn stop_container(username: &str, name: &str) -> ActionSpec {
72    ActionSpec {
73        action_name: "StopContainer",
74        mechanism: podman_as(username, &["stop", name]),
75        risk_level: RiskLevel::Medium,
76        reboot_required: false,
77        rollback_available: false,
78    }
79}
80
81pub fn remove_container(username: &str, name: &str) -> ActionSpec {
82    ActionSpec {
83        action_name: "RemoveContainer",
84        mechanism: podman_as(username, &["rm", name]),
85        risk_level: RiskLevel::Medium,
86        reboot_required: false,
87        rollback_available: false,
88    }
89}
90
91pub fn get_container_info(username: &str, name: &str) -> ActionSpec {
92    ActionSpec {
93        action_name: "GetContainerInfo",
94        mechanism: podman_as(username, &["inspect", name]),
95        risk_level: RiskLevel::Low,
96        reboot_required: false,
97        rollback_available: false,
98    }
99}