Skip to content

Commit

Permalink
[REF. #62] Both the LogAlert and Osquery config files are now generat…
Browse files Browse the repository at this point in the history
…ed on a per-server basis. The install script does not depend on git anymore.
  • Loading branch information
csavelief committed Aug 21, 2024
1 parent 56f9c93 commit 8c6ab29
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 59 deletions.
2 changes: 1 addition & 1 deletion app/Http/Controllers/YnhServerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public function installOsquery(YnhServer $server, InstallOsqueryRequest $request

$uid = Str::random(10);
$ssh = $server->sshConnection($uid, Auth::user());
if ($server->sshInstallOsquery($ssh)) {
if ($server->sshInstallLogAlertAndOsquery($ssh)) {
return response()->json(['success' => "Osquery has been installed!"]);
}
return response()->json(['error' => "An error occurred."]);
Expand Down
1 change: 1 addition & 0 deletions app/Http/Middleware/VerifyCsrfToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class VerifyCsrfToken extends Middleware
'/setup/token',
'/setup/script',
'/logalert/*',
'/osquery/*',
'/metrics',
];
}
2 changes: 1 addition & 1 deletion app/Listeners/ConfigureHostListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected function handle2($event)
$server->save();

$ssh = $server->sshConnection($uid, $user);
$isOk = $isOk && $server->sshInstallOsquery($ssh);
$isOk = $isOk && $server->sshInstallLogAlertAndOsquery($ssh);
}

// $ports = [25 /* email */, 389 /* ldap */, 587 /* email */, 853 /* ? */, 993 /* email */, 5222 /* xmpp client */, 5269 /* xmpp server */];
Expand Down
119 changes: 94 additions & 25 deletions app/Models/YnhOsquery.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,101 @@ class YnhOsquery extends Model
'packed' => 'boolean',
];

public static function installOsquery(YnhServer $server): string
public static function configLogAlert(YnhServer $server): array
{
return ["monitors" => [
[
"name" => "Monitor Osquery Daemon Output",
"path" => "/var/log/osquery/osqueryd.*.log",
"match" => ".*",
"regexp" => true,
"url" => "https://app.towerify.io/logalert/{$server->secret}"
]
],
"sleep" => 5,
"echo" => false,
"verbose" => 1
];
}

public static function configOsquery(): array
{
$schedule = [];
YnhOsqueryRule::orderBy('name', 'asc')
->get()
->each(function (YnhOsqueryRule $rule) use (&$schedule) {
$schedule[$rule->name] = [
'query' => $rule->query,
'interval' => $rule->interval,
'removed' => $rule->removed,
'snapshot' => $rule->snapshot,
'platform' => $rule->platform->value,
];
});
return [
"options" => [
"logger_snapshot_event_type" => "true",
"schedule_splay_percent" => 10
],
"platform" => "linux",
"schedule" => $schedule,
"file_paths" => [
"configuration" => [
"/etc/passwd",
"/etc/shadow",
"/etc/ld.so.preload",
"/etc/ld.so.conf",
"/etc/ld.so.conf.d/%%",
"/etc/pam.d/%%",
"/etc/resolv.conf",
"/etc/rc%/%%",
"/etc/my.cnf",
"/etc/modules",
"/etc/hosts",
"/etc/hostname",
"/etc/fstab",
"/etc/crontab",
"/etc/cron%/%%",
"/etc/init/%%",
"/etc/rsyslog.conf"
],
"binaries" => [
"/usr/bin/%%",
"/usr/sbin/%%",
"/bin/%%",
"/sbin/%%",
"/usr/local/bin/%%",
"/usr/local/sbin/%%"
]
],
"events" => [
"disable_subscribers" => [
"user_events"
]
],
"packs" => [],
];
}

public static function installLogAlertAndOsquery(YnhServer $server): string
{
return <<<EOT
#!/bin/bash
apt install wget curl git tmux jq -y
apt install wget curl tmux jq -y
# Install Osquery
if [ ! -f /etc/osquery/osquery.conf ]; then
# Install Osquery
wget https://pkg.osquery.io/deb/osquery_5.11.0-1.linux_amd64.deb
apt install ./osquery_5.11.0-1.linux_amd64.deb
rm osquery_5.11.0-1.linux_amd64.deb
# Pull Palantir's base rules
git clone https://github.com/palantir/osquery-configuration.git
cp -r osquery-configuration/Classic/Servers/Linux/* /etc/osquery/
rm -rf osquery-configuration/
fi
if [ ! -f /opt/logalert/config.json ]; then
# Install LogAlert
# Install LogAlert
if [ ! -f /opt/logalert/config.json ]; then
mkdir -p /opt/logalert
curl -L https://github.com/jhuckaby/logalert/releases/latest/download/logalert-linux-x64 >/opt/logalert/logalert.bin
chmod 755 /opt/logalert/logalert.bin
# Set base config
echo '{"monitors":[{"name":"Monitor Osquery Daemon Output","path":"/var/log/osquery/osqueryd.*.log","match":".*","regexp":true,"url":"https://app.towerify.io/logalert/{$server->secret}"}],"sleep":5,"echo":true,"verbose":1}' >/opt/logalert/config.json
fi
# LEGACY CODE BEGINS HERE
Expand All @@ -82,17 +149,19 @@ public static function installOsquery(YnhServer $server): string
sudo -H -u root bash -c 'tmux kill-ses -t logalert'
osqueryctl stop osqueryd
# Update Osquery's rules
cat /etc/osquery/osquery.conf | \
jq $'del(.schedule.socket_events)' | \
jq $'del(.schedule.network_interfaces_snapshot)' | \
jq $'del(.schedule.process_events)' | \
jq $'.schedule.packages_available_snapshot += {query:"SELECT name, version, source FROM deb_packages;",interval:86400,snapshot:true}' | \
jq $'.schedule.memory_available_snapshot += {query:"select printf(\'%.2f\',((memory_total - memory_available) * 1.0)/1073741824) as used_space_gb, printf(\'%.2f\',(1.0 * memory_available / 1073741824)) as space_left_gb, printf(\'%.2f\',(1.0 * memory_total / 1073741824)) as total_space_gb, printf(\'%.2f\',(((memory_total - memory_available) * 1.0)/1073741824)/(1.0 * memory_total / 1073741824)) * 100 as \'%_used\', printf(\'%.2f\',(1.0 * memory_available / 1073741824)/(1.0 * memory_total / 1073741824)) * 100 as \'%_available\' from memory_info;",interval:300,snapshot:true}' | \
jq $'.schedule.disk_available_snapshot += {query:"select printf(\'%.2f\',((blocks - blocks_available * 1.0) * blocks_size)/1073741824) as used_space_gb, printf(\'%.2f\',(1.0 * blocks_available * blocks_size / 1073741824)) as space_left_gb, printf(\'%.2f\',(1.0 * blocks * blocks_size / 1073741824)) as total_space_gb, printf(\'%.2f\',(((blocks - blocks_available * 1.0) * blocks_size)/1073741824)/(1.0 * blocks * blocks_size / 1073741824)) * 100 as \'%_used\', printf(\'%.2f\',(1.0 * blocks_available * blocks_size / 1073741824)/(1.0 * blocks * blocks_size / 1073741824)) * 100 as \'%_available\' from mounts where path = \'/\';",interval:300,snapshot:true}' \
>/etc/osquery/osquery2.conf
mv -f /etc/osquery/osquery2.conf /etc/osquery/osquery.conf
# Update LogAlert configuration
wget -O /opt/logalert/config2.json https://app.towerify.io/logalert/{$server->secret}
if jq empty /opt/logalert/config2.json; then
mv -f /opt/logalert/config2.json /opt/logalert/config.json
fi
# Update Osquery configuration
wget -O /etc/osquery/osquery2.conf https://app.towerify.io/osquery/{$server->secret}
if jq empty /etc/osquery/osquery2.conf; then
mv -f /etc/osquery/osquery2.conf /etc/osquery/osquery.conf
fi
# Drop Osquery daemon's output every sunday at 01:00 am
cat <(fgrep -i -v 'rm /var/log/osquery/osqueryd.results.log /var/log/osquery/osqueryd.snapshots.log' <(crontab -l)) <(echo '0 1 * * 0 rm /var/log/osquery/osqueryd.results.log /var/log/osquery/osqueryd.snapshots.log') | crontab -
Expand Down
6 changes: 3 additions & 3 deletions app/Models/YnhServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,9 @@ public function sshTestConnection(): bool
return $this->sshKeyPair()->isSshConnectionUpAndRunning($this->ip(), $this->ssh_port, $this->ssh_username);
}

public function sshInstallOsquery(SshConnection2 $ssh)
public function sshInstallLogAlertAndOsquery(SshConnection2 $ssh): bool
{
$installScript = YnhOsquery::installOsquery($this);
$installScript = YnhOsquery::installLogAlertAndOsquery($this);
$ssh->newTrace(SshTraceStateEnum::IN_PROGRESS, 'Installing Osquery...');
$filename = 'install-yunohost-' . Str::random(10);
$isOk = $ssh->upload($filename, $installScript);
Expand All @@ -376,7 +376,7 @@ public function sshInstallOsquery(SshConnection2 $ssh)
return $isOk;
}

public function sshInstallYunoHost(SshConnection2 $ssh, string $domain, string $username)
public function sshInstallYunoHost(SshConnection2 $ssh, string $domain, string $username): bool
{
$password = Str::random(30);
$installScript = <<<EOT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,6 @@ public function up()
\App\Enums\OsqueryPlatformEnum::ALL->value,
])->default(\App\Enums\OsqueryPlatformEnum::ALL->value);
});
Schema::create('ynh_osquery_rules_scope_customer', function (Blueprint $table) {

$table->id();
$table->timestamps();

// Link a rule to a customer
$table->intOrBigIntBasedOnRelated('rule_id', Schema::connection(null), 'ynh_osquery_rules.id')->cascadeOnDelete();
$table->foreign('rule_id')->references('id')->on('ynh_osquery_rules')->cascadeOnDelete();

$table->intOrBigIntBasedOnRelated('customer_id', Schema::connection(null), 'customers.id')->cascadeOnDelete();
$table->foreign('customer_id')->references('id')->on('customers')->cascadeOnDelete();
});
Schema::create('ynh_osquery_rules_scope_tenant', function (Blueprint $table) {

$table->id();
$table->timestamps();

// Link a rule to a tenant
$table->intOrBigIntBasedOnRelated('rule_id', Schema::connection(null), 'ynh_osquery_rules.id')->cascadeOnDelete();
$table->foreign('rule_id')->references('id')->on('ynh_osquery_rules')->cascadeOnDelete();

$table->intOrBigIntBasedOnRelated('tenant_id', Schema::connection(null), 'tenants.id')->cascadeOnDelete();
$table->foreign('tenant_id')->references('id')->on('tenants')->cascadeOnDelete();
});
}

/**
Expand All @@ -69,8 +45,6 @@ public function up()
*/
public function down()
{
Schema::dropIfExists('ynh_osquery_rules_scope_tenant');
Schema::dropIfExists('ynh_osquery_rules_scope_customer');
Schema::dropIfExists('ynh_osquery_rules');
}
};
4 changes: 2 additions & 2 deletions database/seeds/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ private function setupProducts(): void

private function setupOsqueryRules(): void
{
$rules = $this->palantirOsqueryRulesForLinux()['schedule'];
$rules = $this->palantirOsqueryRules()['schedule'];
foreach ($rules as $name => $rule) {
$fields = [];
if (isset($rule['description'])) {
Expand Down Expand Up @@ -322,7 +322,7 @@ private function customRules(): array
]];
}

private function palantirOsqueryRulesForLinux(): array
private function palantirOsqueryRules(): array
{
// See https://github.com/palantir/osquery-configuration/blob/master/Classic/Servers/Linux/osquery.conf for details
$rules = <<< EOF
Expand Down
32 changes: 31 additions & 1 deletion routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
// 3.2 chmod +x install.sh
// 3.3 ./install.sh
// 3.4 rm install.sh
$installScript = \App\Models\YnhOsquery::installOsquery($server);
$installScript = \App\Models\YnhOsquery::installLogAlertAndOsquery($server);

return response($installScript, 200)
->header('Content-Type', 'text/plain');
Expand Down Expand Up @@ -228,6 +228,36 @@
return new JsonResponse(['status' => 'success'], 200, ['Access-Control-Allow-Origin' => '*']);
});

Route::get('/logalert/{secret}', function (string $secret, \Illuminate\Http\Request $request) {

$server = \App\Models\YnhServer::where('secret', $secret)->first();

if (!$server) {
return response('Unknown server', 500)
->header('Content-Type', 'text/plain');
}

$config = json_encode(\App\Models\YnhOsquery::configLogAlert($server));

return response($config, 200)
->header('Content-Type', 'text/plain');
});

Route::get('/osquery/{secret}', function (string $secret, \Illuminate\Http\Request $request) {

$server = \App\Models\YnhServer::where('secret', $secret)->first();

if (!$server) {
return response('Unknown server', 500)
->header('Content-Type', 'text/plain');
}

$config = json_encode(\App\Models\YnhOsquery::configOsquery());

return response($config, 200)
->header('Content-Type', 'text/plain');
});

/** @deprecated */
Route::post('metrics', function (\Illuminate\Http\Request $request) {

Expand Down

0 comments on commit 8c6ab29

Please sign in to comment.