Skip to content

Commit

Permalink
feat: wind turbine model using OT-sim and Docker
Browse files Browse the repository at this point in the history
  • Loading branch information
activeshadow committed Nov 17, 2023
0 parents commit e418e87
Show file tree
Hide file tree
Showing 29 changed files with 44,245 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
configs/weather.csv filter=lfs diff=lfs merge=lfs -text
32 changes: 32 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Publish Docker Image
on:
- push
jobs:
push-to-ghcr:
name: Push tools Docker image to GitHub Packages
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Get short SHA
run: |
echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "branch=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV
- name: Log in to GitHub Docker Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build container image
uses: docker/build-push-action@v3
with:
context: .
file: Dockerfile.tools
push: true
tags: |
ghcr.io/${{ github.repository }}/tools:${{ env.sha }}
ghcr.io/${{ github.repository }}/tools:${{ env.branch }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
configs/grafana/plugins/*
!configs/grafana/plugins/.gitkeep
28 changes: 28 additions & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
tasks:
- init: |
git lfs pull
curl -L -o /tmp/opensearch.zip "https://grafana.com/api/plugins/grafana-opensearch-datasource/versions/2.13.0/download?os=linux&arch=amd64"
unzip -d configs/grafana/plugins /tmp/opensearch.zip
docker-compose pull wireshark main-ctlr opensearch grafana
- command: |
docker-compose up -d
ports:
- port: 1880
name: HMI
description: Turbine HMI (at /ui path)
- port: 3000
name: Grafana
description: Turbine Status Dashboard
- port: 8080
name: Wireshark
description: Wireshark GUI (at /vnc.html path)
- port: 8090
name: Adversary
description: Adversary Desktop (at /vnc.html path)

vscode:
extensions:
- ms-azuretools.vscode-docker
41 changes: 41 additions & 0 deletions Dockerfile.tools
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
FROM debian:bookworm

RUN echo "wireshark-common wireshark-common/install-setuid boolean false" | debconf-set-selections

RUN apt update \
&& apt install -y --no-install-recommends \
ca-certificates \
dsniff \
lxterminal \
htop \
iptables \
iproute2 \
nano \
novnc \
openbox \
python3 \
python3-pip \
supervisor \
tcpdump \
tigervnc-standalone-server \
tint2 \
tmux \
tshark \
vim \
wireshark \
xdg-utils \
&& rm -rf /var/lib/apt/lists \
&& mkdir -p /usr/share/desktop-directories

RUN python3 -m pip install --break-system-packages mitmproxy

COPY configs/docker/openbox-menu.xml /root/.config/openbox/menu.xml
COPY configs/docker/tint2rc /root/.config/tint2/tint2rc
COPY configs/docker/supervisord.conf /etc/

RUN cp /etc/xdg/openbox/rc.xml /root/.config/openbox/rc.xml \
&& sed -i 's/Clearlooks/Nightmare-01/g' /root/.config/openbox/rc.xml

EXPOSE 8080

CMD ["supervisord", "-c", "/etc/supervisord.conf"]
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Wind Turbine Control Model

This repo contains the relevant Docker and
[OT-sim](https://github.com/patsec/ot-sim) configuration files required to
simulate the control portion of a wind turbine. The turbine controls represented
in this model are simplistic, and are meant to be the basis for developing a
more accurate representation of such controls.

## Getting Started

Run the following after cloning this content.

```
git lfs pull
curl -L -o /tmp/opensearch.zip "https://grafana.com/api/plugins/grafana-opensearch-datasource/versions/2.13.0/download?os=linux&arch=amd64"
unzip -d configs/grafana/plugins /tmp/opensearch.zip
docker-compose pull wireshark main-ctlr opensearch grafana
docker compose up -d
```

You can then access the Node-RED UI [here](http://localhost:1880/ui).

There is also a Grafana dashboard available
[here](http://localhost:3000/d/IUzSfUhVz/turbine).

A container running the Wireshark UI can be accessed
[here](http://localhost:8080/vnc.html).

An adversary container can be accessed [here](http://localhost:8090/vnc.html).
It contains a script, `attack.sh`, that can be run to conduct an AitM attack
against the turbine's main controller and the anemometer. This is a contrived
attack, but is a good example of AitMing the Modbus protocol none-the-less.

## Gitpod Deployment

This repo can alternatively be launched in
[Gitpod](https://gitpod.io/#https://github.com/patsec/wind-turbine).
20 changes: 20 additions & 0 deletions configs/docker/openbox-menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<openbox_menu xmlns="http://openbox.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openbox.org/ file:///usr/share/openbox/menu.xsd">
<menu id="root-menu" label="Openbox 3">
<item label="Wireshark">
<action name="Execute">
<execute>/usr/bin/wireshark</execute>
</action>
</item>
<item label="Terminal">
<action name="Execute">
<execute>/usr/bin/x-terminal-emulator</execute>
</action>
</item>
<item label="Htop">
<action name="Execute">
<execute>/usr/bin/x-terminal-emulator -e htop</execute>
</action>
</item>
</menu>
</openbox_menu>
35 changes: 35 additions & 0 deletions configs/docker/supervisord.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[supervisord]
nodaemon=true
user=root
pidfile=/tmp/supervisord.pid
logfile=/dev/fd/1
logfile_maxbytes=0

[program:websockify]
priority=0
command=/usr/bin/websockify --web /usr/share/novnc 8080 localhost:5900
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true

[program:openbox]
priority=1
command=/usr/bin/openbox
environment=DISPLAY=:1
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true

[program:tint2]
priority=1
command=/usr/bin/tint2
environment=DISPLAY=:1
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true

[include]
files = /etc/supervisor/conf.d/*.conf
8 changes: 8 additions & 0 deletions configs/docker/tigervnc-adversary.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[program:x11]
priority=0
command=/usr/bin/Xtigervnc -desktop "Adversary" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :1
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true

8 changes: 8 additions & 0 deletions configs/docker/tigervnc-wireshark.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[program:x11]
priority=0
command=/usr/bin/Xtigervnc -desktop "Wireshark" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :1
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true

3 changes: 3 additions & 0 deletions configs/docker/tint2rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
panel_items = T
taskbar_name = 0
background_color = #7F1E31 100
9 changes: 9 additions & 0 deletions configs/docker/wireshark.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[program:wireshark]
priority=1
environment=DISPLAY=:1
command=/usr/bin/wireshark
autorestart=false
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true

6 changes: 6 additions & 0 deletions configs/grafana/dashboards.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: 1
providers:
- name: default
type: file
options:
path: /var/lib/grafana/dashboards
4 changes: 4 additions & 0 deletions configs/grafana/grafana.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[auth.anonymous]
enabled = true
org_name = Main Org.
org_role = Admin
13 changes: 13 additions & 0 deletions configs/grafana/opensearch-data-source.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: 1
datasources:
- name: WindTurbine
isDefault: true
type: grafana-opensearch-datasource
access: proxy
url: http://opensearch:9200
jsonData:
database: '[wind-turbine-]YYYY.MM.DD'
interval: 'Daily'
timeField: '@timestamp'
flavor: 'opensearch'
version: '2.10.0'
Empty file.
Loading

0 comments on commit e418e87

Please sign in to comment.