mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Final touches on devcontainer
This commit is contained in:
31
install/production-filesystem/services/scripts/check-cap.sh
Normal file
31
install/production-filesystem/services/scripts/check-cap.sh
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# check-cap.sh - Uses a real nmap command to detect missing container
|
||||
# privileges and warns the user. It is silent on success.
|
||||
|
||||
# Run a fast nmap command that requires raw sockets, capturing only stderr.
|
||||
ERROR_OUTPUT=$(nmap --privileged -sS -p 20211 127.0.0.1 2>&1)
|
||||
EXIT_CODE=$?
|
||||
|
||||
# Flag common capability errors regardless of exact exit code.
|
||||
if [ "$EXIT_CODE" -ne 0 ] && \
|
||||
echo "$ERROR_OUTPUT" | grep -q -e "Operation not permitted" -e "requires root privileges"
|
||||
then
|
||||
YELLOW=$(printf '\033[1;33m')
|
||||
RESET=$(printf '\033[0m')
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<'EOF'
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: Raw network capabilities are missing.
|
||||
|
||||
Tools that rely on NET_RAW/NET_ADMIN/NET_BIND_SERVICE (e.g. nmap -sS,
|
||||
arp-scan, nbtscan) will not function. Restart the container with:
|
||||
|
||||
--cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=NET_BIND_SERVICE
|
||||
|
||||
Without those caps, NetAlertX cannot inspect your network. Fix it before
|
||||
trusting any results.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
# first-run-check.sh - Checks and initializes configuration files on first run
|
||||
|
||||
# Check for app.conf and deploy if required
|
||||
if [ ! -f ${NETALERTX_CONFIG}/app.conf ]; then
|
||||
mkdir -p ${NETALERTX_CONFIG}
|
||||
cp /app/back/app.conf ${NETALERTX_CONFIG}/app.conf
|
||||
CYAN='\033[1;36m'
|
||||
RESET='\033[0m'
|
||||
>&2 printf "%s" "${CYAN}"
|
||||
>&2 cat <<'EOF'
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
🆕 First run detected. Default configuration written to /app/config/app.conf.
|
||||
|
||||
Review your settings in the UI or edit the file directly before trusting
|
||||
this instance in production.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,442 @@
|
||||
#!/bin/sh
|
||||
# This script checks if the database file exists, and if not, creates it with the initial schema.
|
||||
# It is intended to be run at the first start of the application.
|
||||
|
||||
# if the db exists, exit
|
||||
test -f "${NETALERTX_DB_FILE}" && exit 0
|
||||
|
||||
CYAN='\033[1;36m'
|
||||
RESET='\033[0m'
|
||||
>&2 printf "%s" "${CYAN}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
🆕 First run detected. Building initial database schema in ${NETALERTX_DB_FILE}.
|
||||
|
||||
Do not interrupt this step. Once complete, consider backing up the fresh
|
||||
database before onboarding sensitive networks.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
|
||||
# Write all text to db file until we see "end-of-database-schema"
|
||||
cat << end-of-database-schema > "${NETALERTX_DB_FILE}"
|
||||
CREATE TABLE sqlite_stat1(tbl,idx,stat);
|
||||
CREATE TABLE Events (eve_MAC STRING (50) NOT NULL COLLATE NOCASE, eve_IP STRING (50) NOT NULL COLLATE NOCASE, eve_DateTime DATETIME NOT NULL, eve_EventType STRING (30) NOT NULL COLLATE NOCASE, eve_AdditionalInfo STRING (250) DEFAULT (''), eve_PendingAlertEmail BOOLEAN NOT NULL CHECK (eve_PendingAlertEmail IN (0, 1)) DEFAULT (1), eve_PairEventRowid INTEGER);
|
||||
CREATE TABLE Sessions (ses_MAC STRING (50) COLLATE NOCASE, ses_IP STRING (50) COLLATE NOCASE, ses_EventTypeConnection STRING (30) COLLATE NOCASE, ses_DateTimeConnection DATETIME, ses_EventTypeDisconnection STRING (30) COLLATE NOCASE, ses_DateTimeDisconnection DATETIME, ses_StillConnected BOOLEAN, ses_AdditionalInfo STRING (250));
|
||||
CREATE TABLE IF NOT EXISTS "Online_History" (
|
||||
"Index" INTEGER,
|
||||
"Scan_Date" TEXT,
|
||||
"Online_Devices" INTEGER,
|
||||
"Down_Devices" INTEGER,
|
||||
"All_Devices" INTEGER,
|
||||
"Archived_Devices" INTEGER,
|
||||
"Offline_Devices" INTEGER,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
);
|
||||
CREATE TABLE sqlite_sequence(name,seq);
|
||||
CREATE TABLE Devices (
|
||||
devMac STRING (50) PRIMARY KEY NOT NULL COLLATE NOCASE,
|
||||
devName STRING (50) NOT NULL DEFAULT "(unknown)",
|
||||
devOwner STRING (30) DEFAULT "(unknown)" NOT NULL,
|
||||
devType STRING (30),
|
||||
devVendor STRING (250),
|
||||
devFavorite BOOLEAN CHECK (devFavorite IN (0, 1)) DEFAULT (0) NOT NULL,
|
||||
devGroup STRING (10),
|
||||
devComments TEXT,
|
||||
devFirstConnection DATETIME NOT NULL,
|
||||
devLastConnection DATETIME NOT NULL,
|
||||
devLastIP STRING (50) NOT NULL COLLATE NOCASE,
|
||||
devStaticIP BOOLEAN DEFAULT (0) NOT NULL CHECK (devStaticIP IN (0, 1)),
|
||||
devScan INTEGER DEFAULT (1) NOT NULL,
|
||||
devLogEvents BOOLEAN NOT NULL DEFAULT (1) CHECK (devLogEvents IN (0, 1)),
|
||||
devAlertEvents BOOLEAN NOT NULL DEFAULT (1) CHECK (devAlertEvents IN (0, 1)),
|
||||
devAlertDown BOOLEAN NOT NULL DEFAULT (0) CHECK (devAlertDown IN (0, 1)),
|
||||
devSkipRepeated INTEGER DEFAULT 0 NOT NULL,
|
||||
devLastNotification DATETIME,
|
||||
devPresentLastScan BOOLEAN NOT NULL DEFAULT (0) CHECK (devPresentLastScan IN (0, 1)),
|
||||
devIsNew BOOLEAN NOT NULL DEFAULT (1) CHECK (devIsNew IN (0, 1)),
|
||||
devLocation STRING (250) COLLATE NOCASE,
|
||||
devIsArchived BOOLEAN NOT NULL DEFAULT (0) CHECK (devIsArchived IN (0, 1)),
|
||||
devParentMAC TEXT,
|
||||
devParentPort INTEGER,
|
||||
devIcon TEXT,
|
||||
devGUID TEXT,
|
||||
devSite TEXT,
|
||||
devSSID TEXT,
|
||||
devSyncHubNode TEXT,
|
||||
devSourcePlugin TEXT
|
||||
, "devCustomProps" TEXT);
|
||||
CREATE TABLE IF NOT EXISTS "Settings" (
|
||||
"setKey" TEXT,
|
||||
"setName" TEXT,
|
||||
"setDescription" TEXT,
|
||||
"setType" TEXT,
|
||||
"setOptions" TEXT,
|
||||
"setGroup" TEXT,
|
||||
"setValue" TEXT,
|
||||
"setEvents" TEXT,
|
||||
"setOverriddenByEnv" INTEGER
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "Parameters" (
|
||||
"par_ID" TEXT PRIMARY KEY,
|
||||
"par_Value" TEXT
|
||||
);
|
||||
CREATE TABLE Plugins_Objects(
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
SyncHubNodeName TEXT,
|
||||
"HelpVal1" TEXT,
|
||||
"HelpVal2" TEXT,
|
||||
"HelpVal3" TEXT,
|
||||
"HelpVal4" TEXT,
|
||||
ObjectGUID TEXT,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
);
|
||||
CREATE TABLE Plugins_Events(
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
SyncHubNodeName TEXT,
|
||||
"HelpVal1" TEXT,
|
||||
"HelpVal2" TEXT,
|
||||
"HelpVal3" TEXT,
|
||||
"HelpVal4" TEXT, "ObjectGUID" TEXT,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
);
|
||||
CREATE TABLE Plugins_History(
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
SyncHubNodeName TEXT,
|
||||
"HelpVal1" TEXT,
|
||||
"HelpVal2" TEXT,
|
||||
"HelpVal3" TEXT,
|
||||
"HelpVal4" TEXT, "ObjectGUID" TEXT,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
);
|
||||
CREATE TABLE Plugins_Language_Strings(
|
||||
"Index" INTEGER,
|
||||
Language_Code TEXT NOT NULL,
|
||||
String_Key TEXT NOT NULL,
|
||||
String_Value TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
);
|
||||
CREATE TABLE CurrentScan (
|
||||
cur_MAC STRING(50) NOT NULL COLLATE NOCASE,
|
||||
cur_IP STRING(50) NOT NULL COLLATE NOCASE,
|
||||
cur_Vendor STRING(250),
|
||||
cur_ScanMethod STRING(10),
|
||||
cur_Name STRING(250),
|
||||
cur_LastQuery STRING(250),
|
||||
cur_DateTime STRING(250),
|
||||
cur_SyncHubNodeName STRING(50),
|
||||
cur_NetworkSite STRING(250),
|
||||
cur_SSID STRING(250),
|
||||
cur_NetworkNodeMAC STRING(250),
|
||||
cur_PORT STRING(250),
|
||||
cur_Type STRING(250),
|
||||
UNIQUE(cur_MAC)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "AppEvents" (
|
||||
"Index" INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
"GUID" TEXT UNIQUE,
|
||||
"AppEventProcessed" BOOLEAN,
|
||||
"DateTimeCreated" TEXT,
|
||||
"ObjectType" TEXT,
|
||||
"ObjectGUID" TEXT,
|
||||
"ObjectPlugin" TEXT,
|
||||
"ObjectPrimaryID" TEXT,
|
||||
"ObjectSecondaryID" TEXT,
|
||||
"ObjectForeignKey" TEXT,
|
||||
"ObjectIndex" TEXT,
|
||||
"ObjectIsNew" BOOLEAN,
|
||||
"ObjectIsArchived" BOOLEAN,
|
||||
"ObjectStatusColumn" TEXT,
|
||||
"ObjectStatus" TEXT,
|
||||
"AppEventType" TEXT,
|
||||
"Helper1" TEXT,
|
||||
"Helper2" TEXT,
|
||||
"Helper3" TEXT,
|
||||
"Extra" TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "Notifications" (
|
||||
"Index" INTEGER,
|
||||
"GUID" TEXT UNIQUE,
|
||||
"DateTimeCreated" TEXT,
|
||||
"DateTimePushed" TEXT,
|
||||
"Status" TEXT,
|
||||
"JSON" TEXT,
|
||||
"Text" TEXT,
|
||||
"HTML" TEXT,
|
||||
"PublishedVia" TEXT,
|
||||
"Extra" TEXT,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
);
|
||||
CREATE INDEX IDX_eve_DateTime ON Events (eve_DateTime);
|
||||
CREATE INDEX IDX_eve_EventType ON Events (eve_EventType COLLATE NOCASE);
|
||||
CREATE INDEX IDX_eve_MAC ON Events (eve_MAC COLLATE NOCASE);
|
||||
CREATE INDEX IDX_eve_PairEventRowid ON Events (eve_PairEventRowid);
|
||||
CREATE INDEX IDX_ses_EventTypeDisconnection ON Sessions (ses_EventTypeDisconnection COLLATE NOCASE);
|
||||
CREATE INDEX IDX_ses_EventTypeConnection ON Sessions (ses_EventTypeConnection COLLATE NOCASE);
|
||||
CREATE INDEX IDX_ses_DateTimeDisconnection ON Sessions (ses_DateTimeDisconnection);
|
||||
CREATE INDEX IDX_ses_MAC ON Sessions (ses_MAC COLLATE NOCASE);
|
||||
CREATE INDEX IDX_ses_DateTimeConnection ON Sessions (ses_DateTimeConnection);
|
||||
CREATE INDEX IDX_dev_PresentLastScan ON Devices (devPresentLastScan);
|
||||
CREATE INDEX IDX_dev_FirstConnection ON Devices (devFirstConnection);
|
||||
CREATE INDEX IDX_dev_AlertDeviceDown ON Devices (devAlertDown);
|
||||
CREATE INDEX IDX_dev_StaticIP ON Devices (devStaticIP);
|
||||
CREATE INDEX IDX_dev_ScanCycle ON Devices (devScan);
|
||||
CREATE INDEX IDX_dev_Favorite ON Devices (devFavorite);
|
||||
CREATE INDEX IDX_dev_LastIP ON Devices (devLastIP);
|
||||
CREATE INDEX IDX_dev_NewDevice ON Devices (devIsNew);
|
||||
CREATE INDEX IDX_dev_Archived ON Devices (devIsArchived);
|
||||
CREATE VIEW Events_Devices AS
|
||||
SELECT *
|
||||
FROM Events
|
||||
LEFT JOIN Devices ON eve_MAC = devMac
|
||||
/* Events_Devices(eve_MAC,eve_IP,eve_DateTime,eve_EventType,eve_AdditionalInfo,eve_PendingAlertEmail,eve_PairEventRowid,devMac,devName,devOwner,devType,devVendor,devFavorite,devGroup,devComments,devFirstConnection,devLastConnection,devLastIP,devStaticIP,devScan,devLogEvents,devAlertEvents,devAlertDown,devSkipRepeated,devLastNotification,devPresentLastScan,devIsNew,devLocation,devIsArchived,devParentMAC,devParentPort,devIcon,devGUID,devSite,devSSID,devSyncHubNode,devSourcePlugin,devCustomProps) */;
|
||||
CREATE VIEW LatestEventsPerMAC AS
|
||||
WITH RankedEvents AS (
|
||||
SELECT
|
||||
e.*,
|
||||
ROW_NUMBER() OVER (PARTITION BY e.eve_MAC ORDER BY e.eve_DateTime DESC) AS row_num
|
||||
FROM Events AS e
|
||||
)
|
||||
SELECT
|
||||
e.*,
|
||||
d.*,
|
||||
c.*
|
||||
FROM RankedEvents AS e
|
||||
LEFT JOIN Devices AS d ON e.eve_MAC = d.devMac
|
||||
INNER JOIN CurrentScan AS c ON e.eve_MAC = c.cur_MAC
|
||||
WHERE e.row_num = 1
|
||||
/* LatestEventsPerMAC(eve_MAC,eve_IP,eve_DateTime,eve_EventType,eve_AdditionalInfo,eve_PendingAlertEmail,eve_PairEventRowid,row_num,devMac,devName,devOwner,devType,devVendor,devFavorite,devGroup,devComments,devFirstConnection,devLastConnection,devLastIP,devStaticIP,devScan,devLogEvents,devAlertEvents,devAlertDown,devSkipRepeated,devLastNotification,devPresentLastScan,devIsNew,devLocation,devIsArchived,devParentMAC,devParentPort,devIcon,devGUID,devSite,devSSID,devSyncHubNode,devSourcePlugin,devCustomProps,cur_MAC,cur_IP,cur_Vendor,cur_ScanMethod,cur_Name,cur_LastQuery,cur_DateTime,cur_SyncHubNodeName,cur_NetworkSite,cur_SSID,cur_NetworkNodeMAC,cur_PORT,cur_Type) */;
|
||||
CREATE VIEW Sessions_Devices AS SELECT * FROM Sessions LEFT JOIN "Devices" ON ses_MAC = devMac
|
||||
/* Sessions_Devices(ses_MAC,ses_IP,ses_EventTypeConnection,ses_DateTimeConnection,ses_EventTypeDisconnection,ses_DateTimeDisconnection,ses_StillConnected,ses_AdditionalInfo,devMac,devName,devOwner,devType,devVendor,devFavorite,devGroup,devComments,devFirstConnection,devLastConnection,devLastIP,devStaticIP,devScan,devLogEvents,devAlertEvents,devAlertDown,devSkipRepeated,devLastNotification,devPresentLastScan,devIsNew,devLocation,devIsArchived,devParentMAC,devParentPort,devIcon,devGUID,devSite,devSSID,devSyncHubNode,devSourcePlugin,devCustomProps) */;
|
||||
CREATE VIEW Convert_Events_to_Sessions AS SELECT EVE1.eve_MAC,
|
||||
EVE1.eve_IP,
|
||||
EVE1.eve_EventType AS eve_EventTypeConnection,
|
||||
EVE1.eve_DateTime AS eve_DateTimeConnection,
|
||||
CASE WHEN EVE2.eve_EventType IN ('Disconnected', 'Device Down') OR
|
||||
EVE2.eve_EventType IS NULL THEN EVE2.eve_EventType ELSE '<missing event>' END AS eve_EventTypeDisconnection,
|
||||
CASE WHEN EVE2.eve_EventType IN ('Disconnected', 'Device Down') THEN EVE2.eve_DateTime ELSE NULL END AS eve_DateTimeDisconnection,
|
||||
CASE WHEN EVE2.eve_EventType IS NULL THEN 1 ELSE 0 END AS eve_StillConnected,
|
||||
EVE1.eve_AdditionalInfo
|
||||
FROM Events AS EVE1
|
||||
LEFT JOIN
|
||||
Events AS EVE2 ON EVE1.eve_PairEventRowID = EVE2.RowID
|
||||
WHERE EVE1.eve_EventType IN ('New Device', 'Connected','Down Reconnected')
|
||||
UNION
|
||||
SELECT eve_MAC,
|
||||
eve_IP,
|
||||
'<missing event>' AS eve_EventTypeConnection,
|
||||
NULL AS eve_DateTimeConnection,
|
||||
eve_EventType AS eve_EventTypeDisconnection,
|
||||
eve_DateTime AS eve_DateTimeDisconnection,
|
||||
0 AS eve_StillConnected,
|
||||
eve_AdditionalInfo
|
||||
FROM Events AS EVE1
|
||||
WHERE (eve_EventType = 'Device Down' OR
|
||||
eve_EventType = 'Disconnected') AND
|
||||
EVE1.eve_PairEventRowID IS NULL
|
||||
/* Convert_Events_to_Sessions(eve_MAC,eve_IP,eve_EventTypeConnection,eve_DateTimeConnection,eve_EventTypeDisconnection,eve_DateTimeDisconnection,eve_StillConnected,eve_AdditionalInfo) */;
|
||||
CREATE TRIGGER "trg_insert_devices"
|
||||
AFTER INSERT ON "Devices"
|
||||
WHEN NOT EXISTS (
|
||||
SELECT 1 FROM AppEvents
|
||||
WHERE AppEventProcessed = 0
|
||||
AND ObjectType = 'Devices'
|
||||
AND ObjectGUID = NEW.devGUID
|
||||
AND ObjectStatus = CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END
|
||||
AND AppEventType = 'insert'
|
||||
)
|
||||
BEGIN
|
||||
INSERT INTO "AppEvents" (
|
||||
"GUID",
|
||||
"DateTimeCreated",
|
||||
"AppEventProcessed",
|
||||
"ObjectType",
|
||||
"ObjectGUID",
|
||||
"ObjectPrimaryID",
|
||||
"ObjectSecondaryID",
|
||||
"ObjectStatus",
|
||||
"ObjectStatusColumn",
|
||||
"ObjectIsNew",
|
||||
"ObjectIsArchived",
|
||||
"ObjectForeignKey",
|
||||
"ObjectPlugin",
|
||||
"AppEventType"
|
||||
)
|
||||
VALUES (
|
||||
|
||||
lower(
|
||||
hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
|
||||
substr(hex( randomblob(2)), 2) || '-' ||
|
||||
substr('AB89', 1 + (abs(random()) % 4) , 1) ||
|
||||
substr(hex(randomblob(2)), 2) || '-' ||
|
||||
hex(randomblob(6))
|
||||
)
|
||||
,
|
||||
DATETIME('now'),
|
||||
FALSE,
|
||||
'Devices',
|
||||
NEW.devGUID, -- ObjectGUID
|
||||
NEW.devMac, -- ObjectPrimaryID
|
||||
NEW.devLastIP, -- ObjectSecondaryID
|
||||
CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END, -- ObjectStatus
|
||||
'devPresentLastScan', -- ObjectStatusColumn
|
||||
NEW.devIsNew, -- ObjectIsNew
|
||||
NEW.devIsArchived, -- ObjectIsArchived
|
||||
NEW.devGUID, -- ObjectForeignKey
|
||||
'DEVICES', -- ObjectForeignKey
|
||||
'insert'
|
||||
);
|
||||
END;
|
||||
CREATE TRIGGER "trg_update_devices"
|
||||
AFTER UPDATE ON "Devices"
|
||||
WHEN NOT EXISTS (
|
||||
SELECT 1 FROM AppEvents
|
||||
WHERE AppEventProcessed = 0
|
||||
AND ObjectType = 'Devices'
|
||||
AND ObjectGUID = NEW.devGUID
|
||||
AND ObjectStatus = CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END
|
||||
AND AppEventType = 'update'
|
||||
)
|
||||
BEGIN
|
||||
INSERT INTO "AppEvents" (
|
||||
"GUID",
|
||||
"DateTimeCreated",
|
||||
"AppEventProcessed",
|
||||
"ObjectType",
|
||||
"ObjectGUID",
|
||||
"ObjectPrimaryID",
|
||||
"ObjectSecondaryID",
|
||||
"ObjectStatus",
|
||||
"ObjectStatusColumn",
|
||||
"ObjectIsNew",
|
||||
"ObjectIsArchived",
|
||||
"ObjectForeignKey",
|
||||
"ObjectPlugin",
|
||||
"AppEventType"
|
||||
)
|
||||
VALUES (
|
||||
|
||||
lower(
|
||||
hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
|
||||
substr(hex( randomblob(2)), 2) || '-' ||
|
||||
substr('AB89', 1 + (abs(random()) % 4) , 1) ||
|
||||
substr(hex(randomblob(2)), 2) || '-' ||
|
||||
hex(randomblob(6))
|
||||
)
|
||||
,
|
||||
DATETIME('now'),
|
||||
FALSE,
|
||||
'Devices',
|
||||
NEW.devGUID, -- ObjectGUID
|
||||
NEW.devMac, -- ObjectPrimaryID
|
||||
NEW.devLastIP, -- ObjectSecondaryID
|
||||
CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END, -- ObjectStatus
|
||||
'devPresentLastScan', -- ObjectStatusColumn
|
||||
NEW.devIsNew, -- ObjectIsNew
|
||||
NEW.devIsArchived, -- ObjectIsArchived
|
||||
NEW.devGUID, -- ObjectForeignKey
|
||||
'DEVICES', -- ObjectForeignKey
|
||||
'update'
|
||||
);
|
||||
END;
|
||||
CREATE TRIGGER "trg_delete_devices"
|
||||
AFTER DELETE ON "Devices"
|
||||
WHEN NOT EXISTS (
|
||||
SELECT 1 FROM AppEvents
|
||||
WHERE AppEventProcessed = 0
|
||||
AND ObjectType = 'Devices'
|
||||
AND ObjectGUID = OLD.devGUID
|
||||
AND ObjectStatus = CASE WHEN OLD.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END
|
||||
AND AppEventType = 'delete'
|
||||
)
|
||||
BEGIN
|
||||
INSERT INTO "AppEvents" (
|
||||
"GUID",
|
||||
"DateTimeCreated",
|
||||
"AppEventProcessed",
|
||||
"ObjectType",
|
||||
"ObjectGUID",
|
||||
"ObjectPrimaryID",
|
||||
"ObjectSecondaryID",
|
||||
"ObjectStatus",
|
||||
"ObjectStatusColumn",
|
||||
"ObjectIsNew",
|
||||
"ObjectIsArchived",
|
||||
"ObjectForeignKey",
|
||||
"ObjectPlugin",
|
||||
"AppEventType"
|
||||
)
|
||||
VALUES (
|
||||
|
||||
lower(
|
||||
hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
|
||||
substr(hex( randomblob(2)), 2) || '-' ||
|
||||
substr('AB89', 1 + (abs(random()) % 4) , 1) ||
|
||||
substr(hex(randomblob(2)), 2) || '-' ||
|
||||
hex(randomblob(6))
|
||||
)
|
||||
,
|
||||
DATETIME('now'),
|
||||
FALSE,
|
||||
'Devices',
|
||||
OLD.devGUID, -- ObjectGUID
|
||||
OLD.devMac, -- ObjectPrimaryID
|
||||
OLD.devLastIP, -- ObjectSecondaryID
|
||||
CASE WHEN OLD.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END, -- ObjectStatus
|
||||
'devPresentLastScan', -- ObjectStatusColumn
|
||||
OLD.devIsNew, -- ObjectIsNew
|
||||
OLD.devIsArchived, -- ObjectIsArchived
|
||||
OLD.devGUID, -- ObjectForeignKey
|
||||
'DEVICES', -- ObjectForeignKey
|
||||
'delete'
|
||||
);
|
||||
END;
|
||||
end-of-database-schema
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
>&2 echo "Error: Failed to write database schema to ${NETALERTX_DB_FILE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Import the database schema into the new database file
|
||||
sqlite3 "${NETALERTX_DB_FILE}" < "${NETALERTX_DB}/db.sql"
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
# Initialize required directories and log files
|
||||
# These must exist before services start to avoid permission/write errors
|
||||
# TODO - improve with per-directory warning if creation fails
|
||||
[ ! -d "${NETALERTX_PLUGINS_LOG}" ] && mkdir -p "${NETALERTX_PLUGINS_LOG}"
|
||||
[ ! -d "${SYSTEM_SERVICES_RUN_LOG}" ] && mkdir -p "${SYSTEM_SERVICES_RUN_LOG}"
|
||||
[ ! -d "${SYSTEM_SERVICES_RUN_TMP}" ] && mkdir -p "${SYSTEM_SERVICES_RUN_TMP}"
|
||||
[ ! -f "${LOG_DB_IS_LOCKED}" ] && touch "${LOG_DB_IS_LOCKED}"
|
||||
[ ! -f "${LOG_EXECUTION_QUEUE}" ] && touch "${LOG_EXECUTION_QUEUE}"
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
# TODO Add sanity checks here to ensure we can read from
|
||||
# ${NETALERTX_APP}
|
||||
# ${NETALERTX_SERVER}
|
||||
# ${NETALERTX_FRONT}
|
||||
# ${SYSTEM_SERVICES_CONFIG}
|
||||
# ${VIRTUAL_ENV}
|
||||
|
||||
# And read/write tempdirs
|
||||
# ${NETALERTX_API}
|
||||
# ${NETALERTX_LOGS}
|
||||
# ${SYSTEM_SERVICES_RUN}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
# storage-check.sh - Verify critical paths use dedicated mounts.
|
||||
|
||||
warn_if_not_dedicated_mount() {
|
||||
path="$1"
|
||||
if awk -v target="${path}" '$5 == target {found=1} END {exit found ? 0 : 1}' /proc/self/mountinfo; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
failures=1
|
||||
YELLOW=$(printf '\033[1;33m')
|
||||
RESET=$(printf '\033[0m')
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: ${path} is not mounted separately inside this container.
|
||||
|
||||
NetAlertX runs as a single unprivileged process and pounds this directory
|
||||
with writes. Leaving it on the container overlay will thrash storage and
|
||||
slow the stack.
|
||||
|
||||
Fix: mount ${path} explicitly — tmpfs for ephemeral data, or bind/volume if
|
||||
you want to preserve history:
|
||||
--mount type=tmpfs,destination=${path}
|
||||
# or
|
||||
--mount type=bind,src=/path/on/host,dst=${path}
|
||||
|
||||
Apply the mount and restart the container.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
}
|
||||
|
||||
|
||||
# If NETALERTX_DEBUG=1 then we will exit
|
||||
if [ "${NETALERTX_DEBUG}" -eq 1 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
failures=0
|
||||
warn_if_not_dedicated_mount "${NETALERTX_API}"
|
||||
warn_if_not_dedicated_mount "${NETALERTX_LOG}"
|
||||
|
||||
if [ "${failures}" -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "${SYSTEM_NGINIX_CONFIG}/conf.active" ]; then
|
||||
echo "Note: Using default listen address ${LISTEN_ADDR}:${PORT} (no ${SYSTEM_NGINIX_CONFIG}/conf.active override)."
|
||||
fi
|
||||
31
install/production-filesystem/services/scripts/check-root.sh
Normal file
31
install/production-filesystem/services/scripts/check-root.sh
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# check-root.sh - ensure the container is not running as root.
|
||||
|
||||
CURRENT_UID="$(id -u)"
|
||||
|
||||
if [ "${CURRENT_UID}" -eq 0 ]; then
|
||||
YELLOW=$(printf '\033[1;33m')
|
||||
RESET=$(printf '\033[0m')
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<'EOF'
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: NetAlertX is running as root (UID 0).
|
||||
|
||||
This defeats every hardening safeguard built into the image. You just
|
||||
handed a high-value network monitoring appliance full control over your
|
||||
host. If an attacker compromises NetAlertX now, the entire machine goes
|
||||
with it.
|
||||
|
||||
Run the container as the dedicated 'netalertx' user instead:
|
||||
* Keep the default USER in the image (20211:20211), or
|
||||
* In docker-compose.yml, remove any 'user:' override that sets UID 0.
|
||||
|
||||
Bottom line: never run security tooling as root unless you are actively
|
||||
trying to get pwned.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# TODO Sanity checks for storage paths
|
||||
|
||||
# Ensure we can read/write to
|
||||
# ${NETALERTX_CONFIG}
|
||||
# ${NETALERTX_DB}
|
||||
15
install/production-filesystem/services/scripts/cron_script.sh
Executable file
15
install/production-filesystem/services/scripts/cron_script.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
export INSTALL_DIR=/app
|
||||
|
||||
|
||||
|
||||
# Check if there are any entries with cron_restart_backend
|
||||
if grep -q "cron_restart_backend" "${LOG_EXECUTION_QUEUE}"; then
|
||||
# Restart python application using s6
|
||||
killall python3
|
||||
sleep 2
|
||||
/services/start-backend.sh &
|
||||
|
||||
# Remove all lines containing cron_restart_backend from the log file
|
||||
sed -i '/cron_restart_backend/d' "${LOG_EXECUTION_QUEUE}"
|
||||
fi
|
||||
26
install/production-filesystem/services/scripts/update_vendors.sh
Executable file
26
install/production-filesystem/services/scripts/update_vendors.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# NetAlertX
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector
|
||||
#
|
||||
# update_vendors.sh - Back module. IEEE Vendors db update
|
||||
# ------------------------------------------------------------------------------
|
||||
# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Main directories to update:
|
||||
# /usr/share/arp-scan
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# Download the file using wget to stdout and process it
|
||||
wget -q "https://standards-oui.ieee.org/oui/oui.txt" -O /dev/stdout | \
|
||||
sed -E 's/ *\(base 16\)//' | \
|
||||
awk -F' ' '{printf "%s\t%s\n", $1, substr($0, index($0, $2))}' | \
|
||||
sort | \
|
||||
awk '{$1=$1; print}' | \
|
||||
sort -u | \
|
||||
awk -F' ' '{printf "%s\t%s\n", $1, substr($0, index($0, $2))}' \
|
||||
> /services/run/tmp/ieee-oui.txt
|
||||
|
||||
Reference in New Issue
Block a user