[mod] main

This commit is contained in:
roydfalk 2024-08-21 15:07:27 +02:00
parent a47162a8a0
commit 045330759b

View file

@ -3,6 +3,7 @@
*/ */
type type_conf = { type type_conf = {
server : { server : {
host : string;
port : int; port : int;
}; };
authentication : { authentication : {
@ -20,31 +21,35 @@ type type_conf = {
type type_user_list_sparse = ( type type_user_list_sparse = (
null null
| |
Record< {
string, users : Record<
{ string,
disabled ?: boolean; {
displayname ?: string; disabled ?: boolean;
email ?: string; displayname ?: string;
groups ?: Array<string>; email ?: string;
password : string; groups ?: Array<string>;
} password : string;
> }
>;
}
); );
/** /**
*/ */
type type_user_list_complete = Record< type type_user_list_complete = {
string, users : Record<
{ string,
disabled : boolean; {
displayname : string; disabled : boolean;
email : string; displayname : string;
groups : Array<string>; email : string;
password : string; groups : Array<string>;
} password : string;
>; }
>;
};
/** /**
@ -54,41 +59,65 @@ async function conf_get(
) : Promise<type_conf> ) : Promise<type_conf>
{ {
const raw : any = lib_plankton.json.decode(await lib_plankton.file.read(path));; const raw : any = lib_plankton.json.decode(await lib_plankton.file.read(path));;
return { const version_fallback : int = 1;
"server": { if (! ("version" in raw)) {
"port": ((raw["server"] ?? {})["port"] ?? 4466), lib_plankton.log.warning(
}, "conf_version_unspecified",
"authentication": { {
"timestamp_tolerance": (raw["authentication"]["timestamp_tolerance"] ?? 2.0), "assumed_version": version_fallback,
"hash_salt": raw["authentication"]["hash_salt"], // required }
}, );
"authelia": { }
"usersfile_path": ((raw["authelia"] ?? {})["usersfile_path"] ?? "/var/authelia/users.yaml"), else {
}, // do nothing
}; }
const version : int = (raw["version"] ?? version_fallback);
switch (version) {
default: {
throw (new Error("invalid version: " + version.toFixed(0)));
break;
}
case 1: {
return {
"server": {
"host": ((raw["server"] ?? {})["host"] ?? "::"),
"port": ((raw["server"] ?? {})["port"] ?? 7463),
},
"authentication": {
"timestamp_tolerance": (raw["authentication"]["timestamp_tolerance"] ?? 2.0),
"hash_salt": raw["authentication"]["hash_salt"], // required
},
"authelia": {
"usersfile_path": ((raw["authelia"] ?? {})["usersfile_path"] ?? "/var/authelia/users.yaml"),
},
};
break;
}
}
} }
/** /**
*/ */
function encode_user_list( function encode_user_list(
user_list : type_user_list_sparse user_list : (null | type_user_list_sparse)
) : string ) : string
{ {
let output : string = ""; let output : string = "";
Object.entries(user_list ?? {}).forEach( output += "users:\n";
Object.entries((user_list === null) ? {} : user_list.users).forEach(
([key, value]) => { ([key, value]) => {
output += (key + ":\n"); output += (" " + key + ":\n");
output += (" " + "disabled: " + ((value.disabled ?? false) ? "true" : "false") + "\n"); output += (" " + "disabled: " + ((value.disabled ?? false) ? "true" : "false") + "\n");
output += (" " + "displayname: " + (value.displayname ?? key) + "\n"); output += (" " + "displayname: " + (value.displayname ?? key) + "\n");
if ("email" in value) { if ("email" in value) {
output += (" " + "email: " + value.email + "\n"); output += (" " + "email: " + value.email + "\n");
} }
else { else {
// do nothing // do nothing
} }
output += (" " + "groups: " + JSON.stringify(value.groups ?? []) + "\n"); output += (" " + "groups: " + JSON.stringify(value.groups ?? []) + "\n");
output += (" " + "password: " + value.password + "\n"); output += (" " + "password: " + value.password + "\n");
} }
); );
return output; return output;
@ -228,42 +257,52 @@ async function main(
"input_schema": () => ({ "input_schema": () => ({
"nullable": true, "nullable": true,
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": false,
"nullable": false, "properties": {
"type": "object", "users": {
"additionalProperties": false, "nullable": true,
"properties": { "type": "object",
"disabled": { "additionalProperties": {
"nullable": false, "nullable": false,
"type": "boolean", "type": "object",
"additionalProperties": false,
"properties": {
"disabled": {
"nullable": false,
"type": "boolean",
},
"displayname": {
"nullable": false,
"type": "string",
},
"email": {
"nullable": false,
"type": "string",
},
"groups": {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"type": "string"
}
},
"password": {
"nullable": false,
"type": "string",
},
},
"required": [
"password",
]
}, },
"displayname": { "properties": {},
"nullable": false, "required": [],
"type": "string", }
},
"email": {
"nullable": false,
"type": "string",
},
"groups": {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"type": "string"
}
},
"password": {
"nullable": false,
"type": "string",
},
},
"required": [
"password",
]
}, },
"properties": {}, "required": [
"required": [], "users"
]
}), }),
"output_schema": () => ({ "output_schema": () => ({
"nullable": true, "nullable": true,
@ -272,6 +311,13 @@ async function main(
const timestamp_local : float = lib_plankton.base.get_current_timestamp(); const timestamp_local : float = lib_plankton.base.get_current_timestamp();
const timestamp_remote : float = parseFloat(stuff.query_parameters["timestamp"]); const timestamp_remote : float = parseFloat(stuff.query_parameters["timestamp"]);
if (Math.abs(timestamp_local - timestamp_remote) > conf.authentication.timestamp_tolerance) { if (Math.abs(timestamp_local - timestamp_remote) > conf.authentication.timestamp_tolerance) {
lib_plankton.log.notice(
"restriction_access_denied_due_to_invalid_timestamp",
{
"timestamp_local": timestamp_local,
"timestamp_remote": timestamp_remote,
}
);
return false; return false;
} }
else { else {
@ -280,6 +326,14 @@ async function main(
timestamp_remote.toFixed(0) + conf.authentication.hash_salt timestamp_remote.toFixed(0) + conf.authentication.hash_salt
); );
if (authhash_is !== authhash_shall) { if (authhash_is !== authhash_shall) {
lib_plankton.log.notice(
"restriction_access_denied_due_to_mismatching_hashes",
{
"timestamp": timestamp_remote,
"authhash_is": authhash_is,
"authhash_shall": authhash_shall,
}
);
return false; return false;
} }
else { else {
@ -292,6 +346,11 @@ async function main(
conf.authelia.usersfile_path, conf.authelia.usersfile_path,
encode_user_list(stuff.input) encode_user_list(stuff.input)
); );
lib_plankton.log.notice(
"userdata_updated",
{
}
);
return Promise.resolve({ return Promise.resolve({
"status_code": 200, "status_code": 200,
"data": null "data": null
@ -302,15 +361,43 @@ async function main(
} }
const server : lib_plankton.server.type_subject = lib_plankton.server.make( const server : lib_plankton.server.type_subject = lib_plankton.server.make(
conf.server.port,
async (input, metadata) => { async (input, metadata) => {
const http_request : lib_plankton.http.type_request = lib_plankton.http.decode_request(input); const http_request : lib_plankton.http.type_request = lib_plankton.http.decode_request(input.toString());
const http_response : lib_plankton.http.type_response = await lib_plankton.rest.call( return (
rest_subject, lib_plankton.rest.call(
http_request rest_subject,
http_request
)
.catch(
(error) => {
lib_plankton.log.error(
"server_request_processing_failed",
{
"error": String(error),
}
);
return Promise.resolve<lib_plankton.http.type_response>(
{
"version": "HTTP/1.1",
"status_code": 500,
"headers": {},
// @ts-ignore
"body": Buffer.from(""),
}
);
}
)
.then<string>(
(http_response) => {
const output : string = lib_plankton.http.encode_response(http_response);
return Promise.resolve<string>(output);
}
)
); );
const output : string = lib_plankton.http.encode_response(http_response); },
return output; {
"host": conf.server.host,
"port": conf.server.port,
} }
); );