Initial commit

pull/2/head
Raphaël Vinot 2016-07-25 18:48:08 +02:00
commit a86f2c305e
9 changed files with 235 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
build
dist
pytaxonomies.egg-info
*.swp
*.pyc

21
.travis.yml Normal file
View File

@ -0,0 +1,21 @@
language: python
cache: pip
python:
- "3.3"
- "3.4"
- "3.5"
- "nightly"
install:
- pip install coveralls
- pip install codecov
- pip install .
script:
- nosetests --with-coverage --cover-package=pytaxonomies
after_success:
- codecov
- coveralls

4
README.md Normal file
View File

@ -0,0 +1,4 @@
# PyTaxonomies
Pythonic way to work with the taxonomies defined there: https://github.com/MISP/misp-taxonomies

13
bin/pytaxonomies Normal file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
from pytaxonomies import Taxonomies
if __name__ == '__main__':
argParser = argparse.ArgumentParser(description='Use MISP taxonomies')
argParser.add_argument('-p', action='store_true', help='Print all taxonomies')
args = argParser.parse_args()
if args.p:
t = Taxonomies()
print(t)

1
pytaxonomies/__init__.py Normal file
View File

@ -0,0 +1 @@
from .api import Taxonomies

145
pytaxonomies/api.py Normal file
View File

@ -0,0 +1,145 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import requests
import os
import collections
class Entry():
def __init__(self, value, expanded, description):
self.value = value
self.expanded = expanded
self.description = description
class Predicate(collections.Mapping):
def __init__(self, predicate, description, entries):
self.predicate = predicate
self.description = description
self.entries = {}
if entries:
self.__init_entries(entries)
def __init_entries(self, entries):
for e in entries:
self.entries[e['value']] = Entry(e['value'], e['expanded'],
e.get('description'))
def __getitem__(self, entry):
return self.entries[entry]
def __iter__(self):
return iter(self.entries)
def __len__(self):
return len(self.entries)
class Taxonomy(collections.Mapping):
def __init__(self, taxonomy):
self.taxonomy = taxonomy
self.name = self.taxonomy['namespace']
self.description = self.taxonomy['description']
self.version = self.taxonomy['version']
self.__init_predicates()
def __init_predicates(self):
self.predicates = {}
entries = {}
if self.taxonomy.get('values'):
for v in self.taxonomy['values']:
if not entries.get(v['predicate']):
entries[v['predicate']] = []
entries[v['predicate']] += v['entry']
for p in self.taxonomy['predicates']:
self.predicates[p['value']] = Predicate(p['value'], p.get('expanded'),
entries.get(p['value']))
def __str__(self):
to_return = ''
for p, content in self.predicates.items():
if content:
for k in content.keys():
to_return += '{}:{}="{}"\n'.format(self.name, p, k)
else:
to_return += '{}:{}\n'.format(self.name, p)
return to_return
def __getitem__(self, predicate):
return self.predicates[predicate]
def __iter__(self):
return iter(self.predicates)
def __len__(self):
return len(self.predicates)
def amount_entries(self):
return sum([len(p) for p in self.predicates])
def print_expanded_entries(self):
to_return = ''
for p, content in self.predicates.items():
if content:
for k, entry in content.items():
to_return += '{}:{}="{}"\n'.format(self.name, p, entry.expanded)
else:
to_return += '{}:{}\n'.format(self.name, p)
return to_return
class Taxonomies(collections.Mapping):
def __init__(self, manifest_url='https://raw.githubusercontent.com/MISP/misp-taxonomies/master/MANIFEST.json',
manifest_path=None):
if manifest_path:
self.loader = self.__load_path
self.manifest = self.loader(manifest_path)
else:
self.loader = self.__load_url
self.manifest = self.loader(manifest_url)
if manifest_path:
self.url = os.path.dirname(os.path.realpath(manifest_path))
self.version = self.manifest['version']
self.license = self.manifest['license']
self.description = self.manifest['description']
self.taxonomies_names = [t['name'] for t in self.manifest['taxonomies']]
self.__init_taxonomies()
def __load_path(self, path):
with open(path, 'r') as f:
return json.load(f)
def __load_url(self, url):
return requests.get(url).json()
def __make_uri(self, taxonomy_name):
return '{}{}/{}'.format(self.manifest['url'], taxonomy_name, self.manifest['path'])
def __init_taxonomies(self):
self.taxonomies = {}
for t in self.manifest['taxonomies']:
uri = self.__make_uri(t['name'])
tax = self.loader(uri)
self.taxonomies[t['name']] = Taxonomy(tax)
def __getitem__(self, name):
return self.taxonomies[name]
def __iter__(self):
return iter(self.taxonomies)
def __len__(self):
return len(self.taxonomies)
def __str__(self):
to_return = ''
for k, taxonomy in self.taxonomies.items():
to_return += '{}\n'.format(taxonomy.__str__())
return to_return

29
setup.py Normal file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup
setup(
name='pytaxonomies',
version='0.5',
author='Raphaël Vinot',
author_email='raphael.vinot@circl.lu',
maintainer='Raphaël Vinot',
url='https://github.com/MISP/PyTaxonomies',
description='Python API for the taxonomies.',
packages=['pytaxonomies'],
scripts=['bin/pytaxonomies'],
classifiers=[
'License :: OSI Approved :: BSD License',
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Science/Research',
'Intended Audience :: Telecommunications Industry',
'Programming Language :: Python',
'Topic :: Security',
'Topic :: Internet',
],
tests_requires=['nose'],
test_suite='nose.collector',
install_requires=['requests'],
)

0
tests/__init__.py Normal file
View File

17
tests/tests.py Normal file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest
from pytaxonomies import Taxonomies
class TestPyTaxonomies(unittest.TestCase):
def setUp(self):
self.taxonomies = Taxonomies()
def test_print(self):
print(self.taxonomies)
if __name__ == "__main__":
unittest.main()