-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
49e9283
commit 7b38788
Showing
37 changed files
with
4,205 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,2 @@ | ||
HOST_IP=172.18.0.20 | ||
NEO4J_PASSWORD=ChangeMe |
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 @@ | ||
__pycache__/ |
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,56 @@ | ||
 | ||
|
||
# OSAKA | ||
Outil de Sécurité des Architectures Kubernetes Avancées | ||
Advanced Kubernetes Architecture Security Tool | ||
|
||
This tool allows to perform the reconstruction of complex attack paths by graph generation in a Kubernetes cluster. It uses Neo4j for the | ||
storage of objects and relationships in database as well as neodash for visualization. The language Cypher | ||
as MySQL allows queries to the database to retrieve graphs. | ||
It can be used by security auditors to quickly identify attack paths or security experts to monitor theses paths. | ||
|
||
There are four microservices within the tool : | ||
- osaka-database | ||
- osaka-loader | ||
- osaka-visualizer | ||
- osaka-editor | ||
|
||
The tool was not designed in a secure development model, it is necessary to deploy it in an isolated and controlled environment. Also, it is recommended to install a HTTPS reverse proxy in front of the application. | ||
|
||
## Prerequisites : | ||
- Docker | ||
- Docker Compose | ||
|
||
## Installation | ||
Configure the environment variables in the. env file at project root but also at sources/. env : | ||
*HOST_IP* is the host system IP address | ||
*NEO4J_PASSWORD* is the database password | ||
|
||
### Build and run | ||
```sh | ||
$ cd osaka/build | ||
$ chmod +x build.sh | ||
$ ./build.sh | ||
``` | ||
### To stop the services : | ||
```sh | ||
$ cd osaka | ||
$ docker compose down | ||
``` | ||
### To start the services : | ||
```sh | ||
$ cd osaka | ||
$ docker compose up -d | ||
``` | ||
|
||
## Usage | ||
### Data collection | ||
Run the collect.sh script in the "tools" directory with a kubectl binary and an access to kube-apiserver, then retrieve the "collect-*. zip" and upload the file to the osaka-loader service on port 8080 | ||
```sh | ||
$ ./collect.sh | ||
``` | ||
### Reading attack paths | ||
The osaka-visualizer service allows to consult the dashboard in read-only mode. An access to the service can be provided to the beneficiary during an audit (::8082) | ||
|
||
### Customizing graphs | ||
It is necessary to configure the osaka-editor service with the value of *NEO4J_PASSWORD* located in the .env. This gives write access to the dashboard and allows the modification of cypher queries, etc... (::8081) |
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,9 @@ | ||
#!/bin/bash | ||
|
||
git clone https://github.com/neo4j-labs/neodash.git | ||
sed -i 's\Warning: NeoDash is running with a plaintext password in config.json.\\g' neodash/src/dashboard/Dashboard.tsx | ||
|
||
docker rmi pythonloader | ||
docker rmi visualizer | ||
docker compose --env-file ../.env -f ../compose.yml up -d | ||
rm -rf neodash |
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,19 @@ | ||
# Distroless image | ||
|
||
FROM python:3.12-slim AS build-env | ||
RUN groupadd -g 1001 python \ | ||
&& useradd --uid 1001 --gid python --shell /bin/bash --create-home python | ||
WORKDIR /loader | ||
ADD . . | ||
RUN pip install --disable-pip-version-check -r requirements.txt | ||
RUN chown -R python:python /loader | ||
|
||
|
||
FROM gcr.io/distroless/python3-debian12 | ||
COPY --from=build-env /loader /loader | ||
COPY --from=build-env /usr/local/lib/ /usr/local/lib/ | ||
COPY --from=build-env /usr/local/bin /usr/local/bin | ||
ENV PYTHONPATH=/usr/local/lib/python3.12/site-packages | ||
USER 1001 | ||
WORKDIR /loader | ||
ENTRYPOINT ["/usr/local/bin/python3.12","app.py"] |
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,12 @@ | ||
# Non distroless image | ||
|
||
FROM python:3.12.6 | ||
RUN groupadd -g 1001 python \ | ||
&& useradd --uid 1001 --gid python --shell /bin/bash --create-home python | ||
|
||
WORKDIR /loader | ||
ADD . . | ||
RUN chown -R python:python /loader | ||
USER 1001 | ||
RUN pip install --no-cache-dir -r requirements.txt | ||
CMD ["python", "app.py"] |
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,77 @@ | ||
services: | ||
volume-perm-job: | ||
image: alpine | ||
user: "root" | ||
group_add: | ||
- 1001 | ||
volumes: | ||
- /opt/db:/opt/db | ||
command: chown -R 1001:1001 /opt/db | ||
networks: | ||
net: | ||
database: | ||
image: neo4j:5.24.2 | ||
ports: | ||
- 7474:7474 | ||
- 7687:7687 | ||
- 7473:7473 | ||
volumes: | ||
- "/opt/db:/data" | ||
user: 1001:1001 | ||
environment: | ||
- NEO4J_AUTH=neo4j/${NEO4J_PASSWORD} | ||
networks: | ||
net: | ||
ipv4_address: 172.18.0.20 | ||
restart: always | ||
editor: | ||
image: neo4jlabs/neodash:2.4.8 | ||
ports: | ||
- 8081:5005 | ||
networks: | ||
net: | ||
ipv4_address: 172.18.0.21 | ||
restart: always | ||
loader: | ||
image: pythonloader | ||
build: | ||
context: sources | ||
dockerfile: ../build/loader/Dockerfile | ||
ports: | ||
- 8080:5000 | ||
networks: | ||
net: | ||
ipv4_address: 172.18.0.22 | ||
restart: always | ||
visualizer: | ||
image: visualizer | ||
build: | ||
context: build/neodash | ||
dockerfile: Dockerfile | ||
ports: | ||
- 8082:5005 | ||
environment: | ||
- standalone=true | ||
- standaloneProtocol=neo4j | ||
- standaloneHost=${HOST_IP} | ||
- standalonePort=7687 | ||
- standaloneDatabase=neo4j | ||
- standaloneUsername=neo4j | ||
- standalonePassword=${NEO4J_PASSWORD} | ||
- standaloneDashboardName=Dashboard | ||
- standaloneDashboardDatabase=neo4j | ||
networks: | ||
net: | ||
ipv4_address: 172.18.0.23 | ||
restart: always | ||
|
||
volumes: | ||
db: | ||
driver: local | ||
|
||
networks: | ||
net: | ||
driver: bridge | ||
ipam: | ||
config: | ||
- subnet: 172.18.0.0/24 |
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,5 @@ | ||
NEO4J_URI=neo4j://172.18.0.20:7687 | ||
NEO4J_USER=neo4j | ||
NEO4J_PASSWORD=ChangeMe | ||
NEO4J_VERSION=4 | ||
NEO4J_DATABASE=neo4j |
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,50 @@ | ||
import os | ||
from main import main | ||
from flask_assets import Environment, Bundle | ||
from flask import Flask, flash, request, redirect, render_template | ||
from werkzeug.utils import secure_filename | ||
from waitress import serve | ||
|
||
|
||
pwd = os.getcwd() | ||
path = pwd + "/main.py" | ||
UPLOAD_FOLDER = pwd + "/uploads" | ||
ALLOWED_EXTENSIONS = {'zip'} | ||
|
||
app = Flask(__name__) | ||
app.secret_key = "super secret key" | ||
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER | ||
env = Environment(app) | ||
js = Bundle('js/clarity-icons.min.js', 'js/clarity-icons-api.js', | ||
'js/clarity-icons-element.js', 'js/custom-elements.min.js') | ||
env.register('js_all', js) | ||
css = Bundle('css/clarity-ui.min.css', 'css/clarity-icons.min.css') | ||
env.register('css_all', css) | ||
|
||
|
||
def allowed_file(filename): | ||
return '.' in filename and \ | ||
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS | ||
|
||
|
||
@app.route('/', methods=['GET', 'POST']) | ||
def upload_file(): | ||
error = None | ||
if request.method == 'POST': | ||
if 'file' not in request.files: | ||
flash('No file part') | ||
return redirect(request.url) | ||
file = request.files['file'] | ||
if file.filename == '': | ||
error = "No selected file" | ||
return render_template('index.html', error=error) | ||
if file and allowed_file(file.filename): | ||
filename = secure_filename(file.filename) | ||
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) | ||
return render_template('index.html', name=filename), main(filename) | ||
return render_template('index.html', error=error) | ||
|
||
|
||
if __name__ == '__main__': | ||
#app.run(host="0.0.0.0", port=5000, debug=True) | ||
serve(app, host="0.0.0.0", port=5000) |
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,21 @@ | ||
from neo4j import GraphDatabase, basic_auth | ||
from src.common import utils | ||
from src.Loader import loader, dashboard | ||
from src.Database import init, relationships | ||
import settings | ||
import os | ||
|
||
|
||
def main(filename): | ||
pwd = os.getcwd() | ||
path = pwd + "/uploads/" + filename.split(".")[0] | ||
|
||
driver = GraphDatabase.driver(settings.url, auth=basic_auth(settings.username, settings.password)) | ||
driver.verify_connectivity() | ||
|
||
init.setup(driver) | ||
utils.extract_zipfile(pwd, filename) | ||
loader.data(path, driver) | ||
relationships.Add(driver) | ||
dashboard.push(driver) | ||
|
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,14 @@ | ||
blinker==1.8.2 | ||
click==8.1.7 | ||
Flask==3.0.3 | ||
Flask-Assets==2.1.0 | ||
itsdangerous==2.2.0 | ||
Jinja2==3.1.4 | ||
MarkupSafe==2.1.5 | ||
neo4j==5.24.0 | ||
python-dotenv==1.0.1 | ||
pytz==2024.2 | ||
PyYAML==6.0.2 | ||
waitress==3.0.0 | ||
webassets==2.0 | ||
Werkzeug==3.0.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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import os | ||
from dotenv import load_dotenv | ||
|
||
load_dotenv() | ||
|
||
url = os.getenv("NEO4J_URI") | ||
username = os.getenv("NEO4J_USER") | ||
password = os.getenv("NEO4J_PASSWORD") | ||
neo4j_version = os.getenv("NEO4J_VERSION") | ||
neo4j_database = os.getenv("NEO4J_DATABASE") |
Empty file.
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,10 @@ | ||
def setup(driver): | ||
query = """ | ||
MATCH (n) DETACH DELETE n | ||
""" | ||
driver.execute_query(query) | ||
|
||
query = """ | ||
CREATE (c:ClusterAdmins { Name : "CLUSTER ADMINS" }) | ||
""" | ||
driver.execute_query(query) |
Oops, something went wrong.