Exemplo n.º 1
0
class GoAmlParser():
    def __init__(self):
        self.misp_event = MISPEvent()

    def read_xml(self, data):
        self.tree = ET.fromstring(data)

    def parse_xml(self):
        self.first_itteration()
        for t in self.tree.findall('transaction'):
            self.itterate(t, 'transaction')

    def first_itteration(self):
        submission_date = self.tree.find('submission_date').text.split('+')[0]
        self.misp_event.timestamp = int(
            time.mktime(time.strptime(submission_date, "%Y-%m-%dT%H:%M:%S")))
        for node in goAMLobjects['report']['nodes']:
            element = self.tree.find(node)
            if element is not None:
                self.itterate(element, element.tag)

    def itterate(self,
                 tree,
                 aml_type,
                 referencing_uuid=None,
                 relationship_type=None):
        objects = goAMLobjects[aml_type]
        referenced_uuid = referencing_uuid
        rel = relationship_type
        if aml_type not in nodes_to_ignore:
            try:
                mapping = goAMLmapping[aml_type]
                misp_object = MISPObject(name=mapping['misp_name'])
                for leaf in objects['leaves']:
                    element = tree.find(leaf)
                    if element is not None:
                        object_relation = mapping[element.tag]
                        attribute = {
                            'object_relation': object_relation,
                            'value': element.text
                        }
                        misp_object.add_attribute(**attribute)
                if aml_type == 'transaction':
                    for node in objects['nodes']:
                        element = tree.find(node)
                        if element is not None:
                            self.fill_transaction(element, element.tag,
                                                  misp_object)
                self.misp_event.add_object(misp_object)
                last_object = self.misp_event.objects[-1]
                referenced_uuid = last_object.uuid
                if referencing_uuid and relationship_type:
                    referencing_object = self.misp_event.get_object_by_uuid(
                        referencing_uuid)
                    referencing_object.add_reference(referenced_uuid, rel,
                                                     None, **last_object)
            except KeyError:
                pass
        for node in objects['nodes']:
            element = tree.find(node)
            if element is not None:
                tag = element.tag
                if tag in relationship_to_keep:
                    rel = tag[2:] if tag.startswith('t_') else tag
                self.itterate(element,
                              element.tag,
                              referencing_uuid=referenced_uuid,
                              relationship_type=rel)

    @staticmethod
    def fill_transaction(element, tag, misp_object):
        if 't_from' in tag:
            from_funds = element.find('from_funds_code').text
            from_funds_attribute = {
                'object_relation': 'from-funds-code',
                'value': from_funds
            }
            misp_object.add_attribute(**from_funds_attribute)
            from_country = element.find('from_country').text
            from_country_attribute = {
                'object_relation': 'from-country',
                'value': from_country
            }
            misp_object.add_attribute(**from_country_attribute)
        if 't_to' in tag:
            to_funds = element.find('to_funds_code').text
            to_funds_attribute = {
                'object_relation': 'to-funds-code',
                'value': to_funds
            }
            misp_object.add_attribute(**to_funds_attribute)
            to_country = element.find('to_country').text
            to_country_attribute = {
                'object_relation': 'to-country',
                'value': to_country
            }
            misp_object.add_attribute(**to_country_attribute)
Exemplo n.º 2
0
class GoAmlGeneration(object):
    def __init__(self, config):
        self.config = config
        self.parsed_uuids = defaultdict(list)

    def from_event(self, event):
        self.misp_event = MISPEvent()
        self.misp_event.load(event)

    def parse_objects(self):
        uuids = defaultdict(list)
        report_code = []
        currency_code = []
        for obj in self.misp_event.objects:
            obj_type = obj.name
            uuids[obj_type].append(obj.uuid)
            if obj_type == 'bank-account':
                try:
                    report_code.append(
                        obj.get_attributes_by_relation('report-code')
                        [0].value.split(' ')[0])
                    currency_code.append(
                        obj.get_attributes_by_relation('currency-code')
                        [0].value)
                except:
                    print('report_code or currency_code error')
        self.uuids, self.report_codes, self.currency_codes = uuids, report_code, currency_code

    def build_xml(self):
        self.xml = {
            'header':
            "<report><rentity_id>{}</rentity_id><submission_code>E</submission_code>"
            .format(self.config),
            'data':
            ""
        }
        if "STR" in self.report_codes:
            report_code = "STR"
        else:
            report_code = Counter(self.report_codes).most_common(1)[0][0]
        self.xml['header'] += "<report_code>{}</report_code>".format(
            report_code)
        submission_date = str(self.misp_event.timestamp).replace(' ', 'T')
        self.xml['header'] += "<submission_date>{}</submission_date>".format(
            submission_date)
        self.xml[
            'header'] += "<currency_code_local>{}</currency_code_local>".format(
                Counter(self.currency_codes).most_common(1)[0][0])
        for trans_uuid in self.uuids.get('transaction'):
            self.itterate('transaction', 'transaction', trans_uuid, 'data')
        person_to_parse = [
            person_uuid for person_uuid in self.uuids.get('person')
            if person_uuid not in self.parsed_uuids.get('person')
        ]
        if len(person_to_parse) == 1:
            self.itterate('person', 'reporting_person', person_to_parse[0],
                          'header')
        try:
            location_to_parse = [
                location_uuid
                for location_uuid in self.uuids.get('geolocation')
                if location_uuid not in self.parsed_uuids.get('geolocation')
            ]
            if len(location_to_parse) == 1:
                self.itterate('geolocation', 'location', location_to_parse[0],
                              'header')
        except TypeError:
            pass
        self.xml['data'] += "</report>"

    def itterate(self, object_type, aml_type, uuid, xml_part):
        obj = self.misp_event.get_object_by_uuid(uuid)
        if object_type == 'transaction':
            self.xml[xml_part] += "<{}>".format(aml_type)
            self.fill_xml_transaction(object_type, obj.attributes, xml_part)
            self.parsed_uuids[object_type].append(uuid)
            if obj.ObjectReference:
                self.parseObjectReferences(object_type, xml_part,
                                           obj.ObjectReference)
            self.xml[xml_part] += "</{}>".format(aml_type)
        else:
            if 'to_' in aml_type or 'from_' in aml_type:
                relation_type = aml_type.split('_')[0]
                self.xml[
                    xml_part] += "<{0}_funds_code>{1}</{0}_funds_code>".format(
                        relation_type, self.from_and_to_fields[relation_type]
                        ['funds'].split(' ')[0])
                self.itterate_normal_case(object_type, obj, aml_type, uuid,
                                          xml_part)
                self.xml[xml_part] += "<{0}_country>{1}</{0}_country>".format(
                    relation_type,
                    self.from_and_to_fields[relation_type]['country'])
            else:
                self.itterate_normal_case(object_type, obj, aml_type, uuid,
                                          xml_part)

    def itterate_normal_case(self, object_type, obj, aml_type, uuid, xml_part):
        self.xml[xml_part] += "<{}>".format(aml_type)
        self.fill_xml(object_type, obj, xml_part)
        self.parsed_uuids[object_type].append(uuid)
        if obj.ObjectReference:
            self.parseObjectReferences(object_type, xml_part,
                                       obj.ObjectReference)
        self.xml[xml_part] += "</{}>".format(aml_type)

    def parseObjectReferences(self, object_type, xml_part, references):
        for ref in references:
            next_uuid = ref.referenced_uuid
            next_object_type = ref.Object.get('name')
            relationship_type = ref.relationship_type
            self.parse_references(object_type, next_object_type, next_uuid,
                                  relationship_type, xml_part)

    def fill_xml_transaction(self, object_type, attributes, xml_part):
        from_and_to_fields = {'from': {}, 'to': {}}
        for attribute in attributes:
            object_relation = attribute.object_relation
            attribute_value = attribute.value
            if object_relation == 'date-posting':
                self.xml[xml_part] += "<late_deposit>True</late_deposit>"
            elif object_relation in ('from-funds-code', 'to-funds-code'):
                relation_type, field, _ = object_relation.split('-')
                from_and_to_fields[relation_type][field] = attribute_value
                continue
            elif object_relation in ('from-country', 'to-country'):
                relation_type, field = object_relation.split('-')
                from_and_to_fields[relation_type][field] = attribute_value
                continue
            try:
                self.xml[xml_part] += "<{0}>{1}</{0}>".format(
                    goAMLmapping[object_type][object_relation],
                    attribute_value)
            except KeyError:
                pass
        self.from_and_to_fields = from_and_to_fields

    def fill_xml(self, object_type, obj, xml_part):
        if obj.name == 'bank-account':
            for attribute in obj.attributes:
                if attribute.object_relation in ('personal-account-type',
                                                 'status-code'):
                    attribute_value = attribute.value.split(' - ')[0]
                else:
                    attribute_value = attribute.value
                try:
                    self.xml[xml_part] += "<{0}>{1}</{0}>".format(
                        goAMLmapping[object_type][attribute.object_relation],
                        attribute_value)
                except KeyError:
                    pass
        else:
            for attribute in obj.attributes:
                try:
                    self.xml[xml_part] += "<{0}>{1}</{0}>".format(
                        goAMLmapping[object_type][attribute.object_relation],
                        attribute.value)
                except KeyError:
                    pass

    def parse_references(self, object_type, next_object_type, uuid,
                         relationship_type, xml_part):
        reference = referencesMapping[next_object_type]
        try:
            next_aml_type = reference[object_type].get('aml_type').format(
                relationship_type.split('_')[0])
            try:
                bracket = reference[object_type].get('bracket').format(
                    relationship_type)
                self.xml[xml_part] += "<{}>".format(bracket)
                self.itterate(next_object_type, next_aml_type, uuid, xml_part)
                self.xml[xml_part] += "</{}>".format(bracket)
            except KeyError:
                self.itterate(next_object_type, next_aml_type, uuid, xml_part)
        except KeyError:
            next_aml_type = reference.get('aml_type').format(
                relationship_type.split('_')[0])
            bracket = reference.get('bracket').format(relationship_type)
            self.xml[xml_part] += "<{}>".format(bracket)
            self.itterate(next_object_type, next_aml_type, uuid, xml_part)
            self.xml[xml_part] += "</{}>".format(bracket)