2015-11-21 16:53:23 +01:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Python script parsing the MISP taxonomies expressed in Machine Tags (Triple
# Tags) to list all valid tags from a specific taxonomy.
#
2022-02-23 07:34:47 +01:00
# Copyright (c) 2015-2022 Alexandre Dulaunoy - a@foo.be
2015-11-21 16:53:23 +01:00
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
# OF THE POSSIBILITY OF SUCH DAMAGE.
import json
import os . path
import argparse
2016-10-24 17:01:32 +02:00
import os
2022-02-23 07:34:47 +01:00
import sys
2015-11-21 16:53:23 +01:00
2024-03-04 10:06:48 +01:00
skip_list = [ " death-possibilities " , " poison-taxonomy " , " doping-substances " ]
2016-10-24 17:01:32 +02:00
taxonomies = [ ]
2017-01-20 10:35:28 +01:00
# Get our current directory from file location
thisDir = os . path . dirname ( __file__ )
2024-03-04 10:06:48 +01:00
argParser = argparse . ArgumentParser (
description = " Dump Machine Tags (Triple Tags) from MISP taxonomies " ,
epilog = " Available taxonomies are {0} " . format ( taxonomies ) ,
)
argParser . add_argument ( " -e " , action = " store_true " , help = " Include expanded tags " )
argParser . add_argument (
" -a " , action = " store_true " , help = " Generate asciidoctor document from MISP taxonomies "
)
argParser . add_argument ( " -v " , action = " store_true " , help = " Include descriptions " )
argParser . add_argument ( " -n " , default = False , help = " Show only the specified namespace " )
argParser . add_argument (
" --disable-skip-list " ,
default = False ,
action = " store_true " ,
help = " disable default skip list " ,
)
2015-11-21 16:53:23 +01:00
args = argParser . parse_args ( )
2022-02-23 07:34:47 +01:00
if args . disable_skip_list :
2024-03-04 10:06:48 +01:00
skip_list = " "
2022-02-23 07:34:47 +01:00
2024-03-04 10:06:48 +01:00
for folder in os . listdir ( os . path . join ( thisDir , " ../ " ) ) :
if os . path . isfile ( os . path . join ( thisDir , " ../ " , folder , " machinetag.json " ) ) :
2022-02-23 07:50:24 +01:00
if folder in skip_list :
continue
taxonomies . append ( folder )
taxonomies . sort ( )
2024-03-04 10:06:48 +01:00
doc = " "
2015-11-29 15:29:49 +01:00
if args . a :
2017-11-04 14:09:02 +01:00
dedication = " \n [dedication] \n == Funding and Support \n The MISP project is financially and resource supported by https://www.circl.lu/[CIRCL Computer Incident Response Center Luxembourg ]. \n \n image: { images-misp}logo.png[CIRCL logo] \n \n A CEF (Connecting Europe Facility) funding under CEF-TC-2016-3 - Cyber Security has been granted from 1st September 2017 until 31th August 2019 as ***Improving MISP as building blocks for next-generation information sharing***. \n \n image: { images-misp}en_cef.png[CEF funding] \n \n If you are interested to co-fund projects around MISP, feel free to get in touch with us. \n \n "
2015-11-29 15:29:49 +01:00
doc = doc + " :toc: right \n "
2017-05-07 12:22:14 +02:00
doc = doc + " :toclevels: 1 \n "
2015-11-29 15:29:49 +01:00
doc = doc + " :icons: font \n "
2024-03-04 10:06:48 +01:00
doc = (
doc
+ " :images-cdn: https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/logos/ \n "
)
2017-11-04 14:09:02 +01:00
doc = doc + " :images-misp: https://www.misp-project.org/assets/images/ \n "
2015-11-29 15:29:49 +01:00
doc = doc + " = MISP taxonomies and classification as machine tags \n \n "
2017-11-04 14:09:02 +01:00
doc = doc + " = Introduction \n "
2015-11-29 15:46:13 +01:00
doc = doc + " \n image:: { images-cdn}misp-logo.png[MISP logo] \n "
2024-03-04 10:06:48 +01:00
doc = (
doc
+ " The MISP threat sharing platform is a free and open source software helping information sharing of threat intelligence including cyber security indicators, financial fraud or counter-terrorism information. The MISP project includes multiple sub-projects to support the operational requirements of analysts and improve the overall quality of information shared. \n \n "
)
2017-11-04 14:09:02 +01:00
doc = doc + " "
2024-03-04 10:06:48 +01:00
doc = " {} {} {} {} " . format (
doc ,
" \n Taxonomies that can be used in MISP (2.4) and other information sharing tool and expressed in Machine Tags (Triple Tags). " ,
" A machine tag is composed of a namespace (MUST), a predicate (MUST) and an (OPTIONAL) value. " ,
" Machine tags are often called triple tag due to their format. \n " ,
)
doc = (
doc
+ " The following document is generated from the machine-readable JSON describing the https://github.com/MISP/misp-taxonomies[MISP taxonomies]. "
)
2017-11-04 14:09:02 +01:00
doc = doc + " \n \n "
doc = doc + " <<< \n "
doc = doc + dedication
doc = doc + " <<< \n "
doc = doc + " = MISP taxonomies \n "
2015-11-29 15:29:49 +01:00
doc = doc + " \n \n "
2016-02-21 19:45:18 +01:00
if args . n :
del taxonomies [ : ]
taxonomies . append ( args . n )
2017-04-02 22:06:32 +02:00
2024-03-04 10:06:48 +01:00
def asciidoc ( content = False , adoc = doc , t = " title " , toplevel = False ) :
2015-11-29 15:29:49 +01:00
if not args . a :
return False
adoc = adoc + " \n "
2024-03-04 10:06:48 +01:00
if t == " title " :
content = " ==== " + content
elif t == " predicate " :
content = " === " + content
elif t == " namespace " :
content = " == " + content + " \n "
content = " {} \n {} {} {} {} {} {} " . format (
content ,
" NOTE: " ,
namespace ,
" namespace available in JSON format at https://github.com/MISP/misp-taxonomies/blob/main/ " ,
namespace ,
" /machinetag.json[*this location*]. The JSON format can be freely reused in your application " ,
" or automatically enabled in https://www.github.com/MISP/MISP[MISP] taxonomy. " ,
)
elif t == " description " and toplevel is True :
2018-02-18 12:37:45 +01:00
content = " \n {} \n " . format ( content )
2024-03-04 10:06:48 +01:00
elif t == " description " and toplevel is False :
2017-04-30 11:32:11 +02:00
try :
( n , value ) = content . split ( " : " , 1 )
content = " \n {} \n " . format ( value )
except :
content = " \n {} \n " . format ( content )
2024-03-04 10:06:48 +01:00
elif t == " numerical_value " :
2017-12-01 07:55:35 +01:00
( n , value ) = content . split ( " : " , 1 )
2024-03-04 10:06:48 +01:00
content = ' \n Associated numerical value= " {} " \n ' . format ( value )
elif t == " exclusive " :
2017-12-01 08:54:34 +01:00
( n , value ) = content . split ( " : " , 1 )
if n :
content = " \n IMPORTANT: Exclusive flag set which means the values or predicate below must be set exclusively. \n "
2015-11-29 15:29:49 +01:00
adoc = adoc + content
return adoc
2015-11-21 16:53:23 +01:00
2017-04-02 22:06:32 +02:00
2015-11-21 16:53:23 +01:00
def machineTag ( namespace = False , predicate = False , value = None ) :
if namespace is False or predicate is False :
return None
if value is None :
2024-03-04 10:06:48 +01:00
return " {0} : {1} " . format ( namespace , predicate )
2015-11-21 16:53:23 +01:00
else :
2024-03-04 10:06:48 +01:00
return ' {0} : {1} = " {2} " ' . format ( namespace , predicate , value )
2015-11-21 16:53:23 +01:00
2017-04-02 22:06:32 +02:00
2015-11-21 16:53:23 +01:00
for taxonomy in taxonomies :
2022-02-23 07:34:47 +01:00
if taxonomy in skip_list :
sys . stderr . write ( f " Skip { taxonomy } " )
continue
2017-01-20 10:35:28 +01:00
filename = os . path . join ( thisDir , " ../ " , taxonomy , " machinetag.json " )
2015-11-21 16:53:23 +01:00
with open ( filename ) as fp :
t = json . load ( fp )
2024-03-04 10:06:48 +01:00
namespace = t [ " namespace " ]
if t . get ( " expanded " ) :
expanded_namespace = t [ " expanded " ]
2016-01-10 17:03:44 +01:00
else :
expanded_namespace = namespace
2015-11-29 15:29:49 +01:00
if args . a :
2024-03-04 10:06:48 +01:00
doc = asciidoc ( content = t [ " namespace " ] , adoc = doc , t = " namespace " )
doc = asciidoc (
content = t [ " description " ] , adoc = doc , t = " description " , toplevel = True
)
if t . get ( " exclusive " ) :
doc = asciidoc (
content = machineTag ( namespace = namespace , predicate = t [ " exclusive " ] ) ,
adoc = doc ,
t = " exclusive " ,
)
2015-11-29 14:22:25 +01:00
if args . v :
2024-03-04 10:06:48 +01:00
print ( " {0} " . format ( t [ " description " ] ) )
for predicate in t [ " predicates " ] :
2015-11-29 15:29:49 +01:00
if args . a :
2024-03-04 10:06:48 +01:00
doc = asciidoc ( content = predicate [ " value " ] , adoc = doc , t = " predicate " )
if predicate . get ( " description " ) :
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = predicate [ " description " ]
) ,
adoc = doc ,
t = " description " ,
)
if predicate . get ( " exclusive " ) :
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = predicate [ " exclusive " ]
) ,
adoc = doc ,
t = " exclusive " ,
)
2017-12-01 08:54:34 +01:00
2024-03-04 10:06:48 +01:00
if t . get ( " values " ) is None :
2015-11-29 15:29:49 +01:00
if args . a :
2024-03-04 10:06:48 +01:00
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = predicate [ " value " ]
) ,
adoc = doc ,
)
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = predicate [ " expanded " ]
) ,
adoc = doc ,
t = " description " ,
)
if predicate . get ( " description " ) :
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = predicate [ " description " ]
) ,
adoc = doc ,
t = " description " ,
)
if predicate . get ( " numerical_value " ) :
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = predicate [ " numerical_value " ]
) ,
adoc = doc ,
t = " description " ,
)
if predicate . get ( " exclusive " ) :
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = predicate [ " exclusive " ]
) ,
adoc = doc ,
t = " exclusive " ,
)
2015-11-29 15:29:49 +01:00
else :
2024-03-04 10:06:48 +01:00
print ( machineTag ( namespace = namespace , predicate = predicate [ " value " ] ) )
2015-11-22 08:16:09 +01:00
if args . e :
2024-03-04 10:06:48 +01:00
print (
" --> "
+ machineTag (
namespace = expanded_namespace , predicate = predicate [ " expanded " ]
)
)
if predicate . get ( " description " ) :
print ( " --> " + predicate [ " description " ] )
2015-11-22 08:16:09 +01:00
else :
2024-03-04 10:06:48 +01:00
for e in t [ " values " ] :
if e [ " predicate " ] == predicate [ " value " ] :
if " expanded " in predicate :
expanded = predicate [ " expanded " ]
for v in e [ " entry " ] :
if args . a and " expanded " in v :
doc = asciidoc (
content = machineTag (
namespace = namespace ,
predicate = e [ " predicate " ] ,
value = v [ " value " ] ,
) ,
adoc = doc ,
)
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = v [ " expanded " ]
) ,
adoc = doc ,
t = " description " ,
)
if " description " in v :
doc = asciidoc (
content = machineTag (
namespace = namespace , predicate = v [ " description " ]
) ,
adoc = doc ,
t = " description " ,
)
if v . get ( " numerical_value " ) :
doc = asciidoc (
content = machineTag (
namespace = namespace ,
predicate = v [ " numerical_value " ] ,
) ,
adoc = doc ,
t = " numerical_value " ,
)
2015-11-29 15:29:49 +01:00
else :
2024-03-04 10:06:48 +01:00
print (
machineTag (
namespace = namespace ,
predicate = e [ " predicate " ] ,
value = v [ " value " ] ,
)
)
2015-11-22 08:16:09 +01:00
if args . e :
2024-03-04 10:06:48 +01:00
if " expanded " in v :
print (
" --> "
+ machineTag (
namespace = namespace ,
predicate = expanded ,
value = v [ " expanded " ] ,
)
)
2015-11-29 15:29:49 +01:00
2024-03-04 10:06:48 +01:00
with open ( " ../mapping/mapping.json " ) as mapping :
2017-10-24 07:49:19 +02:00
m = json . load ( mapping )
2024-03-04 10:06:48 +01:00
output = " \n = Mapping of taxonomies \n "
output = " {} {} " . format (
output ,
" Analysts relying on taxonomies don ' t always know the appropriate namespace to use but know which value to use for classification. The MISP mapping taxonomy allows to map a single classification into a series of machine-tag synonyms. \n " ,
)
2017-10-24 07:49:19 +02:00
for value in sorted ( m . keys ( ) ) :
2024-03-04 10:06:48 +01:00
output = " {} {} ** {} ** {} {} \n " . format (
output , " \n .Mapping table - " , value , " \n |=== \n | " , value
)
for mapped in m [ value ] [ " values " ] :
output = " {} | {} \n " . format ( output , mapped )
output = " {} |=== \n " . format ( output )
2017-10-24 07:49:19 +02:00
doc = doc + output
2015-11-29 15:29:49 +01:00
if args . a :
2017-04-02 22:06:32 +02:00
print ( doc )