evebox/commands/
elastic_debug.rs

1// Copyright (C) 2020 Jason Ish
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Affero General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16use crate::elastic::request::Request;
17use crate::elastic::{self, Client};
18use crate::types::JsonValue;
19use anyhow::Result;
20use serde::Deserialize;
21use std::collections::HashMap;
22
23pub async fn main(args: &clap::ArgMatches<'static>) -> Result<()> {
24    let url = args.value_of("elasticsearch").unwrap();
25    let client = Client::new(url);
26    let version = client.get_version().await?;
27    let ignore_dot = true;
28    println!("Elasticsearch version: {}", version.version);
29
30    let indices: Vec<Index> = client
31        .get("_cat/indices?format=json")?
32        .send()
33        .await?
34        .json()
35        .await?;
36    for index in indices {
37        if ignore_dot && index.index.starts_with('.') {
38            continue;
39        }
40        println!("Found index: {}", index.index);
41    }
42
43    let templates: HashMap<String, Template> =
44        client.get("_template")?.send().await?.json().await?;
45    for (name, template) in templates {
46        if ignore_dot && name.starts_with('.') {
47            continue;
48        }
49        println!("Template: {} => {:?}", name, template);
50    }
51
52    if let Err(err) = check_logstash(&client).await {
53        println!("Failed to check logstash-* for Suricata events: {}", err);
54    }
55    if let Err(err) = check_filebeat(&client).await {
56        println!("Failed to check filebeat-* for Suricata events: {}", err);
57    }
58    if let Err(err) = check_filebeat_ecs(&client).await {
59        println!(
60            "Failed to check filebeat-* for Suricata ECS events: {}",
61            err
62        );
63    }
64
65    Ok(())
66}
67
68async fn check_logstash(client: &Client) -> anyhow::Result<()> {
69    let index_pattern = "logstash-*";
70    let mut request = elastic::request::new_request();
71    request.push_filter(elastic::request::exists_filter("event_type"));
72    request.push_filter(elastic::request::exists_filter("src_ip"));
73    request.push_filter(elastic::request::exists_filter("dest_ip"));
74    request.size(1);
75    let response: JsonValue = client
76        .post(&format!("{}/_search", index_pattern))?
77        .json(&request)
78        .send()
79        .await?
80        .json()
81        .await?;
82    let mut found = false;
83    if let Some(hits) = response["hits"]["hits"].as_array() {
84        if !hits.is_empty() {
85            found = true;
86        }
87    }
88
89    if found {
90        println!("Found Suricata events at index pattern {}", index_pattern);
91    } else {
92        println!(
93            "No Suricata events found at index pattern {}",
94            index_pattern
95        );
96    }
97
98    Ok(())
99}
100
101async fn check_filebeat(client: &Client) -> anyhow::Result<()> {
102    let index_pattern = "filebeat-*";
103    let mut request = elastic::request::new_request();
104    request.push_filter(elastic::request::exists_filter("event_type"));
105    request.push_filter(elastic::request::exists_filter("src_ip"));
106    request.push_filter(elastic::request::exists_filter("dest_ip"));
107    request.size(1);
108    let response: JsonValue = client
109        .post(&format!("{}/_search", index_pattern))?
110        .json(&request)
111        .send()
112        .await?
113        .json()
114        .await?;
115    let mut found = false;
116    if let Some(hits) = response["hits"]["hits"].as_array() {
117        if !hits.is_empty() {
118            found = true;
119        }
120    }
121
122    if found {
123        println!("Found Suricata events at index pattern {}", index_pattern);
124    } else {
125        println!(
126            "No Suricata events found at index pattern {}",
127            index_pattern
128        );
129    }
130
131    Ok(())
132}
133
134async fn check_filebeat_ecs(client: &Client) -> anyhow::Result<()> {
135    let index_pattern = "filebeat-*";
136    let mut request = elastic::request::new_request();
137    request.push_filter(elastic::request::exists_filter("ecs"));
138    request.push_filter(elastic::request::exists_filter("suricata.eve.event_type"));
139    request.size(1);
140    let response: JsonValue = client
141        .post(&format!("{}/_search", index_pattern))?
142        .json(&request)
143        .send()
144        .await?
145        .json()
146        .await?;
147
148    let mut found = false;
149    if let Some(hits) = response["hits"]["hits"].as_array() {
150        if !hits.is_empty() {
151            found = true;
152        }
153    }
154
155    if found {
156        println!(
157            "Found Suricata ECS events at index pattern {}",
158            index_pattern
159        );
160    } else {
161        println!(
162            "No Suricata ECS events found at index pattern {}",
163            index_pattern
164        );
165    }
166
167    Ok(())
168}
169
170#[derive(Debug, Deserialize)]
171struct Index {
172    pub index: String,
173}
174
175#[derive(Debug, Deserialize)]
176struct Template {
177    pub version: Option<u64>,
178    pub index_patterns: Option<Vec<String>>,
179}