|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# A script to gather key Cyber Hygiene metrics from various sources. Output |
| 4 | +# is a header row and a single line of comma-separated values. |
| 5 | +# |
| 6 | +# Usage: |
| 7 | +# gather_key_cyhy_metrics.sh cyhy_db_fqdn cyhy_reporter_fqdn cyhy_mongodb_uri \ |
| 8 | +# cyhy_mongodb_username cyhy_mongodb_password |
| 9 | +# |
| 10 | +# - cyhy_db_fqdn: The fully qualified domain name of the Cyber Hygiene database |
| 11 | +# server (e.g. "database.example.gov") |
| 12 | +# - cyhy_reporter_fqdn: The fully qualified domain name of the Cyber Hygiene |
| 13 | +# reporter server (e.g. "reporter.example.gov") |
| 14 | +# - cyhy_mongodb_uri: The MongoDB URI for the Cyber Hygiene database (e.g. |
| 15 | +# "mongodb://localhost:27017/cyhy" or "localhost/cyhy") |
| 16 | +# - cyhy_mongodb_username: The MongoDB username for the Cyber Hygiene database |
| 17 | +# - cyhy_mongodb_password: The MongoDB password for the Cyber Hygiene database |
| 18 | +# |
| 19 | +# Requires: |
| 20 | +# - SSH access to the Cyber Hygiene database and reporter servers |
| 21 | +# - mongosh installed |
| 22 | +# - A MongoDB user with read access to the Cyber Hygiene database |
| 23 | + |
| 24 | +set -o nounset |
| 25 | +set -o errexit |
| 26 | +set -o pipefail |
| 27 | + |
| 28 | +if [ $# -eq 5 ]; then |
| 29 | + cyhy_db_fqdn=$1 |
| 30 | + cyhy_reporter_fqdn=$2 |
| 31 | + cyhy_mongodb_uri=$3 |
| 32 | + cyhy_mongodb_username=$4 |
| 33 | + cyhy_mongodb_password=$5 |
| 34 | +else |
| 35 | + echo "Usage: gather_key_cyhy_metrics.sh cyhy_db_fqdn cyhy_reporter_fqdn cyhy_mongodb_uri cyhy_mongodb_username cyhy_mongodb_password" |
| 36 | + echo |
| 37 | + echo "cyhy_db_fqdn: The fully qualified domain name of the Cyber Hygiene database server (e.g. \"database.example.gov\")" |
| 38 | + echo "cyhy_reporter_fqdn: The fully qualified domain name of the Cyber Hygiene reporter server (e.g. \"reporter.example.gov\")" |
| 39 | + echo "cyhy_mongodb_uri: The MongoDB URI for the Cyber Hygiene database (e.g. \"mongodb://localhost:27017/cyhy\" or \"localhost/cyhy\")" |
| 40 | + echo "cyhy_mongodb_username: The MongoDB username for the Cyber Hygiene database" |
| 41 | + echo "cyhy_mongodb_password: The MongoDB password for the Cyber Hygiene database" |
| 42 | + exit 1 |
| 43 | +fi |
| 44 | + |
| 45 | +today=$(date +%Y-%m-%d) |
| 46 | + |
| 47 | +# COMMANDER MAIN LOOP DURATION METRICS |
| 48 | +# NOTE: These metrics are pulled from all existing (non-compressed) commander |
| 49 | +# logs, not just the most recent one. |
| 50 | +commander_duration_mean=$(ssh "$cyhy_db_fqdn" "grep --only-matching --perl-regexp 'Last cycle took .* seconds' /var/log/cyhy/commander.log* | awk '{ total += \$4; count++ } END { print total/count }'") |
| 51 | +commander_duration_median=$(ssh "$cyhy_db_fqdn" "grep --only-matching --perl-regexp 'Last cycle took .* seconds' /var/log/cyhy/commander.log* | cut --delimiter ' ' --fields 4 | sort --numeric-sort | awk '{ a[i++]=\$1; } END { print a[int(i/2)]; }'") |
| 52 | +commander_duration_max=$(ssh "$cyhy_db_fqdn" "grep --only-matching --perl-regexp 'Last cycle took .* seconds' /var/log/cyhy/commander.log* | cut --delimiter ' ' --fields 4 | sort --numeric-sort | tail --lines 1") |
| 53 | + |
| 54 | +# COMMANDER SCAN BACKLOG METRICS |
| 55 | +scan_stages=("NETSCAN1" "NETSCAN2" "PORTSCAN" "VULNSCAN") |
| 56 | + |
| 57 | +# Hosts with non-zero priority |
| 58 | +declare -A nonzero_priority_waiting_count |
| 59 | +for stage in "${scan_stages[@]}"; do |
| 60 | + nonzero_priority_waiting_count[$stage]=$(mongosh --quiet "$cyhy_mongodb_uri" --username "$cyhy_mongodb_username" --password "$cyhy_mongodb_password" --eval "db.hosts.countDocuments({'status': 'WAITING', 'priority': {\$ne: 0}, 'stage':'$stage'})") |
| 61 | +done |
| 62 | + |
| 63 | +# Hosts with zero priority |
| 64 | +declare -A zero_priority_waiting_count |
| 65 | +for stage in "${scan_stages[@]}"; do |
| 66 | + zero_priority_waiting_count[$stage]=$(mongosh --quiet "$cyhy_mongodb_uri" --username "$cyhy_mongodb_username" --password "$cyhy_mongodb_password" --eval "db.hosts.countDocuments({'status': 'WAITING', 'priority': 0, 'stage':'$stage'})") |
| 67 | +done |
| 68 | + |
| 69 | +# WEEKLY REPORTING METRICS |
| 70 | +weekly_snapshots_duration_minutes=$(ssh "$cyhy_reporter_fqdn" "tail --lines 10 /var/cyhy/reports/output/snapshots_reports_scorecard_automation.log | grep 'Time to generate snapshots' | cut --delimiter ' ' --fields 9") |
| 71 | +weekly_reports_duration_minutes=$(ssh "$cyhy_reporter_fqdn" "tail --lines 10 /var/cyhy/reports/output/snapshots_reports_scorecard_automation.log | grep 'Time to generate reports' | cut --delimiter ' ' --fields 9") |
| 72 | +weekly_total_reporting_duration_minutes=$(ssh "$cyhy_reporter_fqdn" "tail --lines 10 /var/cyhy/reports/output/snapshots_reports_scorecard_automation.log | grep 'Total time' | cut --delimiter ' ' --fields 7") |
| 73 | + |
| 74 | +# WEEKLY DATABASE ARCHIVE METRICS |
| 75 | +weekly_cyhy_db_archive_duration_minutes=$(ssh "$cyhy_db_fqdn" "grep 'successfully completed' \$(ls -rt /var/log/cyhy/archive.log-* | tail --lines 1) | grep --only-matching '(.*)' | sed 's/[( minutes)]//g'") |
| 76 | + |
| 77 | +# DAILY CYHY FEED METRICS |
| 78 | +daily_cyhy_feed_duration_minutes=$(ssh "$cyhy_db_fqdn" "grep 'Finished data extraction process' /var/log/cyhy/feeds.log | cut --delimiter ' ' --fields 2 | awk -F: '{print (\$1 * 60) + \$2}'") |
| 79 | + |
| 80 | +# OUTPUT RESULTS |
| 81 | +echo "Date,Commander Main Loop Duration Mean (sec),Commander Main Loop Duration Median (sec),Commander Main Loop Duration Max (sec),NETSCAN1 hosts waiting (non-zero priority),NETSCAN2 hosts waiting (non-zero priority),PORTSCAN hosts waiting (non-zero priority),VULNSCAN hosts waiting (non-zero priority),NETSCAN1 hosts waiting (zero priority),NETSCAN2 hosts waiting (zero priority),PORTSCAN hosts waiting (zero priority),VULNSCAN hosts waiting (zero priority),Weekly Snapshots Duration (min),Weekly Reports Duration (min),Weekly Total Reporting Duration (min),Weekly CyHy DB Archive Duration (min),Daily CyHy Feed Duration (min)" |
| 82 | +echo "$today,$commander_duration_mean,$commander_duration_median,$commander_duration_max,${nonzero_priority_waiting_count[NETSCAN1]},${nonzero_priority_waiting_count[NETSCAN2]},${nonzero_priority_waiting_count[PORTSCAN]},${nonzero_priority_waiting_count[VULNSCAN]},${zero_priority_waiting_count[NETSCAN1]},${zero_priority_waiting_count[NETSCAN2]},${zero_priority_waiting_count[PORTSCAN]},${zero_priority_waiting_count[VULNSCAN]},$weekly_snapshots_duration_minutes,$weekly_reports_duration_minutes,$weekly_total_reporting_duration_minutes,$weekly_cyhy_db_archive_duration_minutes,$daily_cyhy_feed_duration_minutes" |
| 83 | + |
| 84 | +exit 0 |
0 commit comments