Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ services:
networks:
a-grfics-admin: # gets random bridge IP (e.g., 172.18.x.x)
b-ics-net:
ipv4_address: 192.168.95.10
ipv4_address: 192.168.95.45

# Optional if you want to override default CMD
# command: sh -c "./simulation/simulation & cd modbus && ./run_all.sh"
Expand Down
85 changes: 55 additions & 30 deletions simulation/web_visualization/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -311,12 +311,42 @@

<script>
var unityInstance = null;
const toolPorts = { attacker: 6088, defender: 6080, caldera: 8888 };

function openToolPort(port) {
const proto = window.location.protocol; // http: or https:
const host = window.location.hostname; // localhost or 192.168.1.3 or lab.example.com
window.open(`${proto}//${host}:${port}/`, "_blank", "noopener,noreferrer");
const toolEndpoints = {
"localhost": {
attacker: "http://localhost:6088/",
defender: "http://localhost:6080/",
caldera: "http://localhost:8888/"
},
"127.0.0.1": {
attacker: "http://127.0.0.1:6088/",
defender: "http://127.0.0.1:6080/",
caldera: "http://127.0.0.1:8888/"
},
"192.168.95.45": {
attacker: "http://192.168.90.6:6080/",
defender: "http://192.168.95.5:6080/",
caldera: "http://192.168.90.250:8888/"
}
};

function openTool(name) {
const host = window.location.hostname;
const endpoints = toolEndpoints[host] || toolEndpoints["localhost"];
const url = endpoints[name];

if (!url) {
alert(`No URL configured for ${name} on host ${host}`);
return;
}

window.open(url, "_blank", "noopener,noreferrer");
}

function getToolUrl(name) {
const host = window.location.hostname;
const endpoints = toolEndpoints[host] || toolEndpoints["localhost"];
return endpoints[name] || null;
}

function setStatus(text, color) {
Expand Down Expand Up @@ -359,13 +389,21 @@
}
}

async function checkPort(port) {
const url = `${location.protocol}//${location.hostname}:${port}/`;
async function checkTool(name) {
const url = getToolUrl(name);
if (!url) {
return false;
}

try {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), 900);

await fetch(url, { mode: "no-cors", cache: "no-store", signal: ctrl.signal });
await fetch(url, {
mode: "no-cors",
cache: "no-store",
signal: ctrl.signal
});

clearTimeout(t);
return true;
Expand Down Expand Up @@ -404,9 +442,9 @@

async function pollOnce() {
const [attOk, defOk, calOk] = await Promise.all([
checkPort(toolPorts.attacker),
checkPort(toolPorts.defender),
checkPort(toolPorts.caldera),
checkTool("attacker"),
checkTool("defender"),
checkTool("caldera"),
]);

applyStabilizedResult("attacker", attOk);
Expand Down Expand Up @@ -501,7 +539,7 @@ <h1>GRFICSv3</h1>

<div class="section-title">Connect</div>

<button class="btn" onclick="openToolPort(6088)">
<button class="btn" onclick="openTool('attacker')">
<div class="icon">🟥</div>
<div class="meta">
<div class="label">Attacker Workstation</div>
Expand All @@ -514,7 +552,7 @@ <h1>GRFICSv3</h1>
</div>
</button>

<button class="btn" onclick="openToolPort(6080)">
<button class="btn" onclick="openTool('defender')">
<div class="icon">🟦</div>
<div class="meta">
<div class="label">Defender Workstation</div>
Expand All @@ -527,7 +565,7 @@ <h1>GRFICSv3</h1>
</div>
</button>

<button class="btn" onclick="openToolPort(8888)">
<button class="btn" onclick="openTool('caldera')">
<div class="icon">🌋</div>
<div class="meta">
<div class="label">Caldera</div>
Expand Down Expand Up @@ -560,8 +598,8 @@ <h1>GRFICSv3</h1>
<div class="topbar">
<div class="title">Chemical Plant Simulation</div>
<div class="actions">
<button class="small-btn" onclick="openToolPort(6088)">Attacker</button>
<button class="small-btn" onclick="openToolPort(6080)">Defender</button>
<button class="small-btn" onclick="openTool('attacker')">Attacker</button>
<button class="small-btn" onclick="openTool('defender')">Defender</button>
<button class="small-btn" onclick="unityInstance && unityInstance.SetFullscreen(1)">Fullscreen</button>
</div>
</div>
Expand All @@ -572,18 +610,5 @@ <h1>GRFICSv3</h1>
</main>
</div>

<script>
// Fill in the displayed URLs using current hostname (so no "localhost" hardcoding).
(function () {
const proto = window.location.protocol;
const host = window.location.hostname;
const attacker = `${proto}//${host}:6088/`;
const defender = `${proto}//${host}:6080/`;
const aEl = document.getElementById("attackerUrlText");
const dEl = document.getElementById("defenderUrlText");
if (aEl) aEl.textContent = attacker;
if (dEl) dEl.textContent = defender;
})();
</script>
</body>
</html>
</html>
2 changes: 1 addition & 1 deletion workstation/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ RUN apt-get update && \

# Add user
RUN useradd -m -s /bin/bash ${USERNAME} && \
echo "${USERNAME}:plc123" | chpasswd && \
echo "${USERNAME}:zxcvbnm" | chpasswd && \
usermod -aG sudo ${USERNAME}

# Install noVNC + websockify
Expand Down
Loading