[mod] rename:authelia-calls->arc

This commit is contained in:
roydfalk 2024-08-21 19:47:31 +02:00
parent 045330759b
commit 468ac9a23e
5 changed files with 267 additions and 247 deletions

View file

@ -1,29 +0,0 @@
- siehe `~/projekte/linke/sonstiges/authelia-callbacks`
- Espe macht HTTP-Request zu `callbacks.authelia.linke.sx` mit Nutzerliste als Rumpf (Authentifizierung?)
- submit
- timestamp
- userlist
- authhash (`sha256(timestamp+secret)`)
```
type type_data = Record<
string,
{
disabled : boolean;
displayname : string;
email : string;
groups : Array<string>;
password : string;
}
>;
type type_payload = {
timestamp : int;
authhash : string;
data : type_data;
}
```

34
readme.md Normal file
View file

@ -0,0 +1,34 @@
# ARC
## Beschreibung
- ARC = **A**uthelia **R**emote **C**ontrol
- Dienst zur Steuerung einer [Authelia](https://www.authelia.com/)-Instanz
## Erstellung
### Voraussetzungen
- GNU Make
- NodeJS
### Anweisungen
- `tools/build` ausführen
## Betrieb
### Voraussetzungen
- NodeJS
### Anweisungen
- ins Erzeugnis-Verzeichnis wechseln
- `./arc -h` ausführen
- für die meisten Anwendungsfälle ist es erforderlich eine Konfigurations-Datei anzulegen

View file

@ -170,239 +170,254 @@ async function main(
const conf : type_conf = await conf_get(args.conf_path);
// exec
const rest_subject : lib_plankton.rest.type_rest = lib_plankton.rest.make(
if (args["help"]) {
process.stdout.write(
arg_handler.generate_help(
{
"programname": "arc",
"description": "Authelia Remote Control",
"executable": "arc",
}
)
+
"\n"
);
}
else {
const rest_subject : lib_plankton.rest.type_rest = lib_plankton.rest.make(
{
"title": "authelia-callbacks",
"versioning_method": "header",
"versioning_header_name": "X-Api-Version",
"set_access_control_headers": true,
"authentication": {
"kind": "key_header",
"parameters": {"name": "X-Session-Key"}
},
}
);
{
"title": "authelia-callbacks",
"versioning_method": "header",
"versioning_header_name": "X-Api-Version",
"set_access_control_headers": true,
"authentication": {
"kind": "key_header",
"parameters": {"name": "X-Session-Key"}
},
}
);
{
lib_plankton.rest.register<
null,
string
>
(
rest_subject,
lib_plankton.http.enum_method.get,
"/meta/ping",
{
"description": "sendet ein 'pong' zurück; gedacht um die Erreichbarkeit des Backends zu prüfen",
"input_schema": () => ({
"nullable": true,
}),
"output_schema": () => ({
"nullable": false,
"type": "string",
}),
// "restriction": restriction_none,
"execution": () => {
return Promise.resolve({
"status_code": 200,
"data": "pong",
});
},
}
);
lib_plankton.rest.register<
null,
any
>
(
rest_subject,
lib_plankton.http.enum_method.get,
"/meta/spec",
{
"description": "gibt die API-Spezifikation im OpenAPI-Format aus",
"input_schema": () => ({
"nullable": true,
}),
"output_schema": () => ({
}),
// "restriction": restriction_none,
"execution": () => {
return Promise.resolve({
"status_code": 200,
"data": lib_plankton.rest.to_oas(rest_subject),
});
},
}
);
lib_plankton.rest.register<
type_user_list_sparse,
null
>(
rest_subject,
lib_plankton.http.enum_method.put,
"/users/set",
{
"description": "setzt die Nutzerliste",
"query_parameters": [
{
"name": "timestamp",
"required": true,
"description": "current UNIX timestamp",
lib_plankton.rest.register<
null,
string
>
(
rest_subject,
lib_plankton.http.enum_method.get,
"/meta/ping",
{
"description": "sendet ein 'pong' zurück; gedacht um die Erreichbarkeit des Backends zu prüfen",
"input_schema": () => ({
"nullable": true,
}),
"output_schema": () => ({
"nullable": false,
"type": "string",
}),
// "restriction": restriction_none,
"execution": () => {
return Promise.resolve({
"status_code": 200,
"data": "pong",
});
},
{
"name": "auth",
"required": true,
"description": "authorization string",
}
);
lib_plankton.rest.register<
null,
any
>
(
rest_subject,
lib_plankton.http.enum_method.get,
"/meta/spec",
{
"description": "gibt die API-Spezifikation im OpenAPI-Format aus",
"input_schema": () => ({
"nullable": true,
}),
"output_schema": () => ({
}),
// "restriction": restriction_none,
"execution": () => {
return Promise.resolve({
"status_code": 200,
"data": lib_plankton.rest.to_oas(rest_subject),
});
},
],
"input_schema": () => ({
"nullable": true,
"type": "object",
"additionalProperties": false,
"properties": {
"users": {
"nullable": true,
"type": "object",
"additionalProperties": {
"nullable": false,
}
);
lib_plankton.rest.register<
type_user_list_sparse,
null
>(
rest_subject,
lib_plankton.http.enum_method.put,
"/users/set",
{
"description": "setzt die Nutzerliste",
"query_parameters": [
{
"name": "timestamp",
"required": true,
"description": "current UNIX timestamp",
},
{
"name": "auth",
"required": true,
"description": "authorization string",
},
],
"input_schema": () => ({
"nullable": true,
"type": "object",
"additionalProperties": false,
"properties": {
"users": {
"nullable": true,
"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": {
"additionalProperties": {
"nullable": false,
"type": "object",
"additionalProperties": false,
"properties": {
"disabled": {
"nullable": false,
"type": "string"
}
},
"password": {
"nullable": false,
"type": "string",
"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",
]
},
"required": [
"password",
]
},
"properties": {},
"required": [],
}
},
"required": [
"users"
]
}),
"output_schema": () => ({
"nullable": true,
}),
"restriction": async (stuff) => {
const timestamp_local : float = lib_plankton.base.get_current_timestamp();
const timestamp_remote : float = parseFloat(stuff.query_parameters["timestamp"]);
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,
"properties": {},
"required": [],
}
);
return false;
}
else {
const authhash_is : string = stuff.query_parameters["auth"];
const authhash_shall : string = lib_plankton.sha256.get(
timestamp_remote.toFixed(0) + conf.authentication.hash_salt
);
if (authhash_is !== authhash_shall) {
},
"required": [
"users"
]
}),
"output_schema": () => ({
"nullable": true,
}),
"restriction": async (stuff) => {
const timestamp_local : float = lib_plankton.base.get_current_timestamp();
const timestamp_remote : float = parseFloat(stuff.query_parameters["timestamp"]);
if (Math.abs(timestamp_local - timestamp_remote) > conf.authentication.timestamp_tolerance) {
lib_plankton.log.notice(
"restriction_access_denied_due_to_mismatching_hashes",
"restriction_access_denied_due_to_invalid_timestamp",
{
"timestamp": timestamp_remote,
"authhash_is": authhash_is,
"authhash_shall": authhash_shall,
"timestamp_local": timestamp_local,
"timestamp_remote": timestamp_remote,
}
);
return false;
}
else {
return true;
const authhash_is : string = stuff.query_parameters["auth"];
const authhash_shall : string = lib_plankton.sha256.get(
timestamp_remote.toFixed(0) + conf.authentication.hash_salt
);
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;
}
else {
return true;
}
}
}
},
"execution": async (stuff) => {
await lib_plankton.file.write(
conf.authelia.usersfile_path,
encode_user_list(stuff.input)
);
lib_plankton.log.notice(
"userdata_updated",
{
},
"execution": async (stuff) => {
await lib_plankton.file.write(
conf.authelia.usersfile_path,
encode_user_list(stuff.input)
);
lib_plankton.log.notice(
"userdata_updated",
{
}
);
return Promise.resolve({
"status_code": 200,
"data": null
});
},
}
);
}
const server : lib_plankton.server.type_subject = lib_plankton.server.make(
async (input, metadata) => {
const http_request : lib_plankton.http.type_request = lib_plankton.http.decode_request(input.toString());
return (
lib_plankton.rest.call(
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(""),
}
);
}
);
return Promise.resolve({
"status_code": 200,
"data": null
});
},
)
.then<string>(
(http_response) => {
const output : string = lib_plankton.http.encode_response(http_response);
return Promise.resolve<string>(output);
}
)
);
},
{
"host": conf.server.host,
"port": conf.server.port,
}
);
lib_plankton.server.start(server);
}
const server : lib_plankton.server.type_subject = lib_plankton.server.make(
async (input, metadata) => {
const http_request : lib_plankton.http.type_request = lib_plankton.http.decode_request(input.toString());
return (
lib_plankton.rest.call(
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);
}
)
);
},
{
"host": conf.server.host,
"port": conf.server.port,
}
);
lib_plankton.server.start(server);
return Promise.resolve<void>(undefined);
}

View file

@ -12,7 +12,7 @@ def main():
"-o",
"--output-directory",
type = str,
default = "/tmp/authelia-calls",
default = "/tmp/arc",
metavar = "<output-directory>",
help = "output directory",
)

View file

@ -3,7 +3,7 @@
dir_tools := tools
dir_lib := lib
dir_source := source
dir_temp := /tmp/authelia-calls-temp
dir_temp := /tmp/arc-temp
dir_build := build
@ -19,18 +19,18 @@ cmd_tsc := ${dir_tools}/typescript/node_modules/.bin/tsc
## rules
.PHONY: _default
_default: ${dir_build}/authelia-calls
_default: ${dir_build}/arc
${dir_temp}/authelia-calls-unlinked.js: \
${dir_temp}/arc-unlinked.js: \
${dir_lib}/plankton/plankton.d.ts \
${dir_source}/main.ts
@ ${cmd_log} "compiling …"
@ ${cmd_tsc} --lib es2020 --strict $^ --outFile $@
${dir_build}/authelia-calls: \
${dir_build}/arc: \
${dir_source}/head.js \
${dir_lib}/plankton/plankton.js \
${dir_temp}/authelia-calls-unlinked.js
${dir_temp}/arc-unlinked.js
@ ${cmd_log} "linking …"
@ ${cmd_mkdir} $(dir $@)
@ ${cmd_cat} $^ > $@