Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(option): auto complete #1340

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ bytesize = "1.*"
chrono = "0.4.*"
cidr-utils = "0.6.*"
clap = { version = "4.*", features = ["derive", "cargo", "color"]}
clap_complete = "*"
comfy-table = "7.*"
compact_str = "0.7.*"
console = "0.15.*"
Expand Down
2 changes: 1 addition & 1 deletion rules
Submodule rules updated 1005 files
28 changes: 24 additions & 4 deletions src/detections/configs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use crate::options::pivot::PIVOT_KEYWORD;
use crate::options::profile::{load_profile, Profile};
use aho_corasick::{AhoCorasick, AhoCorasickBuilder, MatchKind};
use chrono::{DateTime, Days, Duration, Local, Months, Utc};
use clap::{ArgAction, ArgGroup, Args, ColorChoice, Command, CommandFactory, Parser, Subcommand};
use clap::{
ArgAction, ArgGroup, Args, ColorChoice, Command, CommandFactory, Parser, Subcommand, ValueHint,
};
use compact_str::CompactString;
use hashbrown::{HashMap, HashSet};
use itertools::Itertools;
Expand Down Expand Up @@ -111,6 +113,7 @@ impl StoredStatic {
_ => false,
};
let common_options = match &input_config.as_ref().unwrap().action {
Some(Action::AutoComplete(opt)) => opt.common_options,
Some(Action::CsvTimeline(opt)) => opt.output_options.common_options,
Some(Action::JsonTimeline(opt)) => opt.output_options.common_options,
Some(Action::LevelTuning(opt)) => opt.common_options,
Expand Down Expand Up @@ -296,6 +299,7 @@ impl StoredStatic {
Some(Action::LogonSummary(opt)) => opt.output.as_ref(),
Some(Action::Search(opt)) => opt.output.as_ref(),
Some(Action::ComputerMetrics(opt)) => opt.output.as_ref(),
Some(Action::AutoComplete(opt)) => opt.output.as_ref(),
_ => None,
};
let general_ch_abbr = create_output_filter_config(
Expand Down Expand Up @@ -884,6 +888,10 @@ pub enum Action {
/// List the output profiles
ListProfiles(CommonOptions),

#[clap(display_order = 383)]
/// Make the auto complete
AutoComplete(AutoCompleteOptions),

#[clap(
author = "Yamato Security (https://github.com/Yamato-Security/hayabusa - @SecurityYamato)",
help_template = "\nHayabusa v2.17.0 - Dev Build\n{author-with-newline}\n{usage-heading}\n hayabusa.exe computer-metrics <INPUT> [OPTIONS]\n\n{all-args}",
Expand Down Expand Up @@ -911,6 +919,7 @@ impl Action {
Action::ListProfiles(_) => 9,
Action::Search(_) => 10,
Action::ComputerMetrics(_) => 11,
Action::AutoComplete(_) => 12,
}
} else {
100
Expand All @@ -931,21 +940,32 @@ impl Action {
Action::ListProfiles(_) => "list-profiles",
Action::Search(_) => "search",
Action::ComputerMetrics(_) => "computer-metrics",
Action::AutoComplete(_) => "auto-complete",
}
} else {
""
}
}
}

#[derive(Args, Clone, Debug)]
pub struct AutoCompleteOptions {
#[clap(flatten)]
pub common_options: CommonOptions,

/// Save the auto complete in shell format (ex: auto-complete.sh)
#[arg(help_heading = Some("Output"), short = 'o', long, value_name = "FILE", display_order = 410)]
pub output: Option<PathBuf>,
}

#[derive(Args, Clone, Debug)]
pub struct DetectCommonOption {
/// Scan JSON formatted logs instead of .evtx (.json or .jsonl)
#[arg(help_heading = Some("General Options"), short = 'J', long = "JSON-input", conflicts_with = "live_analysis", display_order = 360)]
pub json_input: bool,

/// Specify additional evtx file extensions (ex: evtx_data)
#[arg(help_heading = Some("General Options"), long = "target-file-ext", value_name = "FILE-EXT...", use_value_delimiter = true, value_delimiter = ',', display_order = 460)]
#[arg(help_heading = Some("General Options"), long = "target-file-ext", value_name = "FILE-EXT...", use_value_delimiter = true, value_delimiter = ',', display_order = 460, value_hint(ValueHint::FilePath))]
pub evtx_file_ext: Option<Vec<String>>,

/// Number of threads (default: optimal number for performance)
Expand All @@ -970,8 +990,8 @@ pub struct DetectCommonOption {
default_value = "./rules/config",
hide_default_value = true,
value_name = "DIR",
display_order = 442
)]
display_order = 442,
value_hint(ValueHint::FilePath))]
pub config: PathBuf,

/// Output verbose information
Expand Down
13 changes: 13 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ use hayabusa::detections::utils::{
check_setting_path, get_writable_color, output_and_data_stack_for_html, output_profile_name,
};
use hayabusa::filter::create_channel_filter;
use hayabusa::options::auto_complete::auto_complete;
use hayabusa::options::htmlreport::{self, HTML_REPORTER};
use hayabusa::options::pivot::create_output;
use hayabusa::options::pivot::PIVOT_KEYWORD;
Expand Down Expand Up @@ -154,6 +155,13 @@ impl App {
println!();
return;
}

//ロゴと時間が表示さないように実行したい
if let Action::AutoComplete(_) = &stored_static.config.action.as_ref().unwrap() {
auto_complete(app, stored_static.output_path.as_ref());
return;
}

if !stored_static.common_options.quiet {
self.output_logo(stored_static);
write_color_buffer(&BufferWriter::stdout(ColorChoice::Always), None, "", true).ok();
Expand Down Expand Up @@ -352,6 +360,11 @@ impl App {
self.print_contributors();
return;
}

Action::AutoComplete(_) => {
panic!("This should not be called here.");
}

Action::LogonSummary(_) => {
let mut target_output_path = Nested::<String>::new();
if let Some(path) = &stored_static.output_path {
Expand Down
34 changes: 34 additions & 0 deletions src/options/auto_complete.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::{env, path::PathBuf};

use clap_complete::{generate_to, Generator, Shell};
use dialoguer::Select;

pub fn auto_complete(app: &mut clap::Command, output_path: Option<&PathBuf>) {
let shell = select_shell();
print_completer(shell, app, output_path);
}

fn select_shell() -> Shell {
let items: Vec<Shell> = vec![Shell::Bash, Shell::Elvish, Shell::Fish, Shell::PowerShell];

let selection = Select::new()
.with_prompt("Which shell are you using?")
.items(&items)
.interact()
.unwrap();

items[selection]
}
fn print_completer<G: Generator>(
generator: G,
app: &mut clap::Command,
output_path: Option<&PathBuf>,
) {
let mut name = "auto-complete".to_string();
if output_path.is_some() {
name = output_path.unwrap().to_str().unwrap().to_string();
}
let out_dir: PathBuf = env::current_dir().expect("can't get current directory");

let _ = generate_to(generator, app, name, out_dir);
}
1 change: 1 addition & 0 deletions src/options/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod auto_complete;
pub mod geoip_search;
pub mod htmlreport;
pub mod level_tuning;
Expand Down
Loading