-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New notebooks - Low Hanging fruits (#235)
* Adding new workflow notebooks * Modifying existing notebook for KHaaS * PR comments * Last PR comment * Update deployments/kubehound/notebook/LowHangingFruit-ContainerEscape.ipynb Co-authored-by: Simon Maréchal <[email protected]> * Update deployments/kubehound/notebook/LowHangingFruit-ContainerEscape.ipynb Co-authored-by: Simon Maréchal <[email protected]> * Update deployments/kubehound/notebook/LowHangingFruit-ContainerEscape.ipynb Co-authored-by: Simon Maréchal <[email protected]> * Update deployments/kubehound/notebook/LowHangingFruit-ContainerEscape.ipynb Co-authored-by: Simon Maréchal <[email protected]> * Update deployments/kubehound/notebook/LowHangingFruit-Endpoints.ipynb Co-authored-by: Simon Maréchal <[email protected]> * Update deployments/kubehound/notebook/LowHangingFruit-Endpoints.ipynb Co-authored-by: Simon Maréchal <[email protected]> * Update deployments/kubehound/notebook/LowHangingFruit-Endpoints.ipynb Co-authored-by: Simon Maréchal <[email protected]> * Update deployments/kubehound/notebook/LowHangingFruit-Endpoints.ipynb Co-authored-by: Simon Maréchal <[email protected]> --------- Co-authored-by: Simon Maréchal <[email protected]>
- Loading branch information
1 parent
99d9e3d
commit 358f2b4
Showing
9 changed files
with
1,445 additions
and
660 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ | |
}, | ||
"outputs": [], | ||
"source": [ | ||
"%%capture \"Remove this line to see debug information\"\n", | ||
"%%graph_notebook_vis_options\n", | ||
"{\n", | ||
" \"edges\": {\n", | ||
|
@@ -72,12 +73,13 @@ | |
"outputs": [], | ||
"source": [ | ||
"%%gremlin\n", | ||
"kh.identities().\n", | ||
" or(\n", | ||
"kh.identities()\n", | ||
" .has(\"runID\", graph.variables().get('runID_yourid').get())\n", | ||
" .or(\n", | ||
" has(\"type\", \"Group\").has(\"name\", within(\"dept-sales\", \"k8s-users\")),\n", | ||
" has(\"type\", \"User\").has(\"name\", \"[email protected]\")).\n", | ||
" hasCriticalPath().\n", | ||
" values(\"name\")" | ||
" has(\"type\", \"User\").has(\"name\", \"[email protected]\"))\n", | ||
" .hasCriticalPath()\n", | ||
" .values(\"name\")" | ||
] | ||
}, | ||
{ | ||
|
@@ -95,13 +97,14 @@ | |
"source": [ | ||
"\n", | ||
"%%gremlin -d class -g critical -le 50 -p inv,oute\n", | ||
"kh.identities().\n", | ||
" or(\n", | ||
"kh.identities()\n", | ||
" .has(\"runID\", graph.variables().get('runID_yourid').get())\n", | ||
" .or(\n", | ||
" has(\"type\", \"Group\").has(\"name\", within(\"dept-sales\", \"k8s-users\")),\n", | ||
" has(\"type\", \"User\").has(\"name\", \"[email protected]\")).\n", | ||
" criticalPaths().\n", | ||
" by(elementMap()).\n", | ||
" limit(100) // Limit the number of results for large clusters\n" | ||
" has(\"type\", \"User\").has(\"name\", \"[email protected]\"))\n", | ||
" .criticalPaths()\n", | ||
" .by(elementMap())\n", | ||
" .limit(100) // Limit the number of results for large clusters" | ||
] | ||
}, | ||
{ | ||
|
@@ -129,13 +132,14 @@ | |
"outputs": [], | ||
"source": [ | ||
"%%gremlin\n", | ||
"kh.containers().\n", | ||
" or(\n", | ||
"kh.containers()\n", | ||
" .has(\"runID\", graph.variables().get('runID_yourid').get())\n", | ||
" .or(\n", | ||
" has(\"image\", TextP.containing(\"nginx\")), // Replace with your image name\n", | ||
" has(\"image\", TextP.containing(\"cilium\"))). // Replace with your image name\n", | ||
" hasCriticalPath().\n", | ||
" values(\"name\").\n", | ||
" dedup()" | ||
" has(\"image\", TextP.containing(\"cilium\"))) // Replace with your image name\n", | ||
" .hasCriticalPath()\n", | ||
" .values(\"name\")\n", | ||
" .dedup()" | ||
] | ||
}, | ||
{ | ||
|
@@ -152,13 +156,14 @@ | |
"outputs": [], | ||
"source": [ | ||
"%%gremlin -d class -g critical -le 50 -p inv,oute\n", | ||
"kh.containers().\n", | ||
" or(\n", | ||
"kh.containers()\n", | ||
" .has(\"runID\", graph.variables().get('runID_yourid').get())\n", | ||
" .or(\n", | ||
" has(\"image\", TextP.containing(\"nginx\")), // Replace with your image name\n", | ||
" has(\"image\", TextP.containing(\"cilium\"))). // Replace with your image name\n", | ||
" criticalPaths().\n", | ||
" by(elementMap()).\n", | ||
" limit(100) // Limit the number of results for large clusters" | ||
" has(\"image\", TextP.containing(\"cilium\"))) // Replace with your image name\n", | ||
" .criticalPaths()\n", | ||
" .by(elementMap())\n", | ||
" .limit(100) // Limit the number of results for large clusters" | ||
] | ||
}, | ||
{ | ||
|
@@ -186,15 +191,17 @@ | |
"outputs": [], | ||
"source": [ | ||
"%%gremlin\n", | ||
"kh.containers().\n", | ||
" where(out().hasLabel(\"Node\")).\n", | ||
" or(\n", | ||
"kh.containers()\n", | ||
" .has(\"runID\", graph.variables().get('runID_yourid').get())\n", | ||
" .where(out().hasLabel(\"Node\"))\n", | ||
" .or(\n", | ||
" has(\"image\", TextP.containing(\"nginx\")), // Replace with your image name\n", | ||
" has(\"image\", TextP.containing(\"cilium\"))). // Replace with your image name\n", | ||
"\tproject('image',\"escapes\").\n", | ||
"\tby(values(\"image\")).\n", | ||
"\tby(outE().where(inV().hasLabel(\"Node\")).label().fold()).\n", | ||
"\tdedup()" | ||
" has(\"image\", TextP.containing(\"cilium\")) // Replace with your image name\n", | ||
" ) \n", | ||
" .project('image',\"escapes\")\n", | ||
" .by(values(\"image\"))\n", | ||
" .by(outE().where(inV().hasLabel(\"Node\")).label().fold())\n", | ||
" .dedup()" | ||
] | ||
}, | ||
{ | ||
|
@@ -215,11 +222,12 @@ | |
"outputs": [], | ||
"source": [ | ||
"%%gremlin \n", | ||
"kh.containers().\n", | ||
" or(\n", | ||
"kh.containers()\n", | ||
" .has(\"runID\", graph.variables().get('runID_yourid').get())\n", | ||
" .or(\n", | ||
" has(\"image\", TextP.containing(\"nginx\")), // Replace with your image name\n", | ||
" has(\"image\", TextP.containing(\"cilium\"))). // Replace with your image name\n", | ||
" minHopsToCritical()" | ||
" has(\"image\", TextP.containing(\"cilium\"))) // Replace with your image name\n", | ||
" .minHopsToCritical()" | ||
] | ||
}, | ||
{ | ||
|
@@ -236,23 +244,21 @@ | |
"outputs": [], | ||
"source": [ | ||
"%%gremlin -d class -g critical -le 50 -p inv,oute\n", | ||
"kh.containers().\n", | ||
" or(\n", | ||
"kh.containers()\n", | ||
" .has(\"runID\", graph.variables().get('runID_yourid').get())\n", | ||
" .or(\n", | ||
" has(\"image\", TextP.containing(\"nginx\")), // Replace with your image name\n", | ||
" has(\"image\", TextP.containing(\"cilium\"))). // Replace with your image name\n", | ||
" \n", | ||
" repeat(\n", | ||
" outE().inV().simplePath()).\n", | ||
" emit().\n", | ||
" until(\n", | ||
" has(\"critical\", true).\n", | ||
" or().\n", | ||
" loops().\n", | ||
" is(4)). // Use result from previous cell\n", | ||
" has(\"critical\", true).\n", | ||
" dedup().\n", | ||
" path().\n", | ||
" by(elementMap())" | ||
" has(\"image\", TextP.containing(\"cilium\"))) // Replace with your image name\n", | ||
" .repeat(\n", | ||
" outE().inV().simplePath())\n", | ||
" .emit()\n", | ||
" .until(\n", | ||
" has(\"critical\", true)\n", | ||
" .or().loops().is(4))\n", | ||
" .has(\"critical\", true)\n", | ||
" .dedup()\n", | ||
" .path()\n", | ||
" .by(elementMap())" | ||
] | ||
}, | ||
{ | ||
|
@@ -271,17 +277,18 @@ | |
"outputs": [], | ||
"source": [ | ||
"%%gremlin -d name -g class -le 50 -p inv,oute\n", | ||
"kh.containers().\n", | ||
" or(\n", | ||
"kh.containers()\n", | ||
" .has(\"runID\", graph.variables().get('runID_yourid').get())\n", | ||
" .or(\n", | ||
" has(\"image\", TextP.containing(\"nginx\")),\n", | ||
" has(\"image\", TextP.containing(\"cilium\"))).\n", | ||
" \trepeat(\n", | ||
" outE().inV().simplePath()).\n", | ||
" times(5). // Increase to expand the potential blast radius, but graph size will increase exponentially!\n", | ||
" emit().\n", | ||
" path().\n", | ||
" by(elementMap()).\n", | ||
" limit(100) // Limit the number of results for large clusters" | ||
" has(\"image\", TextP.containing(\"cilium\")))\n", | ||
" \t.repeat(\n", | ||
" outE().inV().simplePath())\n", | ||
" .times(5) // Increase to expand the potential blast radius, but graph size will increase exponentially!\n", | ||
" .emit()\n", | ||
" .path()\n", | ||
" .by(elementMap())\n", | ||
" .limit(100) // Limit the number of results for large clusters" | ||
] | ||
} | ||
], | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": { | ||
"execution": { | ||
"iopub.execute_input": "2024-07-24T14:46:25.538529Z", | ||
"iopub.status.busy": "2024-07-24T14:46:25.538280Z", | ||
"iopub.status.idle": "2024-07-24T14:46:25.545724Z", | ||
"shell.execute_reply": "2024-07-24T14:46:25.545041Z", | ||
"shell.execute_reply.started": "2024-07-24T14:46:25.538501Z" | ||
}, | ||
"frozen": false, | ||
"init_cell": true, | ||
"tags": [ | ||
"safe_output" | ||
] | ||
}, | ||
"source": [ | ||
"# Autoloading\n", | ||
"\n", | ||
"Loading graph visualisation settings." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"init_cell": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"%%capture \"Remove this line to see debug information\"\n", | ||
"%%graph_notebook_vis_options\n", | ||
"{\n", | ||
" \"edges\": {\n", | ||
" \"smooth\": {\n", | ||
" \"enabled\": true,\n", | ||
" \"type\": \"dynamic\"\n", | ||
" },\n", | ||
" \"arrows\": {\n", | ||
" \"to\": {\n", | ||
" \"enabled\": true,\n", | ||
" \"type\": \"arrow\"\n", | ||
" }\n", | ||
" }\n", | ||
" }\n", | ||
"}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": { | ||
"frozen": false, | ||
"tags": [ | ||
"unsafe_output" | ||
] | ||
}, | ||
"source": [ | ||
"# Initial Setup\n", | ||
"\n", | ||
"## Get a view of all Ingested Cluster\n", | ||
"\n", | ||
"Retrieve all the current cluster ingested in KubeHound with the associated runID with the number of nodes. This numbers can be used to get a clue of the size of the cluster and also identify if an ingestion did not complete." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"execution": { | ||
"iopub.execute_input": "2024-07-24T14:46:28.273187Z", | ||
"iopub.status.busy": "2024-07-24T14:46:28.272852Z", | ||
"iopub.status.idle": "2024-07-24T14:46:28.625859Z", | ||
"shell.execute_reply": "2024-07-24T14:46:28.625126Z", | ||
"shell.execute_reply.started": "2024-07-24T14:46:28.273156Z" | ||
}, | ||
"frozen": false, | ||
"init_cell": true, | ||
"tags": [ | ||
"safe_output" | ||
] | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"%%gremlin -d class -g critical -le 50 -p inv,oute\n", | ||
"\n", | ||
"kh.nodes()\n", | ||
" .groupCount()\n", | ||
" .by(project('cluster','runID')\n", | ||
" .by('cluster').by('runID'))\n", | ||
" .unfold()\n", | ||
" .limit(1000)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": { | ||
"frozen": false, | ||
"tags": [ | ||
"unsafe_output" | ||
] | ||
}, | ||
"source": [ | ||
"## Setting your run_id/cluster\n", | ||
"\n", | ||
"Set which runID you want to use. The variable are being shared with all users of the instance, so we advise to make a uniq string for your user `runID_yourid` to avoid any conflict." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"frozen": false, | ||
"tags": [ | ||
"safe_output" | ||
] | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"%%gremlin -d class -g critical -le 50 -p inv,oute\n", | ||
"\n", | ||
"graph.variables()\n", | ||
" .set('runID_yourid','01htdgjj34mcmrrksw4bjy2e94')" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"celltoolbar": "Initialization Cell", | ||
"kernelspec": { | ||
"display_name": "Python 3 (default)", | ||
"language": "python", | ||
"name": "ipykernel-default" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.10.13" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.