diff --git a/imageroot/actions/get-trusted-proxies/20get_trusted_proxies b/imageroot/actions/get-trusted-proxies/20get_trusted_proxies new file mode 100755 index 0000000..e34afb0 --- /dev/null +++ b/imageroot/actions/get-trusted-proxies/20get_trusted_proxies @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +# +# Copyright (C) 2025 Nethesis S.r.l. +# SPDX-License-Identifier: GPL-3.0-or-later +# + +import agent +import json +import sys +import os +import conf_helpers + +def main(): + curconf = conf_helpers.parse_yaml_config("traefik.yaml") + try: + proxies = list(set( + curconf['entryPoints']['http']['forwardedHeaders']["trustedIPs"] + + curconf['entryPoints']['https']['forwardedHeaders']["trustedIPs"] + )) + except KeyError: + proxies = [] + response = { + "proxies": proxies, + "depth": int(os.getenv("PROXIES_DEPTH", 0)) + } + json.dump(response, fp=sys.stdout) + +if __name__ == "__main__": + main() diff --git a/imageroot/actions/get-trusted-proxies/validate-output.json b/imageroot/actions/get-trusted-proxies/validate-output.json new file mode 100644 index 0000000..1af46b6 --- /dev/null +++ b/imageroot/actions/get-trusted-proxies/validate-output.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "set-trusted-proxies output", + "$id": "http://schema.nethserver.org/traefik/set-trusted-proxies-output.json", + "description": "Get the IP addresses that are trusted as front-end proxies", + "examples": [ + { + "proxies": [ + "192.168.1.1", + "192.168.1.2" + ] + } + ], + "type": "object", + "required": [ + "proxies" + ], + "additionalProperties": false, + "properties": { + "depth": { + "type":"integer", + "minimum": 0 + }, + "proxies": { + "type": "array", + "items": { + "type": "string" + } + } + } +} diff --git a/imageroot/actions/set-trusted-proxies/20set_trusted_proxies b/imageroot/actions/set-trusted-proxies/20set_trusted_proxies new file mode 100755 index 0000000..c173f33 --- /dev/null +++ b/imageroot/actions/set-trusted-proxies/20set_trusted_proxies @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 + +# +# Copyright (C) 2025 Nethesis S.r.l. +# SPDX-License-Identifier: GPL-3.0-or-later +# + +import agent +import json +import sys +import conf_helpers +import ipaddress + +def main(): + request = json.load(sys.stdin) + validate_request(request) + curconf = conf_helpers.parse_yaml_config("traefik.yaml") + curconf['entryPoints']['http'].setdefault('forwardedHeaders', {"trustedIPs": []}) + curconf['entryPoints']['https'].setdefault('forwardedHeaders', {"trustedIPs": []}) + curconf['entryPoints']['http']['forwardedHeaders']["trustedIPs"] = request['proxies'] + curconf['entryPoints']['https']['forwardedHeaders']["trustedIPs"] = request['proxies'] + conf_helpers.write_yaml_config(curconf, "traefik.yaml") + if len(request['proxies']) > 0: + agent.set_env('PROXIES_DEPTH', str(request.get('depth', 1))) + else: + agent.set_env('PROXIES_DEPTH', '0') + agent.run_helper("systemctl", "--user", "restart", "traefik.service").check_returncode() + +def validate_request(request): + for ipvalue in request['proxies']: + # Check if ipvalue is a string representing IPv4 or IPv6 + try: + # IP validation + ipaddress.ip_address(ipvalue) + except ValueError: + agent.set_status('validation-failed') + json.dump([{'field':'proxies','parameter':'proxies','value': ipvalue,'error':'bad_ip_address'}], fp=sys.stdout) + sys.exit(3) + +if __name__ == "__main__": + main() diff --git a/imageroot/actions/set-trusted-proxies/validate-input.json b/imageroot/actions/set-trusted-proxies/validate-input.json new file mode 100644 index 0000000..e30e788 --- /dev/null +++ b/imageroot/actions/set-trusted-proxies/validate-input.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "set-trusted-proxies input", + "$id": "http://schema.nethserver.org/traefik/set-trusted-proxies-input.json", + "description": "Set the IP addresses that are trusted as front-end proxies", + "examples": [ + { + "depth": 1, + "proxies": [ + "192.168.1.1", + "192.168.1.2" + ] + } + ], + "type": "object", + "required": [ + "proxies" + ], + "additionalProperties": false, + "properties": { + "depth": { + "type":"integer", + "minimum": 0 + }, + "proxies": { + "type": "array", + "items": { + "type": "string" + } + } + } +} diff --git a/imageroot/pypkg/conf_helpers.py b/imageroot/pypkg/conf_helpers.py new file mode 100644 index 0000000..897bddb --- /dev/null +++ b/imageroot/pypkg/conf_helpers.py @@ -0,0 +1,20 @@ +# +# Copyright (C) 2025 Nethesis S.r.l. +# SPDX-License-Identifier: GPL-3.0-or-later +# + +import os +import re +import yaml + +def write_yaml_config(conf, path): + """Safely write a configuration file.""" + with open(path + '.tmp', 'w') as fp: + fp.write(yaml.safe_dump(conf, default_flow_style=False, sort_keys=False, allow_unicode=True)) + os.rename(path + '.tmp', path) + +def parse_yaml_config(path): + """Parse a YAML configuration file.""" + with open(path, 'r') as fp: + conf = yaml.safe_load(fp) + return conf diff --git a/imageroot/systemd/user/traefik.service b/imageroot/systemd/user/traefik.service index cdbd017..44dad0f 100644 --- a/imageroot/systemd/user/traefik.service +++ b/imageroot/systemd/user/traefik.service @@ -14,6 +14,7 @@ ExecStart=/usr/bin/podman run \ --cgroups=no-conmon \ --network=host \ --replace --name=%N \ + --env=PROXIES_DEPTH \ --volume=./acme:/etc/traefik/acme:z \ --volume=./traefik.yaml:/etc/traefik/traefik.yaml:z \ --volume=./selfsigned.crt:/etc/traefik/selfsigned.crt:z \ diff --git a/imageroot/update-module.d/11dir_structure b/imageroot/update-module.d/11dir_structure index c37969f..7615ad3 100755 --- a/imageroot/update-module.d/11dir_structure +++ b/imageroot/update-module.d/11dir_structure @@ -1,11 +1,9 @@ -#!/usr/bin/env sh +#!/bin/bash # -# Copyright (C) 2023 Nethesis S.r.l. +# Copyright (C) 2025 Nethesis S.r.l. # SPDX-License-Identifier: GPL-3.0-or-later # -set -e - -# Update from 0.0.12 -mkdir -vp custom_certificates configs +# Placeholder, see bug NethServer/dev#7058 +exit 0 diff --git a/imageroot/update-module.d/30upgrade_to_beta2 b/imageroot/update-module.d/30upgrade_to_beta2 index 964eb4e..7615ad3 100755 --- a/imageroot/update-module.d/30upgrade_to_beta2 +++ b/imageroot/update-module.d/30upgrade_to_beta2 @@ -1,12 +1,9 @@ #!/bin/bash # -# Copyright (C) 2023 Nethesis S.r.l. +# Copyright (C) 2025 Nethesis S.r.l. # SPDX-License-Identifier: GPL-3.0-or-later # -# Create static configuration, ignore warnings -~/.config/actions/create-module/10expandconfig 2>/dev/null -~/.config/actions/create-module/50create 2>/dev/null -# Convert existing configuration to yaml -~/.config/bin/redis2yml ${MODULE_ID} +# Placeholder, see bug NethServer/dev#7058 +exit 0