Skip to content

Commit

Permalink
Merge pull request #1 from maksimryndin/ssh-observer
Browse files Browse the repository at this point in the history
ssh observer
  • Loading branch information
maksimryndin authored May 28, 2024
2 parents c39c09c + ca55c2a commit 7b8a0d4
Show file tree
Hide file tree
Showing 14 changed files with 649 additions and 28 deletions.
7 changes: 5 additions & 2 deletions .github/ISSUE_TEMPLATE/BUG_REPORT.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ body:
label: Preliminary checks
description: Please make sure that you verify each checkbox and follow the instructions for them.
options:
- label: "Before opening a new issue, please search existing issues: https://github.com/maksimryndin/goral/issues. Perhaps, the bug has been already reported or solved"
- label: "This issue is a bug report. For a feature request or other question feel free to use a blank issue."
required: true
- label: "This issue is not a feature request or other - for that just feel free to use a blank issue."
- label: "I've updated Goral to the latest version: https://github.com/maksimryndin/goral/releases and the bug still exists"
required: true
- label: "I've searched existing issues https://github.com/maksimryndin/goral/issues for the same bug and there is nothing similar"
required: true
- type: textarea
attributes:
Expand Down Expand Up @@ -80,6 +82,7 @@ body:
label: Which version of Goral do you run (`goral --version`)?
multiple: false
options:
- 0.1.7
- 0.1.6
- 0.1.5
- 0.1.4
Expand Down
2 changes: 1 addition & 1 deletion .github/site/src/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ main() {

get_architecture || return 1
local _arch="$RETVAL"
local _version=${1:-'0.1.6'}
local _version=${1:-'0.1.7'}
assert_nz "$_arch" "arch"

local _file="goral-${_version}-${_arch}"
Expand Down
8 changes: 4 additions & 4 deletions .github/site/src/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ curl --proto '=https' --tlsv1.2 -sSf https://maksimryndin.github.io/goral/instal
</summary>

```sh
wget https://github.com/maksimryndin/goral/releases/download/0.1.6/goral-0.1.6-x86_64-unknown-linux-gnu.tar.gz
tar -xzf goral-0.1.6-x86_64-unknown-linux-gnu.tar.gz
cd goral-0.1.6-x86_64-unknown-linux-gnu/
wget https://github.com/maksimryndin/goral/releases/download/0.1.7/goral-0.1.7-x86_64-unknown-linux-gnu.tar.gz
tar -xzf goral-0.1.7-x86_64-unknown-linux-gnu.tar.gz
cd goral-0.1.7-x86_64-unknown-linux-gnu/
shasum -a 256 -c sha256_checksum.txt
```
</details>
Expand All @@ -23,7 +23,7 @@ shasum -a 256 -c sha256_checksum.txt

```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
git clone --depth 1 --branch 0.1.6 https://github.com/maksimryndin/goral
git clone --depth 1 --branch 0.1.7 https://github.com/maksimryndin/goral
cd goral
RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target <target triple>
```
Expand Down
7 changes: 7 additions & 0 deletions .github/site/src/system.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ With this configuration System service will create the following sheets:
* `top_open_files` (for Linux only) - among the processes with the same user as Goral (!) - process with the most opened files
* for every process with name containing one of the substrings in `names` - a sheet with process info. Note: the first match (_case sensitive_) is used so plan accordingly a unique name for your binary.
* for every mount in `mounts` - disk usage and free space.
* `ssh` - for Linux systems ssh access log is monitored. There is a `status` field with the following values:
* `rejected` - ssh user is correct but the key or password is wrong. Also a catchall reason for other unsuccessful connections.
* `invalid_user` - an invalid ssh user (unexisting) was used.
* `timeout` - a timeout on ssh connection happened.
* `wrong_params` - no matching key exchange method found or an invalid format of the key
* `connected` - a successful ssh connection is established (by default there is a rule with a warning notification for this event)
* `terminated` - an ssh session (established earlier with `connected`) is terminated

System service doesn't require root privileges to collect the telemetry.
For a process a cpu usage percent may be [more than 100%](https://blog.guillaume-gomez.fr/articles/2021-09-06+sysinfo%3A+how+to+extract+systems%27+information) in a case of a multi-threaded process on several cores. `memory_used` by process is a [resident-set size](https://www.baeldung.com/linux/resident-set-vs-virtual-memory-size).
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
* 0.1.7
* ssh log monitoring
* rules for text now support "is" and "is not" conditions
* more helpful message about usage limits
* remove access/refresh tokens for google oauth from logs at the debug level

* 0.1.6
* safe numbers conversions
* ids collision tests
Expand Down
42 changes: 38 additions & 4 deletions Cargo.lock

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

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "goral"
version = "0.1.6"
version = "0.1.7"
edition = "2021"
author = "Maksim Ryndin"
license = "Apache-2.0"
Expand Down Expand Up @@ -46,10 +46,11 @@ tokio = { version = "^1.0", features = ["sync", "signal", "io-std", "process", "
tonic = { version = "^0.10", features = ["transport", "prost"]}
tonic-health = "0.10.2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["fmt", "json"] }
tracing-subscriber = { version = "0.3", features = ["fmt", "json", "env-filter"] }
url = { version = "2", features = ["serde"] }

[target.'cfg(target_os = "linux")'.dependencies]
logwatcher2 = { git = "https://github.com/maksimryndin/logwatcher2.git" }
psutil = { version = "3.2.2", default-features = false, features = ["disk"]}

[dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ So Goral provides the following features being deployed next to your app(s):
* [Periodic healthchecks](https://maksimryndin.github.io/goral/healthcheck.html) (aka [liveness probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/))
* [Metrics collection](https://maksimryndin.github.io/goral/metrics.html) (fully compatible with Prometheus to be easily replaced with more advanced stack as your project grows)
* [Logs](https://maksimryndin.github.io/goral/logs.html) collection (importing logs from stdout/stderr of the target process)
* [System telemetry](https://maksimryndin.github.io/goral/system.html) (CPU, Memory, Free/Busy storage space etc)
* [System telemetry](https://maksimryndin.github.io/goral/system.html) (CPU, Memory, Free/Busy storage space, ssh access log etc)
* A general key-value appendable log storage (see [the user case](https://maksimryndin.github.io/goral/kv-log.html))
* Features are modular - all [services](https://maksimryndin.github.io/goral/services.html) are switched on/off in the configuration.
* You can observe several instances of the same app or different apps on the same host with a single Goral daemon (except logs as logs are collected via stdin of Goral - see [Logs](https://maksimryndin.github.io/goral/logs.html))
Expand Down
2 changes: 1 addition & 1 deletion src/google/datavalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub(crate) enum Datavalue {
pub struct Datarow {
log_name: String,
timestamp: NaiveDateTime,
data: Vec<(String, Datavalue)>,
pub(crate) data: Vec<(String, Datavalue)>,
sheet_id: Option<SheetId>,
}

Expand Down
12 changes: 10 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::sync::Arc;
use std::time::Duration;
use tokio::signal;
use tokio::sync::broadcast;
use tracing_subscriber::filter::LevelFilter;
use tracing_subscriber::filter::{EnvFilter, LevelFilter};
use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;

Expand Down Expand Up @@ -75,6 +75,14 @@ async fn start() -> Result<(), String> {
)?;

let level = LevelFilter::from_level(config.general.log_level);
let filter = EnvFilter::new("")
.add_directive(level.into())
.add_directive(
"yup_oauth2=info"
.parse()
.expect("assert: tracing directive is properly set for yup_oauth2"),
);

let (json, plain) = if args.json {
(
Some(tracing_subscriber::fmt::layer().with_target(true).json()),
Expand All @@ -85,7 +93,7 @@ async fn start() -> Result<(), String> {
};

tracing_subscriber::registry()
.with(level)
.with(filter)
.with(json)
.with(plain)
.init();
Expand Down
68 changes: 64 additions & 4 deletions src/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ impl Rule {
RuleCondition::IsNot if value.is_string() && value.as_str()? == NOT_AVAILABLE => {
Datavalue::NotAvailable
}
RuleCondition::Is if value.is_string() && value.as_str()? != NOT_AVAILABLE => {
Datavalue::Text(value.as_str()?.to_string())
}
RuleCondition::IsNot if value.is_string() && value.as_str()? != NOT_AVAILABLE => {
Datavalue::Text(value.as_str()?.to_string())
}
RuleCondition::Contains if value.is_string() && value.as_str()? != NOT_AVAILABLE => {
Datavalue::Text(value.as_str()?.to_string())
}
Expand Down Expand Up @@ -285,6 +291,12 @@ impl Rule {
(Datavalue::Bool(c), IsNot, Datavalue::NotAvailable) => {
format!("{self} triggered for value {c}")
}
(Datavalue::Text(c), Is, Datavalue::Text(v)) if c == v => {
format!("{self} triggered for value {c}")
}
(Datavalue::Text(c), IsNot, Datavalue::Text(v)) if c != v => {
format!("{self} triggered for value {c}")
}
(Datavalue::Text(c), Contains, Datavalue::Text(v)) if c.contains(v) => {
format!("{self} triggered for value {c}")
}
Expand Down Expand Up @@ -479,8 +491,8 @@ mod tests {
None,
);
assert!(
rule.is_none(),
"test assert: `is` cannot be a condition for a text value"
rule.is_some(),
"test assert: `is` can be a condition for a text value"
);

let rule = Rule::try_from_values(
Expand Down Expand Up @@ -511,8 +523,8 @@ mod tests {
None,
);
assert!(
rule.is_none(),
"test assert: `is not` cannot be a condition for a text value"
rule.is_some(),
"test assert: `is not` can be a condition for a text value"
);

let rule = Rule::try_from_values(
Expand Down Expand Up @@ -977,6 +989,54 @@ mod tests {
_ => panic!("test assert: rule should trigger"),
};

let rule = Rule::try_from_values(
vec![
json!(0.0),
json!("log_name1"),
json!("key"),
json!(IS_CONDITION),
json!("substring"),
json!(INFO_ACTION),
],
None,
);
let mut datarow = Datarow::new(
"log_name1".to_string(),
Utc::now().naive_utc(),
vec![("key".to_string(), Datavalue::Text("substring".to_string()))],
);
datarow.sheet_id(TEST_HOST_ID, "test");
match rule.unwrap().apply(&datarow.into()) {
RuleOutput::Process(Some(Triggered { action, .. })) => {
assert_eq!(action, Action::Info)
}
_ => panic!("test assert: rule should trigger"),
};

let rule = Rule::try_from_values(
vec![
json!(0.0),
json!("log_name1"),
json!("key"),
json!(IS_NOT_CONDITION),
json!("first"),
json!(INFO_ACTION),
],
None,
);
let mut datarow = Datarow::new(
"log_name1".to_string(),
Utc::now().naive_utc(),
vec![("key".to_string(), Datavalue::Text("second".to_string()))],
);
datarow.sheet_id(TEST_HOST_ID, "test");
match rule.unwrap().apply(&datarow.into()) {
RuleOutput::Process(Some(Triggered { action, .. })) => {
assert_eq!(action, Action::Info)
}
_ => panic!("test assert: rule should trigger"),
};

let rule = Rule::try_from_values(
vec![
json!(0.0),
Expand Down
Loading

0 comments on commit 7b8a0d4

Please sign in to comment.