def _get(self, object, name, items): """ return a list of PlatformItem items: follows XML-RPC format """ networks = object.ruleset.resources protocols = object.ruleset.protocols values = [] for item in items: if 'network' in item: network = getUnicode(item['network']) else: raise ValueError("Platform object: missing node 'network' in node 'item'") if 'protocol' in item: protocol = getUnicode(item['protocol']) else: raise ValueError("Platform object: missing node 'protocol' in node 'item'") network = networks[network] protocol = protocols[protocol] values.append(PlatformItem(network, protocol)) if not values: return None return values
def service_rulesetOpen(self, context, filetype, name): """ Open a ruleset or a template (if is_template is True). """ filetype = getUnicode(filetype) name = getUnicode(name) checkRulesetName(name) client = self.getClient(context) logger = ContextLoggerChild(context, self) self.info(context, 'Open the ruleset "%s"' % name) data = yield self.core.callService(self.ufwi_ruleset_context, 'network', 'getNetconfig') netcfg = deserializeNetCfg(data) read_only = not any(context.hasRole(role) for role in RULESET_FORWARD_WRITE_ROLES) if EDENWALL \ and (not read_only) \ and (filetype == "template") \ and (self.core.getMultisiteType() == MULTISITE_SLAVE): read_only = True ruleset = Ruleset(self, logger, netcfg, read_only=read_only, client=client) result = ruleset.load(logger, filetype, name) if not read_only: self.core.lock_manager.acquire(context, LOCK_RULESET) self._saveRuleset(context, ruleset) returnValue(result)
def service_rulesetDownload(self, context, filetype, name): """ Download a ruleset (filetype="ruleset") or a template (ruleset="template"). Return the file content as an encoded byte string, use decodeFileContent() to decode the content. """ name = getUnicode(name) filetype = getUnicode(filetype) self.info(context, 'Download the %s: "%s"' % (filetype, name)) return rulesetDownload(filetype, name)
def service_rulesetDelete(self, context, filetype, name): """ Delete the specified ruleset or template. """ name = getUnicode(name) filetype = getUnicode(filetype) if self.hasRuleset(context): ruleset = self.getRuleset(context) if ruleset.name == name: raise RulesetError(tr("Unable to delete the current rule set!")) rulesetDelete(self.core, filetype, name)
def service_getRules(self, context, rule_type, fusion=None): """ Get all rules. Arguments : - rule_type: possible values are * "acls-ipv4" (IPv4 ACL) * "acls-ipv6" (IPv6 ACL) * "nats" (IPv4 NAT) - fusion (boolean): if True, replace generic networks / user groups by physical networks / user groups Result is list of (chain identifier, list of rules) where chain identifier possible values are: - ACL rules: "INPUT", "OUTPUT", (input, output) where input / output are interface identifiers (eg. ("eth0", "eth2")). - NAT rules: "PREROUTING", "POSTROUTING" See getRule() service for the format of one rule. """ rule_type = getUnicode(rule_type) fusion = self.getFusion(context, fusion) ruleset = self.getRuleset(context) rules = ruleset.getRuleList(rule_type) return rules.exportXMLRPC(fusion)
def service_objectDelete(self, context, lib_name, identifier): """ Delete an object from the library lib_name using its identifier (unicode string). """ identifier = getUnicode(identifier) library = self.getRuleset(context).getLibrary(lib_name) updates = library.delete(identifier) self.saveSession(context) return updates
def service_objectCreate(self, context, library, attr, fusion=None): """ Create a new object in a library from a dict of attributes """ library = getUnicode(library) fusion = self.getFusion(context, fusion) library = self.getRuleset(context).getLibrary(library) result = library.createObject(attr, fusion) self.saveSession(context) return result
def service_getObjects(self, context, library, fusion=None): """ Returns the list of all objects of a library. If fusion is True, merge generic and physical objects. """ library = getUnicode(library) fusion = self.getFusion(context, fusion) ruleset = self.getRuleset(context) library = ruleset.getLibrary(library) return library.exportXMLRPC(fusion)
def service_rulesetUpload(self, context, filetype, filename, content): """ Upload a new ruleset or template: - filetype: "ruleset" or "template" - filename: input filename - content: file content encoded by encodeFileContent() Return the ruleset name. """ filetype = getUnicode(filetype) filename = getUnicode(filename) content = getUnicode(content) self.info(context, 'Upload a new %s: filename="%s"' % (filetype, filename)) logger = ContextLoggerChild(context, self) data = yield self.core.callService(self.ufwi_ruleset_context, 'network', 'getNetconfig') netcfg = deserializeNetCfg(data) result = rulesetUpload(self, logger, filetype, filename, content, netcfg) returnValue(result)
def service_objectTemplatize(self, context, library, identifier, fusion=None): """ Convert an object to a generic. """ identifier = getUnicode(identifier) fusion = self.getFusion(context, fusion) library = self.getRuleset(context).getLibrary(library) object = library[identifier] updates = library.templatize(object, fusion) self.saveSession(context) return updates
def service_rulesetSaveAs(self, context, name): """ Save the ruleset as a new name. See also rulesetSave(). """ name = getUnicode(name) ruleset = self.getRuleset(context) result = ruleset.saveAs(name) self.saveSession(context) return result
def service_resourceCreate(self, context, restype, parent, attr, fusion=None): """ Create new host or network resource (depending on the IP prefix length): - restype: resource type (unicode string) - parent: parent resource identifier (unicode string) - id: resource identifier (unicode string) - argument: IP address for network/host, host name or the interface name (value depends on the resource type) Use parent=address=empty string for a new interface. """ restype = getUnicode(restype) parent = getUnicode(parent) fusion = self.getFusion(context, fusion) resources = self.getRuleset(context).resources updates = resources.serviceCreate(restype, parent, attr, fusion) self.saveSession(context) return updates
def service_rulesetList(self, context, filetype): """ Return the list of: - filetype="ruleset": rulesets - filetype="template": templates Return a list of (name, timestamp) where name and timestamp are unicode string. """ filetype = getUnicode(filetype) return rulesetList(filetype)
def service_setDefaultDecisions(self, context, rule_type, default_decisions): """ Set the default decisions, rule_type is "acls-ipv4" or "acls-ipv6". See getDefaultDecisions() service for the format (dictionary). """ rule_type = getUnicode(rule_type) if rule_type not in ("acls-ipv4", "acls-ipv6"): raise RulesetError(tr("No default decision is associated with %s rules"), rule_type) ruleset = self.getRuleset(context) rules = ruleset.getRuleList(rule_type) action = rules.default_decisions.setDecisions(default_decisions) return ruleset.addAction(action)
def service_removeTemplate(self, context, name): """ Delete the specified template from the current ruleset. All objects from the template are marked as editable and now saved in the ruleset. """ if EDENWALL \ and (self.core.getMultisiteType() == MULTISITE_SLAVE): raise RulesetError(tr("Can not delete a template from a slave.")) name = getUnicode(name) ruleset = self.getRuleset(context) updates = ruleset.removeTemplate(name) self.saveSession(context) return updates
def service_objectModify(self, context, library, identifier, attr, fusion=None): """ Modify an object: - library (unicode): name of the object library (eg. "protocols") - identifier (unicode or int): object identifier (int for rules, unicode for other objects) - attr (dict): object attributes If a (mandatory or optional) attribute is not set in attr, the attribute value is unchanged. """ identifier = getUnicode(identifier) library = getUnicode(library) fusion = self.getFusion(context, fusion) ruleset = self.getRuleset(context) library = ruleset.getLibrary(library) object = library[identifier] updates = library.modifyObject(object, attr, fusion) self.saveSession(context) return updates
def service_getMissingLinks(self, context, filetype, name, links): """ Check if all generic links are defined for the specified ruleset/template "name". Return the list of generic links without physical value as a dictionary. If the dictionary is empty, all generic links are defined. """ name = getUnicode(name) logger = ContextLoggerChild(context, self) data = yield self.core.callService(self.ufwi_ruleset_context, 'network', 'getNetconfig') netcfg = deserializeNetCfg(data) result = getMissingLinks(self, logger, filetype, name, netcfg, links) returnValue(result)
def service_addTemplate(self, context, name): """ Add the specified template to the current ruleset. On duplicate identifiers, objects from the ruleset are renamed with suffix (eg. "Internet" => "Internet-2"). """ if EDENWALL \ and (self.core.getMultisiteType() == MULTISITE_SLAVE): raise RulesetError(tr("Can not add a template from a slave.")) name = getUnicode(name) ruleset = self.getRuleset(context) updates = ruleset.addTemplate(self, name) self.saveSession(context) return updates
def service_groupCreate(self, context, id, library, objects): """ Create a new group of objects: - id : unicode string of the group identifier - library : name of the library that stores this group ("applications", "protocols" ...) - objects: list of object identifiers contained in the group """ id = getUnicode(id) objects = getList(getUnicode, objects) library = self.getRuleset(context).getLibrary(library) attr = {'id': id, 'objects': objects} updates = library.createGroup(attr) self.saveSession(context) return updates
def service_ldapRules(self, context, rule_type, identifiers): """ ldapRules(rule_type, identifiers) Create LDAP rules for ACLs: - identifiers: ACL identifiers (list of integers) - address_type: "IPv4" or "IPv6" Use an empty list as identifiers to generate rules of all ACLs. Result is a list of Unicode strings. """ rule_type = getUnicode(rule_type) identifiers = getIntegerList(identifiers) ruleset = self.getRuleset(context) return ldapRules(context, self, ruleset, rule_type, identifiers)
def service_getDefaultDecisions(self, context, rule_type): """ Get the default decisions, rule_type is "acls-ipv4" or "acls-ipv6". Result is a dictionary chain => (decision, use_log), with: - chain: 'INPUT, 'OUTPUT', or a tuple of the input and output interface identifiers, eg. ('DMZ', 'LAN Interface') - decision: 'ACCEPT', 'DROP' or 'REJECT' - use_log: boolean """ rule_type = getUnicode(rule_type) if rule_type not in ("acls-ipv4", "acls-ipv6"): raise RulesetError(tr("No default decision is associated with %s rules"), rule_type) ruleset = self.getRuleset(context) rules = ruleset.getRuleList(rule_type) return rules.default_decisions.exportXMLRPC()
def service_iptablesRules(self, context, rule_type, identifiers, use_nufw): """ iptablesRules(rule_type, identifiers, use_nufw) Create iptables rules for ACLs: - identifiers: ACL identifiers (list of integers) - address_type: "IPv4" or "IPv6" Use an empty list as identifiers to generate rules of all ACLs. Result is a list of Unicode strings (without "iptables " prefix). """ rule_type = getUnicode(rule_type) identifiers = getIntegerList(identifiers) use_nufw = getBoolean(use_nufw) ruleset = self.getRuleset(context) return iptablesRules(context, self, ruleset, rule_type, identifiers, use_nufw)
def service_getChain(self, context, rule_type, key, fusion=None): """ Get ACLs as a chain where chain is: - (unicode, unicode) for a FORWARD chain, - "INPUT" for the input ACLs - "OUTPUT for the output ACLs Return a list of ACLs. See getRule() service for the format of each ACL. """ ruleset = self.getRuleset(context) if isinstance(key, (tuple, list)): key = getTuple(getUnicode, key) else: key = getUnicode(key) fusion = self.getFusion(context, fusion) rules = ruleset.getRuleList(rule_type) chain = rules.getChain(key) return chain.exportXMLRPC(fusion)
def service_getRule(self, context, rule_type, rule_id, fusion=None): """ Get a ACL or NAT rule. Arguments: - rule_type: possible values are * "acls-ipv4" (IPv4 ACL) * "acls-ipv6" (IPv6 ACL) * "nats" (IPv4 NAT) - rule_id (integer): rule identifier - fusion (boolean): if True, replace generic networks / user groups by physical networks / user groups Result is a dictionary with the following keys. Common keys: - mandatory keys * id (integer): unique rule identifier * mandatory (boolean): True if the rule is mandatory * enabled (boolean): ACL is enabled? (bool) * sources (list of unicode): List of network identifiers * destinations (list of unicode): List of network identifiers - optional keys: * comment (unicode): Comment ACL keys: - mandatory keys: * decision (unicode): 'ACCEPT', 'DROP' or 'REJECT' * protocols (list of unicode): List of protocol identifiers * address_type (unicode): IPV4_ADDRESS or IPV6_ADDRESS * input (unicode): Identifier of the input interface * output (unicode): Identifier of the output interface * chain (unicode): 'INPUT', 'OUTPUT' or 'FORWARD' * log (boolean): Log connections or not? - optional keys: * user_groups (list of unicode): List of user group identifiers * applications (list of unicode): List of application identifiers * operating_systems (list of unicode): List of operating system identifiers * periodicities (list of unicode): List of periodicity identifiers * durations (list of unicode): List of duration identifiers * log_prefix (unciode): Prefix of an log entry NAT keys: - mandatory keys: * filters (list of unicode): List of protocol identifiers * nated_sources (list of unicode): List of translated network identifiers * nated_destinations (list of unicode): List of translated network identifiers * nated_filters (list of unicode): List of translated protocol identifiers * chain (unicode): 'PREROUTING' or 'POSTROUTING' A rule identifier is only unique in its list. Eg. you can have an IPv4 ACL and an IPv6 ACL with the same identifier. Use (rule_type, rule_id) for a global unique identifier. """ rule_type = getUnicode(rule_type) rule_id = getInteger(rule_id) fusion = self.getFusion(context, fusion) rules = self.getRuleset(context).getRuleList(rule_type) rule = rules[rule_id] return rule.exportXMLRPC(fusion)
def service_addFilterRule(self, context, attr): """ Create a filter rule. attr is a dictionary. Mandatory attr keys: - chain: 'INPUT', 'OUTPUT' or 'FORWARD' - decision: 'ACCEPT', 'REJECT' or 'DROP' Optional attr keys: - ipv6: False (IPv4) or True (IPv6), default: False (IPv4) - protocol: layer3 protocol ('ip', 'esp', 'ah') or layer4 protocol ('tcp', 'udp', 'icmp') - dport: tcp/udp destination port number in [0; 65535], eg. 80 - sources: list of source addresses/hostnames, eg. ['0.0.0.0/0', '2000::/3', 'example.com'] - destinations: list of destination addresses/hostnames, eg. ['0.0.0.0/0', '2000::/3', 'example.com'] - input: input interface name, eg. 'eth0' - output: output interface name, eg. 'eth2' Return the number of created rules. The rule will be added before the ruleset rules. """ # Mandatory attributes for key in ('decision', 'chain'): if key not in attr: raise LocalFWError(tr("Missing attribute: %s"), key) chain = getUnicode(attr.pop('chain')) decision = getUnicode(attr.pop('decision')) # Optional attributes if getOptionalDict(getBoolean, attr, 'ipv6', False): address_type = IPV6_ADDRESS else: address_type = IPV4_ADDRESS protocol = getOptionalDict(getUnicode, attr, 'protocol') dport = getOptionalDict(getInteger, attr, 'dport') sources = getAddressList(attr, 'sources', address_type) destinations = getAddressList(attr, 'destinations', address_type) input = getOptionalDict(getUnicode, attr, 'input') output = getOptionalDict(getUnicode, attr, 'output') kw = { 'icmp_type': getOptionalDict(getInteger, attr, 'icmp_type'), 'icmpv6_type': getOptionalDict(getInteger, attr, 'icmpv6_type'), } keys = attr.keys() if keys: raise LocalFWError(tr("Unknown attributes: %s"), ', '.join(keys)) rules = self.getRulesFile(context) for source in sources: for destination in destinations: rule = FilterRule(address_type, chain, protocol, dport, source, destination, input, output, decision, **kw) rules.addFilterRule(rule) self.saveSession(context) return len(sources) * len(destinations)