Skip to content
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ plantuml.jar
tm/
/sqldump
/tests/output_current.json
/tests/output_current.md
/tests/1.txt
/tests/0.txt
/tests/.config.pytm
111 changes: 97 additions & 14 deletions docs/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,119 @@ Name|From|To |Data|Protocol|Port
{dataflows:repeat:|{{item.name}}|{{item.source.name}}|{{item.sink.name}}|{{item.data}}|{{item.protocol}}|{{item.dstPort}}|
}

<br>
<br>

## Data Dictionary
&nbsp;

Name|Description|Classification
|:----:|:--------:|:----:|
{data:repeat:|{{item.name}}|{{item.description}}|{{item.classification.name}}|
Name|Description|Classification|Carried|Processed
|:----:|:--------:|:----:|:----|:----|
{data:repeat:|{{item.name}}|{{item.description}}|{{item.classification.name}}|{{item.carriedBy:repeat:{{{{item.name}}}}<br>}}|{{item.processedBy:repeat:{{{{item.name}}}}<br>}}|
}

&nbsp;

## Potential Threats

&nbsp;
## Actors
&nbsp;

|{findings:repeat:
Name|Description|isAdmin
|:----:|:--------:|:----:|
{actors:repeat:|{{item.name}}|{{item.description}}|{{item.isAdmin}}|
}

<br>
<br>

## Boundaries

{boundaries:repeat:
Element|{{item.name}}
|:----|:----|
Description|{{item.description}}|
InScope|{{item.inScope}}|
Parent|{{item:utils:getParentName}}|
Parents|{{item.parents:call:{{{{item.name}}}}, }}|
Classification|{{item.maxClassification}}|

<br>
<br>

}

## Assets

{assets:repeat:

<br>
<hr>

Element|{{item.name}}
|:----|:----|
Description|{{item.description}}|
InScope|{{item.inScope}}|
Type|{{item:utils:getElementType}}|
Finding Count|{{item:utils:getFindingCount}}|

###### Threats

{{item.findings:repeat:
<details>
<summary> {{{{item.id}}}} -- {{{{item.threat_id}}}} -- {{{{item.description}}}}</summary>
<h6> Targeted Element </h6>
<p> {{{{item.target}}}} </p>
<h6> Severity </h6>
<p>{{{{item.severity}}}}</p>
<h6>Example Instances</h6>
<p>{{{{item.example}}}}</p>
<h6>Mitigations</h6>
<p>{{{{item.mitigations}}}}</p>
<h6>References</h6>
<p>{{{{item.references}}}}</p>
&nbsp;
&nbsp;
&emsp;
</details>
}}
}

<br>
<br>

## Data Flows

{dataflows:repeat(e):

<br>
<hr>

Dataflow|{{item.name}}
|:----|:----|
Description|{{item.description}}|
InScope|{{item.inScope}}|
Finding Count|{{item:utils:getFindingCount}}|

###### Threats

{{item.findings:repeat:
<details>
<summary> {{item.id}} -- {{item.description}}</summary>
<summary> {{{{item.id}}}} -- {{{{item.threat_id}}}} -- {{{{item.description}}}}</summary>
<h6> Targeted Element </h6>
<p> {{item.target}} </p>
<p> {{{{item.target}}}} </p>
<h6> Severity </h6>
<p>{{item.severity}}</p>
<p>{{{{item.severity}}}}</p>
<h6>Example Instances</h6>
<p>{{item.example}}</p>
<p>{{{{item.example}}}}</p>
<h6>Mitigations</h6>
<p>{{item.mitigations}}</p>
<p>{{{{item.mitigations}}}}</p>
<h6>References</h6>
<p>{{item.references}}</p>
<p>{{{{item.references}}}}</p>
&nbsp;
&nbsp;
&emsp;
</details>
}|
}}

}

&nbsp;
42 changes: 42 additions & 0 deletions pytm/report_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

class ReportUtils:
@staticmethod
def getParentName(element):
from pytm import Boundary
if (isinstance(element, Boundary)):
parent = element.inBoundary
if (parent is not None):
return parent.name
else:
return str("")
else:
return "ERROR: getParentName method is not valid for " + element.__class__.__name__


@staticmethod
def getNamesOfParents(element):
from pytm import Boundary
if (isinstance(element, Boundary)):
parents = map(lambda b: b.name, element.parents())
return list(parents)
else:
return "ERROR: getNamesOfParents method is not valid for " + element.__class__.__name__

@staticmethod
def getFindingCount(element):
from pytm import Element
if (isinstance(element, Element)):
return str(len(list(element.findings)))
else:
return "ERROR: getFindingCount method is not valid for " + element.__class__.__name__

@staticmethod
def getElementType(element):
from pytm import Element
if (isinstance(element, Element)):
return str(element.__class__.__name__)
else:
return "ERROR: getElementType method is not valid for " + element.__class__.__name__



29 changes: 27 additions & 2 deletions pytm/template_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,33 @@ def format_field(self, value, spec):
if type(value) is dict:
value = value.items()
return "".join([self.format(template, item=item) for item in value])
elif spec == "call":
return value()
elif spec.startswith("call"):
result = value()
if type(result) is list:
template = spec.partition(":")[-1]
return "".join([self.format(template, item=item) for item in result])

return result
elif spec.startswith("utils"):

spec_parts = spec.split(":")

method_name = spec_parts[1]
template = spec_parts[-1]

module_name = "pytm.report_util"
klass_name = "ReportUtils"
module = __import__(module_name, fromlist=['ReportUtils'])
klass = getattr(module, klass_name)

method = getattr(klass, method_name)
result = method(value)

if type(result) is list:
return "".join([self.format(template, item=item) for item in result])

return result

elif spec.startswith("if"):
return (value and spec.partition(":")[-1]) or ""
else:
Expand Down
Loading