malwaredb 0.3.2

Service for storing malicious, benign, or unknown files and related metadata and relationships.
// SPDX-License-Identifier: Apache-2.0

use super::Installer;

use std::path::PathBuf;
use std::process::ExitCode;

use anyhow::{ensure, Result};
use clap::Parser;

const LAUNCH_PATH: &str = "/etc/systemd/system/malwaredb.service";

/// Install Malware DB as a systemd service
#[derive(Parser, Debug, Clone, PartialEq)]
pub struct Install {
    /// Use a specific configuration file path
    #[arg(value_hint = clap::ValueHint::FilePath)]
    pub config: Option<PathBuf>,

    /// The user account under which Malware DB will run
    #[arg(short, long, default_value = "mdbd")]
    pub user: String,

    /// The group under which Malware DB will run
    #[arg(short, long, default_value = "mdbd")]
    pub group: String,
}

impl Install {
    fn gen_config(&self) -> Result<String> {
        let exec = std::env::current_exe()?;

        // Not ideal, but the path is needed without quotes.
        let exec = exec.to_str().unwrap();

        let exec = if let Some(config) = &self.config {
            // Force an absolute path since the working directory when the service is launched could vary
            ensure!(
                config.starts_with("/"),
                "Must use an absolute path for the config file"
            );
            format!("{exec} run load {}", config.display())
        } else {
            format!("{exec} run")
        };

        Ok(format!(
            "[Unit]
Description=MalwareDB
Wants=network-online.target
After=network-online.target nss-lookup.target

[Service]
User={}
Group={}
Type=exec
Restart=always
RuntimeMaxSec=1d
StandardOutput=journal
ExecStart={exec}

[Install]
WantedBy=multi-user.target
",
            self.user, self.group
        ))
    }
}

impl Installer for Install {
    fn do_install(&self) -> Result<ExitCode> {
        let config = self.gen_config()?;
        std::fs::write(LAUNCH_PATH, config)?;
        Ok(ExitCode::SUCCESS)
    }
}