From 512b8a05273fc52bbb0d4891b0b5e8ca79bf581c Mon Sep 17 00:00:00 2001 From: Abhishek M J Date: Wed, 13 Dec 2023 21:04:07 +0530 Subject: [PATCH] Harden physical-port --- config/sampleconfig.toml | 5 +- docs/physical_ports.md | 5 +- harden/config_file.py | 22 +++++++++ harden/physical_ports.py | 103 +++++++++++++++++---------------------- 4 files changed, 72 insertions(+), 63 deletions(-) create mode 100644 harden/config_file.py diff --git a/config/sampleconfig.toml b/config/sampleconfig.toml index bad38d6..45c8639 100644 --- a/config/sampleconfig.toml +++ b/config/sampleconfig.toml @@ -1,12 +1,11 @@ [physical-ports] enable = true -allow-all = false device-rules = [ - {allow = true, id = "1a2c:4c5e", name = "USB Keyboard", port = "1-2"}, # allow only at that port + {allow = true, id = "1a2c:4c5e", name = "USB Keyboard"}, # allow only at that port {allow = true, id = "04f3:0c00", name = "ELAN:ARM-M4"} ] port-rules = [ - {allow = false, port = "1-3"} # block all devices at that port + {allow = false, id = "1-3"} # block all devices at that port ] [ssh] diff --git a/docs/physical_ports.md b/docs/physical_ports.md index 1e2fab0..175ab97 100644 --- a/docs/physical_ports.md +++ b/docs/physical_ports.md @@ -36,13 +36,12 @@ USBGuard: https://usbguard.github.io/documentation/rule-language.html ```toml [physical-ports] enable = true -allow-all = false device-rules = [ - {allow = true, id = "1a2c:4c5e", name = "USB Keyboard", port = "1-2"}, # allow only at that port + {allow = true, id = "1a2c:4c5e", name = "USB Keyboard"}, # allow only at that port {allow = true, id = "04f3:0c00", name = "ELAN:ARM-M4"} ] port-rules = [ - {allow = false, port = "1-3"} # block all devices at that port + {allow = false, id = "1-3"} # block all devices at that port ] ``` diff --git a/harden/config_file.py b/harden/config_file.py new file mode 100644 index 0000000..4c68c93 --- /dev/null +++ b/harden/config_file.py @@ -0,0 +1,22 @@ +import tomlkit +import os +import shutil +from typing import Mapping + +file_path = os.path.join(os.path.dirname(__file__), "../config/sampleconfig.toml") +temp_file_path = os.path.join(os.path.dirname(file_path), "sampleconfig_copy.toml") +shutil.copyfile(file_path, temp_file_path) + + +def read(): + with open(temp_file_path, "r") as f: + return tomlkit.load(f) + + +def write(config: Mapping): + with open(temp_file_path, "w") as f: + tomlkit.dump(config, f) + + +def save(): + os.replace(temp_file_path, file_path) \ No newline at end of file diff --git a/harden/physical_ports.py b/harden/physical_ports.py index 73f9c6e..e34326f 100644 --- a/harden/physical_ports.py +++ b/harden/physical_ports.py @@ -1,66 +1,55 @@ -# This File Reads the TOML File and Generates the Rules File -from tomlkit import loads -import os +import subprocess +import config_file -# Set file paths -test_directory = os.path.dirname(os.path.abspath(__file__)) -absolute_path = os.path.join(test_directory, '..', 'config', 'sampleconfig.toml') -config_file_path = absolute_path -rules_file_path = os.path.join(test_directory, '..', 'BackEnd', 'rules.conf') +config = config_file.read()["physical-ports"] -# Check if the configuration file exists -if not os.path.exists(config_file_path): - print("Error: Configuration file not found.") - exit(1) -# Define the parse_toml_file function -def parse_toml_file(file_path): - try: - with open(file_path, 'r') as file: - toml_content = file.read() - parsed_data = loads(toml_content) - return parsed_data - except FileNotFoundError: - print(f"Error: File not found at {file_path}") - return None +def _generate_policy(): + return subprocess.check_output( + ["usbguard", "generate-policy"] + ).decode("utf-8") -def ConfUtile(parsed_data,test_directory): - #print(parsed_data) - # Check if the 'enable' key is present and set to True - enable = parsed_data['physical-ports']['enable'] - if not enable: - temp_disable_file = os.path.join(test_directory, 'disable_usbguard.tmp') - with open(temp_disable_file, 'w') as file: - file.write("disable") - # Generate rules based on parsed data - rules_content = "" - allow_all = parsed_data['physical-ports']['allow-all'] - #print(allow_all) - if allow_all: - rules_content = "allow\n" - else: - for rule in parsed_data['physical-ports']['rules']: - for key in rule: - if key == 'allow': - if rule[key]: - rules_content += "allow " - else: - rules_content += "reject " - if 'id' in rule: - rules_content += f"{rule['id']} " - if 'name' in rule: - rules_content += f"name \"{rule['name']}\" " - if 'port' in rule: - rules_content += f"via-port \"{rule['port']}\"\n" - else: - rules_content += "\n" - return rules_content +def get_devices(): + config_rules = config["device-rules"] + devices = {device["id"]: device for device in config_rules} + policy = _generate_policy().splitlines() + rules = filter(lambda x: "via-port" in x, policy) + for rule in rules: + rule_split = rule.split() + device_id = rule_split[rule_split.index("id") + 1] + if device_id in devices: + continue + device_name = rule_split[rule_split.index("name") + 1].strip('"') + devices[device_id] = {"id": device_id, "name": device_name, "allow": True} + + return list(devices.values()) -# Parse the TOML configuration file -parsed_data = parse_toml_file(config_file_path) -rules_content = ConfUtile(parsed_data,test_directory) -print(rules_content) +def get_script(all_config): + config = all_config["physical-ports"] + script = "" + if not config["enable"]: + return "sudo systemctl disable --now usbguard\n" + script += "cat > rules.conf << EOF\n" + + for device in config["device-rules"]: + if not device["allow"]: + continue + script += f"allow id {device['id']} name \"{device['name']}\"\n" + + for port in config["port-rules"]: + script += f"allow via-port \"{port['id']}\"\n" + + script += "EOF\n" + + script += "sudo install -m 0600 -o root -g root rules.conf /etc/usbguard/rules.conf\n" + script += "sudo systemctl restart usbguard\n" + script += "sudo systemctl enable usbguard\n" + + return script + +if __name__ == "__main__": + print(get_script(config_file.read())) \ No newline at end of file