diff --git a/Cargo.lock b/Cargo.lock index ab9cfe5df..15ad75ce7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -428,6 +437,29 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -533,7 +565,7 @@ version = "0.5.0" dependencies = [ "ariadne", "clap", - "fapolicy-analyzer", + "env_logger", "fapolicy-app", "fapolicy-daemon", "fapolicy-rules", @@ -543,7 +575,7 @@ dependencies = [ "lmdb", "log", "nom", - "rayon", + "strip-ansi-escapes", "thiserror", ] @@ -678,6 +710,12 @@ dependencies = [ "uuid", ] +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "iana-time-zone" version = "0.1.47" @@ -1244,6 +1282,8 @@ version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] @@ -1347,6 +1387,15 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.10.0" @@ -1527,6 +1576,26 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "walkdir" version = "2.5.0" diff --git a/Makefile b/Makefile index d01a5df30..f26060432 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,8 @@ RED=\033[0;31m NC=\033[0m # No Color VERSION ?= $(shell sed -n 's/^Version: *//p' fapolicy-analyzer.spec) -FID ?= rawhide +fc ?= rawhide +el ?= 9 # List the common developer targets list: @@ -142,17 +143,17 @@ build-info: # Generate Fedora rawhide rpms fc-rpm: - @echo -e "${GRN}--- Fedora $(FID) RPM generation v${VERSION}...${NC}" + @echo -e "${GRN}--- Fedora $(fc) RPM generation v${VERSION}...${NC}" make -f .copr/Makefile vendor OS_ID=fedora VERSION=${VERSION} - podman build -t fapolicy-analyzer:build --target fedorabuild --build-arg version=${VERSION} -f Containerfile . - podman run --privileged --rm -it -v /tmp:/v fapolicy-analyzer:build fedora-$(FID)-x86_64 /v + podman build -t fapolicy-analyzer:build-fc$(fc) --target fedorabuild --build-arg version=${VERSION} -f Containerfile . + podman run --privileged --rm -it -v /tmp:/v fapolicy-analyzer:build-fc$(fc) fedora-$(fc)-x86_64 /v # Generate RHEL 9 rpms -el9-rpm: - @echo -e "${GRN}--- el9 RPM generation v${VERSION}...${NC}" - make -f .copr/Makefile vendor vendor-rs OS_ID=rhel VERSION=${VERSION} DIST=.el9 spec=scripts/srpm/fapolicy-analyzer.el9.spec - podman build -t fapolicy-analyzer:build --target elbuild --build-arg version=${VERSION} --build-arg spec=scripts/srpm/fapolicy-analyzer.el9.spec -f Containerfile . - podman run --privileged --rm -it -v /tmp:/v fapolicy-analyzer:build rocky+epel-9-x86_64 /v +el-rpm: + @echo -e "${GRN}--- el$(el) RPM generation v${VERSION}...${NC}" + make -f .copr/Makefile vendor vendor-rs OS_ID=rhel VERSION=${VERSION} DIST=.el$(el) spec=scripts/srpm/fapolicy-analyzer.el$(el).spec + podman build -t fapolicy-analyzer:build-el$(el) --target elbuild --build-arg version=${VERSION} --build-arg spec=scripts/srpm/fapolicy-analyzer.el$(el).spec -f Containerfile . + podman run --privileged --rm -it -v /tmp:/v fapolicy-analyzer:build-el$(el) rocky+epel-$(el)-x86_64 /v # Update embedded help documentation help-docs: diff --git a/crates/daemon/src/error.rs b/crates/daemon/src/error.rs index 58107e877..d5163d5ca 100644 --- a/crates/daemon/src/error.rs +++ b/crates/daemon/src/error.rs @@ -38,4 +38,7 @@ pub enum Error { #[error("failed to parse stat entry: {0}")] ParseStatsError(String), + + #[error("the profiler is already active")] + ProfilerAlreadyActive, } diff --git a/crates/daemon/src/profiler.rs b/crates/daemon/src/profiler.rs index 4f01f5533..b6c392866 100644 --- a/crates/daemon/src/profiler.rs +++ b/crates/daemon/src/profiler.rs @@ -15,8 +15,9 @@ use fapolicy_rules::db::DB; use fapolicy_rules::write; use crate::error::Error; +use crate::error::Error::ProfilerAlreadyActive; use crate::fapolicyd::{Daemon, COMPILED_RULES_PATH}; -use crate::svc::State; +use crate::svc::{wait_for_service, State}; use crate::{fapolicyd, svc}; const PROFILER_NAME: &str = "fapolicyp"; @@ -48,49 +49,59 @@ impl Profiler { self.fapolicyp.active() } - pub fn activate(&mut self) -> Result { + pub fn activate(&mut self) -> Result { self.activate_with_rules(None) } - pub fn activate_with_rules(&mut self, db: Option<&DB>) -> Result { + pub fn activate_with_rules(&mut self, db: Option<&DB>) -> Result { let fapolicyd = svc::Handle::default(); - if !self.is_active() { - // 1. preserve fapolicyd daemon state - self.prev_state = Some(fapolicyd.state()?); - // 2. stop fapolicyd daemon if running - if let Some(State::Active) = self.prev_state { - // todo;; probably need to ensure its not in - // a state like restart, init or some such - fapolicyd.stop()? - } - // 3. swap the rules file if necessary - if let Some(db) = db { - // compiled.rules is always at the default location - let compiled = PathBuf::from(COMPILED_RULES_PATH); - // create a temp file as the backup location - let backup = NamedTempFile::new()?; - // move original compiled to backup location - fs::rename(&compiled, &backup).or_else(|x| { - log::debug!("rename fallback copy"); - fs::copy(&compiled, &backup) - .and_then(|_| fs::remove_file(&compiled)) - .or(Err(x)) - })?; - // write compiled rules for the profiling run - write::compiled_rules(db, &compiled)?; - log::debug!("rules backed up to {:?}", backup.path()); - self.prev_rules = Some(backup); - } - // 5. start the profiler daemon - self.fapolicyp.start(self.events_log.as_ref())?; - // 6. wait for the profiler daemon to become active - if let Some(log) = self.events_log.as_ref() { - if fapolicyd::wait_until_ready(log).is_err() { - log::warn!("wait_until_ready failed"); - }; - } + if self.is_active() { + return Err(ProfilerAlreadyActive); } - fapolicyd.state() + + // 1. preserve fapolicyd daemon state + self.prev_state = Some(fapolicyd.state()?); + // 2. stop fapolicyd daemon if running + if let Some(State::Active) = self.prev_state { + // todo;; probably need to ensure its not in + // a state like restart, init or some such + fapolicyd.stop()?; + wait_for_service(&fapolicyd, State::Inactive, 10)?; + } + // 3. swap the rules file if necessary + if let Some(db) = db { + // compiled.rules is always at the default location + let compiled = PathBuf::from(COMPILED_RULES_PATH); + // create a temp file as the backup location + let backup = NamedTempFile::new()?; + // move original compiled to backup location + fs::rename(&compiled, &backup).or_else(|x| { + log::debug!("rename fallback copy"); + fs::copy(&compiled, &backup) + .and_then(|_| fs::remove_file(&compiled)) + .or(Err(x)) + })?; + // write compiled rules for the profiling run + write::compiled_rules(db, &compiled)?; + log::debug!("rules backed up to {:?}", backup.path()); + self.prev_rules = Some(backup); + } + // 5. resolve the output file + let outfile = match &self.events_log { + Some(p) => p.clone(), + None => NamedTempFile::new()?.into_temp_path().to_path_buf(), + }; + log::debug!("events-file: {}", outfile.display()); + + // 6. start the profiler daemon + self.fapolicyp.start(Some(&outfile))?; + + // 7. wait for the profiler daemon to become active + if fapolicyd::wait_until_ready(&outfile).is_err() { + log::warn!("wait_until_ready failed"); + }; + + Ok(outfile) } pub fn deactivate(&mut self) -> Result { @@ -107,7 +118,6 @@ impl Profiler { } // 4. start fapolicyd daemon if it was previously active if let Some(State::Active) = self.prev_state { - log::debug!("restarting daemon"); fapolicyd.start()?; } } diff --git a/crates/tools/Cargo.toml b/crates/tools/Cargo.toml index 098c08cd2..84b387759 100644 --- a/crates/tools/Cargo.toml +++ b/crates/tools/Cargo.toml @@ -21,13 +21,13 @@ path = "src/rule_check.rs" clap = { version = "3.2.20", features = ["derive"] } lmdb = "0.8" nom = "7.1" -rayon = "1.5" thiserror = "1.0" log = "0.4" ariadne = { version = "0.4", optional = true } human-panic = "2.0" +env_logger = "0.11" +strip-ansi-escapes = "0.2" -fapolicy-analyzer = { path = "../analyzer" } fapolicy-app = { path = "../app" } fapolicy-daemon = { path = "../daemon" } fapolicy-rules = { path = "../rules" } diff --git a/crates/tools/src/fapolicy_profiler.rs b/crates/tools/src/fapolicy_profiler.rs index 1459ada9c..e0c3a91df 100644 --- a/crates/tools/src/fapolicy_profiler.rs +++ b/crates/tools/src/fapolicy_profiler.rs @@ -14,23 +14,35 @@ // along with this program. If not, see . use clap::Parser; +use fapolicy_daemon::fapolicyd::START_POLLING_EVENTS_MESSAGE; use fapolicy_daemon::profiler::Profiler; use fapolicy_rules::read::load_rules_db; use std::error::Error; +use std::fs::File; +use std::io::{BufRead, BufReader, Write}; use std::os::unix::prelude::CommandExt; use std::path::PathBuf; use std::process::Command; +use strip_ansi_escapes::strip_str; #[derive(Parser)] #[clap(name = "File Access Policy Profiler", version = "v0.0.0")] struct Opts { + /// do not write events to stdout + #[clap(long)] + quiet: bool, + /// path to *.rules or rules.d - #[clap(short, long)] + #[clap(long)] rules: Option, - /// out path for daemon stdout log + /// path to write daemon log + #[clap(long)] + dlog: Option, + + /// path to write command log #[clap(long)] - stdout: Option, + clog: Option, /// the profiling uid #[clap(long)] @@ -48,18 +60,17 @@ struct Opts { fn main() -> Result<(), Box> { fapolicy_tools::setup_human_panic(); + env_logger::init(); let opts: Opts = Opts::parse(); log::info!("profiling: {:?}", opts.target); let target = opts.target.first().expect("target not specified"); let args: Vec<&String> = opts.target.iter().skip(1).collect(); - let mut profiler = Profiler::new(); let db = opts .rules .map(|p| load_rules_db(&p).expect("failed to load rules")); - - if let Some(path) = opts.stdout.map(PathBuf::from) { + if let Some(path) = opts.dlog.as_ref().map(PathBuf::from) { if path.exists() { log::warn!("deleting existing log file from {}", path.display()); std::fs::remove_file(&path)?; @@ -67,7 +78,7 @@ fn main() -> Result<(), Box> { profiler.events_log = Some(path); } - profiler.activate_with_rules(db.as_ref())?; + let outfile = profiler.activate_with_rules(db.as_ref())?; let mut cmd = Command::new(target); if let Some(uid) = opts.uid { cmd.uid(uid); @@ -75,9 +86,39 @@ fn main() -> Result<(), Box> { if let Some(gid) = opts.gid { cmd.gid(gid); } + let out = cmd.args(args).output()?; - println!("{}", String::from_utf8(out.stdout)?); profiler.deactivate()?; + // write command output to file if specified + if let Some(path) = opts.clog.map(PathBuf::from) { + let mut f = File::create(&path)?; + f.write_all(&out.stdout)?; + log::info!("wrote cmd output to {}", path.display()); + } + + // if the events file was not specified we will dump to the screen + if !opts.quiet { + let f = File::open(outfile)?; + let bufrdr = BufReader::new(&f); + let lines = bufrdr.lines().map(|x| x.unwrap()); + for line in lines + .skip_while(|l| !l.contains(START_POLLING_EVENTS_MESSAGE)) + .skip(1) + { + if strip_str(&line).contains("[ INFO ]") { + if let Some((_, rhs)) = line.split_once("]: ") { + println!("{rhs}"); + } else { + log::warn!("failed to split output line \"{}\", ignoring", line); + } + } + } + } + + if let Some(path) = opts.dlog.map(PathBuf::from) { + log::info!("wrote daemon output to {}", path.display()); + } + Ok(()) } diff --git a/crates/tools/src/rule_check.rs b/crates/tools/src/rule_check.rs index d8bee8327..0d0baf02b 100644 --- a/crates/tools/src/rule_check.rs +++ b/crates/tools/src/rule_check.rs @@ -19,6 +19,7 @@ use std::path::PathBuf; use clap::Parser; +use fapolicy_daemon::fapolicyd; use fapolicy_rules::parser::errat::{ErrorAt, StrErrorAt}; use fapolicy_rules::parser::parse::StrTrace; use fapolicy_rules::parser::trace::Trace; @@ -31,11 +32,13 @@ use std::collections::BTreeMap; use std::fs::File; use std::io; use std::io::{BufRead, BufReader}; +use std::process::ExitCode; #[derive(Parser)] #[clap(name = "Rule Checker", version = "v0.0.0")] struct Opts { /// path to *.rules or rules.d + #[clap(default_value=fapolicyd::RULES_FILE_PATH)] rules_path: String, } @@ -48,8 +51,9 @@ enum Line<'a> { RuleDef(RuleParse<'a>), } -fn main() -> Result<(), Box> { +fn main() -> Result> { fapolicy_tools::setup_human_panic(); + env_logger::init(); let all_opts: Opts = Opts::parse(); @@ -64,15 +68,17 @@ fn main() -> Result<(), Box> { x }); + let mut errors = 0; for (file, _) in contents { - report_for_file(file)?; + errors += report_for_file(file)?; } - Ok(()) + + Ok(ExitCode::from(if errors > 0 { 1 } else { 0 })) } -fn report_for_file(path: PathBuf) -> Result<(), Box> { +fn report_for_file(path: PathBuf) -> Result> { let filename = path.display().to_string(); - let buff = BufReader::new(File::open(path)?); + let buff = BufReader::new(File::open(&path)?); let lines: Result, io::Error> = buff.lines().collect(); let contents: Vec = lines?.into_iter().collect(); @@ -114,6 +120,7 @@ fn report_for_file(path: PathBuf) -> Result<(), Box> { }) .collect(); + let mut errors = 0; for (lineno, result) in results { if result.is_err() { #[cfg(feature = "pretty")] @@ -135,16 +142,20 @@ fn report_for_file(path: PathBuf) -> Result<(), Box> { match result { Ok(_) => {} Err(nom::Err::Error(e)) => { - println!("[E] {filename}:{} {}", lineno + 1, e.0); + println!("[EE] {filename}:{} {}", lineno + 1, e.0); } res => { log::warn!("unhandled err {:?}", res); } } + errors += 1; } } + if errors == 0 { + println!("[OK] {}", path.display()); + } - Ok(()) + Ok(errors) } #[cfg(feature = "pretty")] diff --git a/crates/tools/src/trust_db_util.rs b/crates/tools/src/trust_db_util.rs index 2b2444d1b..be4b62a04 100644 --- a/crates/tools/src/trust_db_util.rs +++ b/crates/tools/src/trust_db_util.rs @@ -25,12 +25,13 @@ use thiserror::Error; use fapolicy_app::cfg; use fapolicy_daemon::fapolicyd::TRUST_LMDB_NAME; +use fapolicy_trust::db::DB; use fapolicy_trust::read::rpm_trust; use fapolicy_trust::stat::Status::{Discrepancy, Missing, Trusted}; use fapolicy_trust::{check, load, parse, read, Trust}; use fapolicy_util::sha::sha256_digest; -use crate::Error::DirTrustError; +use crate::Error::{DirTrustError, TrustError}; use crate::Subcommand::{Add, Check, Clear, Count, Del, Dump, Init, Load, Search}; /// An Error that can occur in this app @@ -175,6 +176,7 @@ struct CountOpts {} fn main() -> Result<(), Error> { fapolicy_tools::setup_human_panic(); + env_logger::init(); let sys_conf = cfg::All::load()?; let all_opts: Opts = Opts::parse(); @@ -236,7 +238,7 @@ fn init(opts: InitOpts, verbose: bool, cfg: &cfg::All, env: &Environment) -> Res #[cfg(feature = "deb")] let sys = if opts.dpkg { - dpkg_trust()? + dpkg_trust(opts.count)? } else { rpm_trust(&PathBuf::from(&cfg.system.system_trust_path))? }; @@ -341,11 +343,8 @@ fn find(opts: SearchDbOpts, _: &cfg::All, env: &Environment) -> Result<(), Error } fn dump(opts: DumpDbOpts, cfg: &cfg::All) -> Result<(), Error> { - let db = load::trust_db( - &PathBuf::from(&cfg.system.trust_lmdb_path), - &PathBuf::from(&cfg.system.trust_dir_path), - Some(&PathBuf::from(&cfg.system.trust_file_path)), - )?; + let db = load_trust_db(cfg)?; + match opts.outfile { None => { for (_, v) in db.iter() { @@ -364,11 +363,7 @@ fn dump(opts: DumpDbOpts, cfg: &cfg::All) -> Result<(), Error> { } fn check(_: CheckDbOpts, cfg: &cfg::All) -> Result<(), Error> { - let db = load::trust_db( - &PathBuf::from(&cfg.system.trust_lmdb_path), - &PathBuf::from(&cfg.system.trust_dir_path), - Some(&PathBuf::from(&cfg.system.trust_file_path)), - )?; + let db = load_trust_db(cfg)?; let t = SystemTime::now(); let db = check::disk_sync(&db)?; @@ -393,6 +388,15 @@ fn check(_: CheckDbOpts, cfg: &cfg::All) -> Result<(), Error> { Ok(()) } +fn load_trust_db(cfg: &cfg::All) -> Result { + load::trust_db( + &PathBuf::from(&cfg.system.trust_lmdb_path), + &PathBuf::from(&cfg.system.trust_dir_path), + Some(&PathBuf::from(&cfg.system.trust_file_path)), + ) + .map_err(TrustError) +} + fn count(_: CountOpts, _: &cfg::All, env: &Environment) -> Result<(), Error> { let db = env.open_db(Some(TRUST_LMDB_NAME))?; let tx = env.begin_ro_txn()?; @@ -424,10 +428,9 @@ const DPKG_QUERY_HEADER_LINES: usize = 6; #[cfg(feature = "deb")] const DPKG_QUERY: &str = "dpkg-query"; #[cfg(feature = "deb")] -fn dpkg_trust() -> Result, Error> { +fn dpkg_trust(count: Option) -> Result, Error> { use crate::Error::{DpkgCommandFail, DpkgNotFound}; use fapolicy_trust::load::keep_entry; - use rayon::prelude::*; use std::process::Command; // check that dpkg-query exists and can be called @@ -448,18 +451,34 @@ fn dpkg_trust() -> Result, Error> { .map(String::from) .collect(); - Ok(packages - .par_iter() - .flat_map(|p| Command::new(DPKG_QUERY).args(vec!["-L", p]).output()) - .flat_map(output_lines) - .flatten() - // apply the rpm filter to limit results - .filter(|p| keep_entry(p)) - .filter_map(|s| match new_trust_record(&s) { - Ok(t) => Some(t), - Err(_) => None, - }) - .collect()) + let mut trust = vec![]; + 'outer: for pkg in packages { + if let Ok(lines) = Command::new(DPKG_QUERY) + .args(vec!["-L", &pkg]) + .output() + .map_err(DpkgCommandFail) + .and_then(output_lines) + { + for line in lines { + if keep_entry(&line) { + if let Ok(t) = new_trust_record(&line) { + trust.push(t); + if let Some(count) = count { + if trust.len() >= count { + break 'outer; + } + } + } else { + log::warn!("failed to create trust entry for [{line}]") + } + } + } + } else { + log::warn!("failed to {DPKG_QUERY} {pkg}") + } + } + + Ok(trust) } #[cfg(feature = "deb")] diff --git a/data/fapolicy-analyzer-cli-profiler.8 b/data/fapolicy-analyzer-cli-profiler.8 new file mode 100644 index 000000000..4789fbb7d --- /dev/null +++ b/data/fapolicy-analyzer-cli-profiler.8 @@ -0,0 +1,17 @@ +.\" Manpage for the fapolicy-analyzer Profiler CLI. +.TH man 8 "30 Dec 2023" "1.0" "fapolicy-analyzer-cli-profiler man page" +.SH NAME +fapolicy-analyzer-cli-profiler \- Program execution and analysis CLI for fapolicyd +.SH SYNOPSIS +Provides command line tool to execute and assist with analysis of applications using fapolicyd. +.P +This tool allows a command to be executed with fapolicyd in permissie mode to capture and analyze logged file access events. + +.SH DESCRIPTION +Provides File Access Policy Analyzer profiler functionality from the command line. + +.SH SEE ALSO +fapolicy-analyzer(8), fapolicyd(8) + +.SH BUGS +No known bugs. diff --git a/data/fapolicy-analyzer-cli-rules.8 b/data/fapolicy-analyzer-cli-rules.8 new file mode 100644 index 000000000..dbd628bc4 --- /dev/null +++ b/data/fapolicy-analyzer-cli-rules.8 @@ -0,0 +1,17 @@ +.\" Manpage for the fapolicy-analyzer Rules CLI. +.TH man 8 "30 Dec 2023" "1.0" "fapolicy-analyzer-cli-rules man page" +.SH NAME +fapolicy-analyzer-cli-rules \- Configuration and analysis CLI for fapolicyd rule files +.SH SYNOPSIS +Provides command line tool to assist with the configuration and management of fapolicyd rules. +.P +This tool allows validation and compilation of fapolicyd rule files. + +.SH DESCRIPTION +Provides File Access Policy Analyzer rules functionality from the command line. + +.SH SEE ALSO +fapolicy-analyzer(8), fapolicyd.rules(5), fapolicyd(8) + +.SH BUGS +No known bugs. diff --git a/data/fapolicy-analyzer-cli-trust.8 b/data/fapolicy-analyzer-cli-trust.8 new file mode 100644 index 000000000..0148218c1 --- /dev/null +++ b/data/fapolicy-analyzer-cli-trust.8 @@ -0,0 +1,17 @@ +.\" Manpage for the fapolicy-analyzer Trust CLI. +.TH man 8 "30 Dec 2023" "1.0" "fapolicy-analyzer-cli-trust man page" +.SH NAME +fapolicy-analyzer-cli-trust \- Configuration and analysis CLI for fapolicyd trust entries +.SH SYNOPSIS +Provides command line tool to assist with the configuration and management of fapolicyd trust. +.P +This tool allows setup and customization of trust entries suitable for a variety of use cases. + +.SH DESCRIPTION +Provides File Access Policy Analyzer trust functionality from the command line. + +.SH SEE ALSO +fapolicy-analyzer(8), fapolicyd.trust(5), fapolicyd(8) + +.SH BUGS +No known bugs. diff --git a/fapolicy-analyzer.spec b/fapolicy-analyzer.spec index 01cbd4a61..77a846d94 100644 --- a/fapolicy-analyzer.spec +++ b/fapolicy-analyzer.spec @@ -145,7 +145,7 @@ export RUSTFLAGS="%{build_rustflags}" %if %{with cli} install -D target/release/tdb %{buildroot}/%{_sbindir}/%{name}-cli-trust install -D target/release/faprofiler %{buildroot}/%{_sbindir}/%{name}-cli-profiler -install -D target/release/rulec %{buildroot}/%{_sbindir}/%{name}-cli-rulec +install -D target/release/rulec %{buildroot}/%{_sbindir}/%{name}-cli-rules %endif %if %{with gui} @@ -153,6 +153,7 @@ install -D target/release/rulec %{buildroot}/%{_sbindir}/%{name}-cli-rulec %{python3} help install --dest %{buildroot}/%{_datadir}/help install -D bin/%{name} %{buildroot}/%{_sbindir}/%{name} install -D data/%{name}.8 -t %{buildroot}/%{_mandir}/man8/ +install -D data/%{name}-cli-*.8 -t %{buildroot}/%{_mandir}/man8/ install -D data/config.toml -t %{buildroot}%{_sysconfdir}/%{name}/ desktop-file-install data/%{name}.desktop find locale -name %{name}.mo -exec cp --parents -rv {} %{buildroot}/%{_datadir} \; @@ -167,13 +168,14 @@ desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop %files cli %attr(755,root,root) %{_sbindir}/%{name}-cli-trust %attr(755,root,root) %{_sbindir}/%{name}-cli-profiler -%attr(755,root,root) %{_sbindir}/%{name}-cli-rulec +%attr(755,root,root) %{_sbindir}/%{name}-cli-rules %files gui %{python3_sitearch}/%{module} %{python3_sitearch}/%{module}-%{module_version}* %attr(755,root,root) %{_sbindir}/%{name} %attr(644,root,root) %{_mandir}/man8/%{name}.8* +%attr(644,root,root) %{_mandir}/man8/%{name}-cli-*.8* %attr(755,root,root) %{_datadir}/applications/%{name}.desktop %config(noreplace) %attr(644,root,root) %{_sysconfdir}/%{name}/config.toml %ghost %attr(640,root,root) %verify(not md5 size mtime) %{_localstatedir}/log/%{name}/%{name}.log diff --git a/scripts/srpm/fapolicy-analyzer.el9.spec b/scripts/srpm/fapolicy-analyzer.el9.spec index 7f645d302..81c35ed6b 100644 --- a/scripts/srpm/fapolicy-analyzer.el9.spec +++ b/scripts/srpm/fapolicy-analyzer.el9.spec @@ -238,7 +238,7 @@ cargo build --bin rulec --release %if %{with cli} install -D target/release/tdb %{buildroot}/%{_sbindir}/%{name}-cli-trust install -D target/release/faprofiler %{buildroot}/%{_sbindir}/%{name}-cli-profiler -install -D target/release/rulec %{buildroot}/%{_sbindir}/%{name}-cli-rulec +install -D target/release/rulec %{buildroot}/%{_sbindir}/%{name}-cli-rules %endif %if %{with gui} @@ -246,6 +246,7 @@ install -D target/release/rulec %{buildroot}/%{_sbindir}/%{name}-cli-rulec %{python3} help install --dest %{buildroot}/%{_datadir}/help install -D bin/%{name} %{buildroot}/%{_sbindir}/%{name} install -D data/%{name}.8 -t %{buildroot}/%{_mandir}/man8/ +install -D data/%{name}-cli-*.8 -t %{buildroot}/%{_mandir}/man8/ desktop-file-install data/%{name}.desktop find locale -name %{name}.mo -exec cp --parents -rv {} %{buildroot}/%{_datadir} \; %find_lang %{name} --with-gnome @@ -259,13 +260,14 @@ desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop %files cli %attr(755,root,root) %{_sbindir}/%{name}-cli-trust %attr(755,root,root) %{_sbindir}/%{name}-cli-profiler -%attr(755,root,root) %{_sbindir}/%{name}-cli-rulec +%attr(755,root,root) %{_sbindir}/%{name}-cli-rules %files gui %{python3_sitearch}/%{module} %{python3_sitearch}/%{module}-%{module_version}* %attr(755,root,root) %{_sbindir}/%{name} %attr(644,root,root) %{_mandir}/man8/%{name}.8* +%attr(644,root,root) %{_mandir}/man8/%{name}-cli-*.8* %attr(755,root,root) %{_datadir}/applications/%{name}.desktop %files -f %{name}.lang