Source code for web

"""
Module to manage Web configuration (Protect -> Web) on Sophos Firewall. 
"""
from sophosfirewall_python.api_client import SophosFirewallAPIError

[docs] class WebFilterPolicy: """ Manages Web Filter Policies """ def __init__(self, api_client): self.api_client = api_client self.xml_tag = "WebFilterPolicy" # Get categories for rules resp = self.api_client.get_tag("WebFilterCategory") self.categories = [category['Name'] for category in resp['Response']['WebFilterCategory']] self.categories.append("All web traffic") # Add default category # Get URL Groups resp = self.api_client.get_tag("WebFilterURLGroup") self.url_groups = [group['Name'] for group in resp['Response']['WebFilterURLGroup']] # Get File Types resp = self.api_client.get_tag("FileType") self.file_types = [file_type['Name'] for file_type in resp['Response']['FileType']] # Get User Activities resp = self.api_client.get_tag("UserActivity") self.user_activities = [activity['Name'] for activity in resp['Response']['UserActivity']]
[docs] def get(self, name=None): """ Retrieves web filter policies. If name is provided, filters by name. Otherwise, retrieves all policies. """ if name: return self.api_client.get_tag_with_filter(self.xml_tag, "Name", name, operator="=") return self.api_client.get_tag(self.xml_tag)
[docs] def create(self, name, default_action, download_file_size_restriction, enable_reporting="Enable", download_file_size_restriction_enabled=None, goog_app_domain_list=None, goog_app_domain_list_enabled=None, youtube_filter_is_strict=None, youtube_filter_enabled=None, enforce_safe_search=None, enforce_image_licensing=None, xff_enabled=None, office_365_tenants_list=None, office_365_directory_id=None, office_365_enabled=None, quota_limit=60, description=None, rules=None, debug: bool = False): """ Creates a new web filter policy. Args: name (str): Specify a name for the Web Filter Policy. Max 50 chars. default_action (str): Default action of the policy ('Allow' or 'Deny'). download_file_size_restriction (int): Specify maximum allowed file download size in MB (0-1536). enable_reporting (str, optional): Select to enable reporting of policy. Defaults to "Enable". (API Default: Enable) download_file_size_restriction_enabled (str, optional): Enable ('1') or disable ('0') checking for maximum allowed file download size. Defaults to None. goog_app_domain_list (str, optional): Comma-separated list of domains allowed to access Google services. Max 256 chars. Defaults to None. goog_app_domain_list_enabled (str, optional): Enable ('1') or disable ('0') specifying domains for Google services. Defaults to None. youtube_filter_is_strict (str, optional): Adjust the policy used for YouTube Restricted Mode ('1' for strict, '0' for moderate). Defaults to None. youtube_filter_enabled (str, optional): Enable ('1') or disable ('0') YouTube Restricted Mode. Defaults to None. enforce_safe_search (str, optional): Enable ('1') or disable ('0') blocking of pornography and explicit content in search results. Defaults to None. enforce_image_licensing (str, optional): Enable ('1') or disable ('0') limiting search results to Creative Commons licensed images. Defaults to None. xff_enabled (str, optional): Enable ('1') or disable ('0') X-Forwarded-For header. Defaults to None. office_365_tenants_list (str, optional): Comma-separated list of domain names and domain IDs allowed to access Microsoft 365. Max 4096 chars. Defaults to None. office_365_directory_id (str, optional): Domain ID allowed to access the Microsoft 365 service. Max 50 chars. Defaults to None. office_365_enabled (str, optional): Turn on ('1') or off ('0') specifying domains/IDs for Microsoft 365. Defaults to None. quota_limit (int, optional): Maximum allowed time (1-1440 minutes) for browsing restricted web content under quota policy action. Defaults to 60. (API Default: 60) description (str, optional): Specify Policy description. Max 255 chars. Defaults to None. rules (list of dict, optional): Specify the rules contained in this policy. Defaults to None. See rule list structure below: - categories (list of dict): List of rule categories containing: - id (str): Category Name - type (str): Category type - http_action (str, optional): HTTP action (Allow/Deny). Defaults to Deny. - https_action (str, optional): HTTPS action (Allow/Deny). Defaults to Deny. - follow_http_action (str, optional): '1' to enable, '0' to disable. Defaults to 1. - schedule (str, optional): Schedule name. Defaults to 'All The Time' - policy_rule_enabled (str, optional): '1' to enable, '0' to disable. Defaults to 1. - ccl_rule_enabled (str, optional): '1' to enable, '0' to disable. Defaults to 0. - user_list (list of str, optional): List of users to apply this rule to. Defaults to None. """ # Ensure rules is a list, even if None is passed if rules is None: rules = [] for rule in rules: if "categories" in rule: for category in rule["categories"]: if category.get("type") == "WebCategory": if not category.get("id") in self.categories: raise SophosFirewallAPIError(f"Category '{category.get('id')}' is not a valid Web Filter Category.") if category.get("type") == "FileType": if not category.get("id") in self.file_types: raise SophosFirewallAPIError(f"File Type '{category.get('id')}' is not a valid File Type.") if category.get("type") == "URLGroup": if not category.get("id") in self.url_groups: raise SophosFirewallAPIError(f"URL Group '{category.get('id')}' is not a valid URL Group.") if category.get("type") == "UserActivity": if not category.get("id") in self.user_activities: raise SophosFirewallAPIError(f"User Activity '{category.get('id')}' is not a valid User Activity.") if category.get("type") not in ["WebCategory", "FileType", "URLGroup", "UserActivity"]: raise SophosFirewallAPIError(f"Category type '{category.get('type')}' is not valid. Must be 'WebCategory', 'FileType', 'URLGroup', or 'UserActivity'.") template_vars = { "name": name, "default_action": default_action, "enable_reporting": enable_reporting, "download_file_size_restriction": download_file_size_restriction, "download_file_size_restriction_enabled": download_file_size_restriction_enabled, "goog_app_domain_list": goog_app_domain_list, "goog_app_domain_list_enabled": goog_app_domain_list_enabled, "youtube_filter_is_strict": youtube_filter_is_strict, "youtube_filter_enabled": youtube_filter_enabled, "enforce_safe_search": enforce_safe_search, "enforce_image_licensing": enforce_image_licensing, "xff_enabled": xff_enabled, "office_365_tenants_list": office_365_tenants_list, "office_365_directory_id": office_365_directory_id, "office_365_enabled": office_365_enabled, "quota_limit": quota_limit, "description": description, "rules": rules } return self.api_client.submit_template( filename="createwebfilterpolicy.j2", template_vars=template_vars, debug=debug )
[docs] def update(self, name, default_action=None, enable_reporting=None, download_file_size_restriction=None, download_file_size_restriction_enabled=None, goog_app_domain_list=None, goog_app_domain_list_enabled=None, youtube_filter_is_strict=None, youtube_filter_enabled=None, enforce_safe_search=None, enforce_image_licensing=None, xff_enabled=None, office_365_tenants_list=None, office_365_directory_id=None, office_365_enabled=None, quota_limit=None, description=None, rules=None, rule_action="add", debug: bool = False): """ Updates an existing web filter policy. Fetches the existing policy and applies changes only for provided arguments. Handles 'add' or 'replace' actions for rules. To remove specific rules, use rule_action='replace' with the desired final list of rules. The full policy object is sent in the update payload. Args: name (str): Specify a name for the Web Filter Policy. Max 50 chars. (Mandatory for identification) default_action (str, optional): Default action of the policy ('Allow' or 'Deny'). enable_reporting (str, optional): Select to enable reporting of policy. download_file_size_restriction (int, optional): Specify maximum allowed file download size in MB (0-1536). download_file_size_restriction_enabled (str, optional): Enable ('1') or disable ('0') checking for maximum allowed file download size. goog_app_domain_list (str, optional): Comma-separated list of domains allowed to access Google services. Max 256 chars. goog_app_domain_list_enabled (str, optional): Enable ('1') or disable ('0') specifying domains for Google services. youtube_filter_is_strict (str, optional): Adjust the policy used for YouTube Restricted Mode ('1' for strict, '0' for moderate). youtube_filter_enabled (str, optional): Enable ('1') or disable ('0') YouTube Restricted Mode. enforce_safe_search (str, optional): Enable ('1') or disable ('0') blocking of pornography and explicit content in search results. enforce_image_licensing (str, optional): Enable ('1') or disable ('0') limiting search results to Creative Commons licensed images. xff_enabled (str, optional): Enable ('1') or disable ('0') X-Forwarded-For header. office_365_tenants_list (str, optional): Comma-separated list of domain names and domain IDs allowed to access Microsoft 365. Max 4096 chars. office_365_directory_id (str, optional): Domain ID allowed to access the Microsoft 365 service. Max 50 chars. office_365_enabled (str, optional): Turn on ('1') or off ('0') specifying domains/IDs for Microsoft 365. quota_limit (int, optional): Maximum allowed time (1-1440 minutes) for browsing restricted web content under quota policy action. description (str, optional): Specify Policy description. Max 255 chars. rules (list of dict, optional): Specify the rules contained in this policy. Defaults to None. See rule list structure below: - categories (list of dict): List of rule categories containing: - id (str): Category Name - type (str): Category type. Valid options are 'WebCategory', 'FileType', 'URLGroup', or 'UserActivity'. - http_action (str, optional): HTTP action (Allow/Deny). Defaults to Deny. - https_action (str, optional): HTTPS action (Allow/Deny). Defaults to Deny. - follow_http_action (str, optional): '1' to enable, '0' to disable. Defaults to 1. - schedule (str, optional): Schedule name. Defaults to 'All The Time' - policy_rule_enabled (str, optional): '1' to enable, '0' to disable. Defaults to 1. - ccl_rule_enabled (str, optional): '1' to enable, '0' to disable. Defaults to 0. - user_list (str, optional): List of users to apply this policy to. Defaults to "None". rule_action (str, optional): Action for rules ('add' or 'replace'). Defaults to "add". """ updated_policy_data = self.get(name=name)['Response'][self.xml_tag] # Update scalar fields if new values are provided if default_action is not None: updated_policy_data["DefaultAction"] = default_action if enable_reporting is not None: updated_policy_data["EnableReporting"] = enable_reporting if download_file_size_restriction is not None: updated_policy_data["DownloadFileSizeRestriction"] = download_file_size_restriction if download_file_size_restriction_enabled is not None: updated_policy_data["DownloadFileSizeRestrictionEnabled"] = download_file_size_restriction_enabled if goog_app_domain_list is not None: updated_policy_data["GoogAppDomainList"] = goog_app_domain_list if goog_app_domain_list_enabled is not None: updated_policy_data["GoogAppDomainListEnabled"] = goog_app_domain_list_enabled if youtube_filter_is_strict is not None: updated_policy_data["YoutubeFilterIsStrict"] = youtube_filter_is_strict if youtube_filter_enabled is not None: updated_policy_data["YoutubeFilterEnabled"] = youtube_filter_enabled if enforce_safe_search is not None: updated_policy_data["EnforceSafeSearch"] = enforce_safe_search if enforce_image_licensing is not None: updated_policy_data["EnforceImageLicensing"] = enforce_image_licensing if xff_enabled is not None: updated_policy_data["XFFEnabled"] = xff_enabled if office_365_tenants_list is not None: updated_policy_data["Office365TenantsList"] = office_365_tenants_list if office_365_directory_id is not None: updated_policy_data["Office365DirectoryId"] = office_365_directory_id if office_365_enabled is not None: updated_policy_data["Office365Enabled"] = office_365_enabled if quota_limit is not None: updated_policy_data["QuotaLimit"] = quota_limit if description is not None: updated_policy_data["Description"] = description # Rules handling rule_list = [] if "RuleList" in updated_policy_data and not rule_action == "replace": # If we are not replacing, keep existing rules if isinstance(updated_policy_data["RuleList"]["Rule"], dict): rule_list = [updated_policy_data["RuleList"]["Rule"]] if isinstance(updated_policy_data["RuleList"]["Rule"], list): rule_list = updated_policy_data["RuleList"]["Rule"] if rules and (rule_action == "add" or rule_action == "replace"): for rule in rules: category_list = [] for category in rule.get("categories", []): if category.get("type") == "WebCategory": if not category.get("id") in self.categories: raise SophosFirewallAPIError(f"Category '{category.get('id')}' is not a valid Web Filter Category.") if category.get("type") == "FileType": if not category.get("id") in self.file_types: raise SophosFirewallAPIError(f"File Type '{category.get('id')}' is not a valid File Type.") if category.get("type") == "URLGroup": if not category.get("id") in self.url_groups: raise SophosFirewallAPIError(f"URL Group '{category.get('id')}' is not a valid URL Group.") if category.get("type") == "UserActivity": if not category.get("id") in self.user_activities: raise SophosFirewallAPIError(f"User Activity '{category.get('id')}' is not a valid User Activity.") if category.get("type") not in ["WebCategory", "FileType", "URLGroup", "UserActivity"]: raise SophosFirewallAPIError(f"Category type '{category.get('type')}' is not valid. Must be 'WebCategory', 'FileType', 'URLGroup', or 'UserActivity'.") category_list.append({ "ID": category.get("id", ""), "type": category.get("type", "") }) rule_list.append({ "CategoryList": {"Category": category_list}, "HTTPAction": rule.get("http_action", "Deny"), "HTTPSAction": rule.get("https_action", "Deny"), "FollowHTTPAction": rule.get("follow_http_action", "1"), "Schedule": rule.get("schedule", "All The Time"), "PolicyRuleEnabled": rule.get("policy_rule_enabled", "1"), "CCLRuleEnabled": rule.get("ccl_rule_enabled", "0"), "UserList": {"User": rule.get("user_list", [])} }) if rule_list: if updated_policy_data.get("RuleList"): updated_policy_data["RuleList"]["Rule"] = rule_list if not updated_policy_data.get("RuleList"): updated_policy_data["RuleList"] = {"Rule": rule_list} return self.api_client.submit_template( filename="updatewebfilterpolicy.j2", template_vars=updated_policy_data, debug=debug )
[docs] class UserActivity: """ Manages User Activities. """ def __init__(self, api_client): self.api_client = api_client self.xml_tag = "UserActivity" # Get categories resp = self.api_client.get_tag("WebFilterCategory") self.categories = [category['Name'] for category in resp['Response']['WebFilterCategory']] self.categories.append("All web traffic") # Add default category # Get URL Groups resp = self.api_client.get_tag("WebFilterURLGroup") self.url_groups = [group['Name'] for group in resp['Response']['WebFilterURLGroup']] # Get File Types resp = self.api_client.get_tag("FileType") self.file_types = [file_type['Name'] for file_type in resp['Response']['FileType']]
[docs] def get(self, name=None): """ Retrieves User Activities. If name is provided, filters by name. Otherwise, retrieves all policies. Args: name (str, optional): Name of the User Activity to filter by. Defaults to None """ if name: return self.api_client.get_tag_with_filter(self.xml_tag, "Name", name, operator="=") return self.api_client.get_tag(self.xml_tag)
[docs] def create(self, name, description: str=None, category_list: list[dict]=None, debug: bool = False): """ Creates a new User Activity. Args: name (str): Specify a name for the User Activity. Max 50 chars. description (str, optional): Specify a description for the User Activity. Defaults to None. category_list (list of dict, optional): List of categories to apply to this User Activity. Defaults to None. Category dict format below: Each category dict should contain: - id (str): Category Name - type (str): Category type. Supports 'web category', 'file type', or 'url group'. """ if category_list: for category in category_list: if category.get("type") == "web category": if not category.get("id") in self.categories: raise SophosFirewallAPIError(f"Category '{category.get('id')}' is not a valid Web Filter Category.") if category.get("type") == "file type": if not category.get("id") in self.file_types: raise SophosFirewallAPIError(f"File Type '{category.get('id')}' is not a valid File Type.") if category.get("type") == "url group": if not category.get("id") in self.url_groups: raise SophosFirewallAPIError(f"URL Group '{category.get('id')}' is not a valid URL Group.") if category.get("type") not in ["web category", "file type", "url group"]: raise SophosFirewallAPIError(f"Category type '{category.get('type')}' is not valid. Must be 'web category', 'file type', or 'url group'.") template_vars = { "name": name, "description": description, "category_list": category_list if category_list else [] } return self.api_client.submit_template( filename="createuseractivity.j2", template_vars=template_vars, debug=debug )