import requests
import json
import logging
import argparse
import warnings
from urllib3.exceptions import InsecureRequestWarning
warnings.filterwarnings("ignore", category=InsecureRequestWarning)
# Set up command-line argument parsing
parser = argparse.ArgumentParser(description='Toggle the status of an OPNsense Traffic Shaper rule or show its current status.')
parser.add_argument('action', choices=['enable', 'disable', 'show'], help='Action to perform on the rule (enable, disable, or show status).')
parser.add_argument('rule_uuid', help='UUID of the rule to modify or view.', nargs='?') # Make rule_uuid optional for show action
args = parser.parse_args()
# Initialize logging
LOG_FILE_PATH = '/root/shaper.log'
logging.basicConfig(filename=LOG_FILE_PATH, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
API_KEY = 'YOUR_KEY'
API_SECRET = 'YOUR_SECRET'
OPNSENSE_URL = 'https://127.0.0.1/api'
def get_rule_status(rule_uuid):
"""Retrieve the current status of a rule."""
url = f"{OPNSENSE_URL}/trafficshaper/settings/getRule/{rule_uuid}"
auth = (API_KEY, API_SECRET)
response = requests.get(url, auth=auth, verify=False)
if response.ok:
rule_data = response.json()
enabled = rule_data['rule']['enabled'] == '1'
return enabled
else:
logging.error(f"Failed to retrieve rule status, status code: {response.status_code}, response content: {response.text}")
return None
def toggle_rule(rule_uuid, enable):
"""Toggle the status of a specified Traffic Shaper rule to either enable or disable."""
url = f"{OPNSENSE_URL}/trafficshaper/settings/toggleRule"
headers = {'Content-Type': 'application/json'}
data = {"uuid": rule_uuid, "enabled": "1" if enable else "0"}
auth = (API_KEY, API_SECRET)
action = 'enable' if enable else 'disable'
logging.info(f"Attempting to {action} rule: {rule_uuid}")
response = requests.post(url, headers=headers, data=json.dumps(data), auth=auth, verify=False)
if response.ok:
logging.info(f"Rule {rule_uuid} successfully {action}d.")
else:
logging.error(f"Failed to {action} rule, status code: {response.status_code}, response content: {response.text}")
def show_rule_status(rule_uuid):
"""Show the enable/disable status of a specified Traffic Shaper rule."""
enabled = get_rule_status(rule_uuid)
if enabled is not None:
status = 'enabled' if enabled else 'disabled'
logging.info(f"Rule {rule_uuid} is currently {status}.")
print(f"Rule {rule_uuid} is currently {status}.")
else:
print("Failed to retrieve rule status.")
# Determine action
if args.action == 'show':
if args.rule_uuid:
show_rule_status(args.rule_uuid)
else:
logging.error("Rule UUID is required for 'show' action.")
elif args.rule_uuid:
if args.action in ['enable', 'disable']:
enable = args.action == 'enable'
toggle_rule(args.rule_uuid, enable)
else:
logging.error("Invalid action provided. Use 'enable', 'disable', or 'show'.")
else:
logging.error("Rule UUID is required for 'enable' or 'disable' actions.")
python3 shaper.py -h
usage: shaper.py [-h] {enable,disable,show} [rule_uuid]
Toggle the status of an OPNsense Traffic Shaper rule or show its current status.
positional arguments:
{enable,disable,show}
Action to perform on the rule (enable, disable, or show status).
rule_uuid UUID of the rule to modify or view.
optional arguments:
-h, --help show this help message and exit
The show function works fine,but the enable and disable can not work,the error is:
2024-02-27 20:58:22,402 - ERROR - Failed to enable rule, status code: 400, response content: {"message":"action toggleRule expects at least 1 parameter(s)","status":400}
How can I fix it ?
Looks like it expects the rule UUID, you can get it from /conf/config.xml - TrafficShaper section
python3 shaper.py disable 63c924d0-794e-4976-9bf0-e171e3911d29
I've input the uuid to the script,but it return the error.
Quote
2024-02-27 20:58:22,402 - ERROR - Failed to enable rule, status code: 400, response content: {"message":"action toggleRule expects at least 1 parameter(s)","status":400}
The show command works fine.
Quote
python3 shaper.py show 63c924d0-794e-4976-9bf0-e171e3911d29
Rule 63c924d0-794e-4976-9bf0-e171e3911d29 is currently enabled.
Probably best to open a Github issue then