diff --git a/.gitignore b/.gitignore index b6e4761..ade267c 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,6 @@ dmypy.json # Pyre type checker .pyre/ + +# vim +.*.swp diff --git a/example_tinkerbell.py b/example_tinkerbell.py new file mode 100644 index 0000000..8104c4e --- /dev/null +++ b/example_tinkerbell.py @@ -0,0 +1,75 @@ +from fluentm import ( + Actor, + Process, + DataFlow, + HTTP, + MTLS, + TLS, + DHCP, +) +from fluentm import report + +scenes = { + # Example using variables, which is fine for small things but gets hard with longer flows + "Tink API traffic": [ + DataFlow( + Actor("tink-cli"), + Process("Tink API").inBoundary("Tink Control Plane Network"), + MTLS(HTTP("API request")), + ), + DataFlow( + Process("Machine").inBoundary("On Premise Network"), + Process("boots").inBoundary("Tink Control Plane Network"), + DHCP("IP Request"), + # response=DHCP("DHCP Response"), + ), + DataFlow( + Process("boots").inBoundary("Tink Control Plane Network"), + Process("Tink API").inBoundary("Tink Control Plane Network"), + MTLS(HTTP("API request")), + "Boots queries for IP", + ), + DataFlow( + Process("Machine").inBoundary("On Premise Network"), + Process("boots").inBoundary("Tink Control Plane Network"), + DHCP("PXE Location Request"), + # response=DHCP("PXE Location Response"), + ), + DataFlow( + Process("boots").inBoundary("Tink Control Plane Network"), + Process("Tink API").inBoundary("Tink Control Plane Network"), + MTLS(HTTP("API request")), + "Boots queries for PXE OS location", + ), + DataFlow( + Process("Machine").inBoundary("On Premise Network"), + Process("Nginx").inBoundary("Tink Control Plane Network"), + HTTP("Boot OS Request"), + # response=HTTP("Boot OS"), + ), + DataFlow( + Process("Machine").inBoundary("On Premise Network"), + Process("Tink API").inBoundary("Tink Control Plane Network"), + TLS(HTTP("Workflow")), + ), + DataFlow( + Process("Machine").inBoundary("On Premise Network"), + Process("Container Registry").inBoundary("Tink Control Plane Network"), + TLS(HTTP("Container Images")), + ), + DataFlow( + Process("Machine").inBoundary("On Premise Network"), + Process("Hegel").inBoundary("Tink Control Plane Network"), + TLS(HTTP("Machine metadata")), + "Metadata request", + ), + DataFlow( + Process("Machine").inBoundary("On Premise Network"), + Process("Nginx").inBoundary("Tink Control Plane Network"), + HTTP("Workload OS"), + ), + ] # TODO: Fix silent error on repeat label names +} + +if __name__ == "__main__": + report(scenes, outputDir="examples/tinkerbell", dfdLabels=True) diff --git a/examples/tinkerbell/ThreatModel.html b/examples/tinkerbell/ThreatModel.html new file mode 100644 index 0000000..ad3d6e7 --- /dev/null +++ b/examples/tinkerbell/ThreatModel.html @@ -0,0 +1,185 @@ + + + + Threat Models + + + + +
+ +

Tink API traffic

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Flow IDPitcherCatcherData Flow
1tink-cliTink APIMTLS( HTTP( API request ) )
2MachinebootsDHCP( IP Request )
3bootsTink APIMTLS( HTTP( API request ) )
4MachinebootsDHCP( PXE Location Request )
5bootsTink APIMTLS( HTTP( API request ) )
6MachineNginxHTTP( Boot OS Request )
7MachineTink APITLS( HTTP( Workflow ) )
8MachineContainer RegistryTLS( HTTP( Container Images ) )
9MachineHegelTLS( HTTP( Machine metadata ) )
10MachineNginxHTTP( Workload OS )
+ + +
+ + + \ No newline at end of file diff --git a/examples/tinkerbell/Tink API traffic-dfd b/examples/tinkerbell/Tink API traffic-dfd new file mode 100644 index 0000000..e20fd0d --- /dev/null +++ b/examples/tinkerbell/Tink API traffic-dfd @@ -0,0 +1,27 @@ +digraph "Tink API traffic" { + color=blue rankdir=LR + node [fontname=Arial fontsize=14] + "tink-cli" + subgraph "cluster_Tink Control Plane Network" { + graph [color=red fontname=Arial fontsize=12 label="Tink Control Plane Network" line=dotted] + "Tink API" + boots + Nginx + "Container Registry" + Hegel + } + subgraph "cluster_On Premise Network" { + graph [color=red fontname=Arial fontsize=12 label="On Premise Network" line=dotted] + Machine + } + "tink-cli" -> "Tink API" [label="(1) API request"] + Machine -> boots [label="(2) IP Request"] + boots -> "Tink API" [label="(3) Boots queries for IP"] + Machine -> boots [label="(4) PXE Location Request"] + boots -> "Tink API" [label="(5) Boots queries for PXE OS location"] + Machine -> Nginx [label="(6) Boot OS Request"] + Machine -> "Tink API" [label="(7) Workflow"] + Machine -> "Container Registry" [label="(8) Container Images"] + Machine -> Hegel [label="(9) Metadata request"] + Machine -> Nginx [label="(10) Workload OS"] +} diff --git a/examples/tinkerbell/Tink API traffic-dfd.png b/examples/tinkerbell/Tink API traffic-dfd.png new file mode 100644 index 0000000..ec6e98e Binary files /dev/null and b/examples/tinkerbell/Tink API traffic-dfd.png differ diff --git a/fluentm.py b/fluentm.py index 4a42a8d..b627235 100644 --- a/fluentm.py +++ b/fluentm.py @@ -92,6 +92,11 @@ def __init__(self, toWrap): ) +class DHCP(Plaintext): + def __init__(self, toWrap): + super().__init__(toWrap) + + class Internal(WrappableProtocol): def __init__(self, toWrap): super().__init__( @@ -129,6 +134,19 @@ def __init__(self, toWrap): ) +class MTLS(WrappableProtocol): + def __init__(self, toWrap): + super().__init__( + toWrap, + encrypted=True, + version=None, + serverAuthenticated=True, + clientAuthenticated=True, + serverCredential="x509", + clientCredential="x509", + ) + + class MTLSVPN(WrappableProtocol): def __init__(self, toWrap): super().__init__(