core/source/logic/check_kinds/file_state.ts
2024-07-02 15:02:35 +02:00

398 lines
8.7 KiB
TypeScript

/*
Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
<info@greenscale.de>
»heimdall« is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
»heimdall« is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with »heimdall«. If not, see <http://www.gnu.org/licenses/>.
*/
namespace _heimdall.check_kinds.file_state
{
/**
*/
function parameters_schema(
) : _heimdall.helpers.json_schema.type_schema
{
return {
"type": "object",
"additionalProperties": false,
"properties": {
"path": {
"type": "string"
},
"exist_mode": {
"description": "whether the file is supposed to exist or not",
"type": "boolean",
"default": true,
},
"exist_critical": {
"description": "whether a violation of the extist state (parameter 'exist_mode') shall be considered as critical (true) or concerning (false)",
"type": "boolean",
"default": true,
},
"age_threshold_concerning": {
"description": "in seconds; ignored if 'exist_mode' is set to false",
"anyOf": [
{
"type": "null",
},
{
"type": "integer",
"exclusiveMinimum": 0,
},
],
"default": null,
},
"age_threshold_critical": {
"description": "in seconds; ignored if 'exist_mode' is set to false",
"anyOf": [
{
"type": "null",
},
{
"type": "integer",
"exclusiveMinimum": 0,
},
],
"default": null,
},
"size_threshold_concerning": {
"description": "in bytes; ignored if 'exist_mode' is set to false",
"anyOf": [
{
"type": "null",
},
{
"type": "integer",
"exclusiveMinimum": 0,
},
],
"default": null,
},
"size_threshold_critical": {
"description": "in bytes; ignored if 'exist_mode' is set to false",
"anyOf": [
{
"type": "null",
},
{
"type": "integer",
"exclusiveMinimum": 0,
},
],
"default": null,
},
// deprecated
"strict": {
"deprecated": true,
"description": "",
"type": "boolean",
"default": true,
},
"exist": {
"deprecated": true,
"description": "",
"type": "boolean",
"default": true,
},
"age_threshold": {
"deprecated": true,
"description": "",
"anyOf": [
{
"type": "null",
},
{
"type": "integer",
"exclusiveMinimum": 0,
},
],
"default": null,
},
"size_threshold": {
"deprecated": true,
"description": "",
"anyOf": [
{
"type": "null",
},
{
"type": "integer",
"exclusiveMinimum": 0,
},
],
"default": null,
},
},
"required": [
"path",
]
};
}
/**
*/
function normalize_order_node(
node : any
) : any
{
const version : string = (
(! ("exist_mode" in node))
? "v1"
: "v2"
);
switch (version) {
default: {
throw (new Error("unhandled version"));
break;
}
case "v1": {
if (! ("path" in node)) {
throw new Error("missing mandatory field 'path'");
}
else {
const node_ = Object.assign(
{
"strict": true,
"exist": true,
"age_threshold": null,
"size_threshold": null,
},
node
);
return {
"path": node["path"],
"exist_mode": node_["exist"],
"exist_critical": node_["strict"],
"age_threshold_concerning": (
node_["strict"]
? null
: node_["age_threshold"]
),
"age_threshold_critical": (
node_["strict"]
? node_["age_threshold"]
: null
),
"size_threshold_concerning": (
node_["strict"]
? null
: node_["age_threshold"]
),
"size_threshold_critical": (
node_["strict"]
? node_["age_threshold"]
: null
),
};
}
break;
}
case "v2": {
if (! ("path" in node)) {
throw new Error("missing mandatory field 'path'");
}
else {
const node_ = Object.assign(
{
"exist_mode": true,
"exist_critical": true,
"age_threshold_concerning": null,
"age_threshold_critical": null,
"size_threshold_concerning": null,
"size_threshold_critical": null,
},
node
);
return node_;
}
break;
}
}
}
/**
*/
async function run(
parameters
) : Promise<_heimdall.type_result>
{
const nm_fs = require("fs");
let condition : _heimdall.enum_condition = _heimdall.enum_condition.ok;
let faults : Array<string> = [];
let data : Record<string, any> = {};
let exists : boolean;
let stats : {
ctime : float;
size : int;
};
await new Promise<void>(
(resolve, reject) => {
nm_fs.stat(
parameters["path"],
{
"bigint": false,
},
(err, stats_) => {
if (err) {
exists = false;
stats = null;
resolve(undefined);
}
else {
exists = true;
stats = stats_;
resolve(undefined);
}
}
);
}
);
if (! parameters["exist_mode"]) {
if (exists) {
condition = (
parameters["exist_critical"]
? _heimdall.enum_condition.concerning
: _heimdall.enum_condition.critical
);
faults.push(lib_plankton.translate.get("checks.file_state.exists"));
}
else {
// do nothing
}
}
else {
if (! exists) {
condition = (
parameters["exist_critical"]
? _heimdall.enum_condition.concerning
: _heimdall.enum_condition.critical
);
faults.push(lib_plankton.translate.get("checks.file_state.missing"));
}
else {
// age
{
const timestamp_this : int = _heimdall.get_current_timestamp();
const timestamp_that : int = Math.floor(stats.ctime);
const age : int = (timestamp_this - timestamp_that);
if (age < 0) {
condition = _heimdall.enum_condition.critical;
faults.push(lib_plankton.translate.get("checks.file_state.timestamp_implausible"));
}
else {
if (
(parameters["age_threshold_critical"] !== null)
&&
(age > parameters["age_threshold_critical"])
) {
condition = _heimdall.enum_condition.critical;
faults.push(lib_plankton.translate.get("checks.file_state.too_old"));
}
else {
if (
(parameters["age_threshold_concerning"] !== null)
&&
(age > parameters["age_threshold_concerning"])
) {
condition = _heimdall.enum_condition.critical;
faults.push(lib_plankton.translate.get("checks.file_state.too_old"));
}
else {
// do nothing
}
}
}
data = Object.assign(
data,
{
"timestamp_of_checking_instance": timestamp_this,
"timestamp_of_file": timestamp_that,
"age_value_in_seconds": age,
"age_threshold_in_seconds_concerning": parameters["age_threshold_concerning"],
"age_threshold_in_seconds_critical": parameters["age_threshold_critical"],
}
);
}
// size
{
const size : int = stats.size;
if (size < 0) {
condition = _heimdall.enum_condition.critical;
faults.push(lib_plankton.translate.get("checks.file_state.size_implausible"));
}
else {
if (
(parameters["size_threshold_critical"] !== null)
&&
(size > parameters["size_threshold_critical"])
) {
condition = _heimdall.enum_condition.critical;
faults.push(lib_plankton.translate.get("checks.file_state.too_big"));
}
else {
if (
(parameters["size_threshold_concerning"] !== null)
&&
(size > parameters["size_threshold_concerning"])
) {
condition = _heimdall.enum_condition.critical;
faults.push(lib_plankton.translate.get("checks.file_state.too_big"));
}
else {
// do nothing
}
}
}
data = Object.assign(
data,
{
"size_value_in_bytes": size,
"size_threshold_in_bytes": parameters["size_threshold"],
}
);
}
}
}
return {
"condition": condition,
"info": {
"path": parameters["path"],
"faults": faults,
"data": data,
}
};
}
/**
*/
register_implementation(
"file_state",
{
"parameters_schema": parameters_schema,
"normalize_order_node": normalize_order_node,
"run": run,
}
);
}