From 9adf4da0d1a19d5d50bb6f2f9a73822066c653df Mon Sep 17 00:00:00 2001 From: Marco Wende Date: Mon, 21 Sep 2026 13:28:43 +0200 Subject: [PATCH] =?UTF-8?q?Docker:=20Test-Setup=20f=C3=BCr=20self-hosted?= =?UTF-8?q?=20Betrieb=20(ohne=20=C3=84nderung=20des=20App-Teils)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neuer Ordner docker/ (Dockerfile, docker-entrypoint.sh, docker-compose.yml, README). Der bestehende App-/Client-Teil (Start.ps1, src/, www/) bleibt unverändert und wird nur ins Image kopiert. Container-Spezifika laufen ohne Codeeingriff: - socat-Bridge 0.0.0.0:8080 -> 127.0.0.1:8077 (App bindet weiter nur loopback) - Datenpfad via XDG_CONFIG_HOME=/data (Volume) - Get-AppDataDir nutzt das auf Linux - Login über den vorhandenen Device-Code-Flow (WAM/Loopback geht im Container nicht) Kein Caddy: der vorhandene Reverse-Proxy zieht Port 8080 an. Co-Authored-By: Claude Opus 4.8 --- docker/Dockerfile | 35 ++++++++++++++++++ docker/README.md | 74 +++++++++++++++++++++++++++++++++++++ docker/docker-compose.yml | 21 +++++++++++ docker/docker-entrypoint.sh | 14 +++++++ 4 files changed, 144 insertions(+) create mode 100644 docker/Dockerfile create mode 100644 docker/README.md create mode 100644 docker/docker-compose.yml create mode 100755 docker/docker-entrypoint.sh diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..a1cb5fc --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,35 @@ +# Intune Manager - Test-Image (self-hosted). +# WICHTIG: Der bestehende App-/Client-Teil wird NICHT veraendert - Start.ps1, src/ +# und www/ werden nur unveraendert ins Image kopiert. Die einzigen Container- +# Spezifika (Bridge fuer den localhost-Listener, Datenpfad, Login) laufen ueber +# Env-Variablen bzw. das Entrypoint-Script - ohne Codeaenderung. +FROM mcr.microsoft.com/powershell:7.4-debian-12 + +# socat = Bridge 0.0.0.0:BRIDGE_PORT -> 127.0.0.1:APP_PORT (App bindet nur loopback). +# git = fuer das optionale Policy-Git-Snapshot-Feature. +RUN apt-get update \ + && apt-get install -y --no-install-recommends socat git ca-certificates \ + && rm -rf /var/lib/apt/lists/* \ + && pwsh -NoProfile -Command "Install-Module Microsoft.Graph.Authentication -Scope AllUsers -Force" + +WORKDIR /app + +# Bestehende App unveraendert ins Image kopieren (Build-Kontext = Repo-Root). +COPY Start.ps1 ./ +COPY src/ ./src/ +COPY www/ ./www/ + +# Entrypoint (neu, nur fuer den Container). +COPY docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +# Datenverzeichnis: Get-AppDataDir nutzt auf Linux $XDG_CONFIG_HOME -> +# Settings/Policy-Exporte landen im Volume /data. Kein Codeeingriff noetig. +ENV XDG_CONFIG_HOME=/data \ + APP_PORT=8077 \ + BRIDGE_PORT=8080 + +VOLUME /data +EXPOSE 8080 + +ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..7f80470 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,74 @@ +# Intune Manager - Docker-Test (self-hosted) + +Test-Aufbau, um den Intune Manager als Container zu verproben. **Der bestehende +App-/Client-Teil (`Start.ps1`, `src/`, `www/`) wird nicht verändert** — er wird nur +unverändert ins Image kopiert. Container-Spezifika laufen über Env-Variablen und ein +Entrypoint-Script. + +> Kein Caddy/TLS enthalten — der **vorhandene Reverse-Proxy** zieht den +> veröffentlichten Port (`8080`) an. HTTPS macht der Proxy. + +## Wie es funktioniert +- Die App bindet unverändert auf `http://localhost:8077/` (nur containerintern). +- Ein **socat-Bridge** im Container leitet `0.0.0.0:8080 → 127.0.0.1:8077` — dadurch ist + die App von außen erreichbar, ohne den App-Code anzufassen. +- Settings/Policy-Exporte liegen im Volume `/data` (`XDG_CONFIG_HOME=/data`, wird von + `Get-AppDataDir` auf Linux automatisch genutzt). + +## Bauen & starten +```bash +docker compose -f docker/docker-compose.yml up --build -d +``` +Logs ansehen: +```bash +docker compose -f docker/docker-compose.yml logs -f +``` +Erwartet: „Intune Manager - Web Edition" und „URL: http://localhost:8077/". + +Den Reverse-Proxy auf `http://:8080` zeigen lassen (reiner HTTP-Proxy, +keine WebSockets/Callbacks nötig). + +## Erststart: Verbindung konfigurieren +Beim ersten Start ist noch kein Tenant hinterlegt. Zwei Wege: + +- **UI:** Seite öffnen → *Einstellungen* → **Tenant-ID**, **Client-ID** (Read/Write), + optional **Client-ID (Read-Only)** und **Scopes** eintragen und speichern. Landet in + `/data/IntuneAppManager-Web/settings.json`. +- **oder** eine vorhandene `settings.json` ins Volume legen: + ```bash + docker cp settings.json intune-manager-test:/data/IntuneAppManager-Web/settings.json + docker compose -f docker/docker-compose.yml restart + ``` + +## Login (Device-Code) +Der interaktive „Verbinden"-Button nutzt WAM/Loopback und **funktioniert im Container +nicht** — das ist erwartet. Für den Test den bereits vorhandenen **Device-Code-Flow** +per `curl` anstoßen (Host = euer Reverse-Proxy oder `http://:8080`): + +```bash +curl -s -X POST http:///api/connect/start +``` +Antwort enthält `code` und `urlComplete`. Dann: +1. `urlComplete` im Browser öffnen und als Admin anmelden. +2. Status pollen, bis verbunden: + ```bash + curl -s http:///api/status + ``` + (Feld `connected` wird `true`.) +3. Die UI im Browser **neu laden** → jetzt verbunden. Geräte/Gruppen/Policies laden + zum Verifizieren. + +## Stoppen / Aufräumen +```bash +docker compose -f docker/docker-compose.yml down # Daten bleiben im Volume +docker compose -f docker/docker-compose.yml down -v # inkl. Daten löschen +``` + +## Wichtige Hinweise (für den echten Einsatz) +- **Kein eigener UI-Login und geteilte Sitzung:** Wer die URL erreicht, kann den Login + auslösen; die verbundene Graph-Sitzung gilt prozessweit. Die Instanz **zwingend hinter + Zugangsschutz** stellen (Reverse-Proxy-Auth / Netzsegment / VPN). Eine Instanz = + eine Team-Sitzung, kein sauberes Multi-Admin. +- Reports liegen unter `/tmp` (nicht persistent) — für den Test ausreichend. +- Das ist ein **Test-Setup**. Echtes Mehrbenutzer (Login pro Admin) wäre ein separater + Ausbau (Auth-Code-Flow + Sitzungs-Isolation). diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..532d004 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,21 @@ +# Intune Manager - Test-Compose (self-hosted). +# Kein Caddy/TLS: der bestehende Reverse-Proxy zieht den veroeffentlichten Port an. +services: + intune-manager: + build: + context: .. # Build-Kontext = Repo-Root (fuer COPY Start.ps1/src/www) + dockerfile: docker/Dockerfile + image: intune-manager-test + container_name: intune-manager-test + ports: + - "8080:8080" # :8080 -> vom Reverse-Proxy anziehen + volumes: + - im-data:/data # settings.json + policy-exports persistent + environment: + - XDG_CONFIG_HOME=/data + - APP_PORT=8077 + - BRIDGE_PORT=8080 + restart: unless-stopped + +volumes: + im-data: diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh new file mode 100755 index 0000000..528c77a --- /dev/null +++ b/docker/docker-entrypoint.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# Startet die App unveraendert (bindet auf 127.0.0.1:APP_PORT) und leitet externe +# Verbindungen per socat-Bridge dorthin - so bleibt der App-Code unangetastet. +set -e + +: "${APP_PORT:=8077}" +: "${BRIDGE_PORT:=8080}" + +# Bridge im Hintergrund: 0.0.0.0:BRIDGE_PORT -> 127.0.0.1:APP_PORT +# (fork = pro Verbindung ein Prozess; reuseaddr = schneller Neustart). +socat "TCP-LISTEN:${BRIDGE_PORT},fork,reuseaddr" "TCP:127.0.0.1:${APP_PORT}" & + +# App im Vordergrund (Logs -> stdout). -NoBrowser: im Container kein Desktop/open. +exec pwsh -NoProfile -File /app/Start.ps1 -NoBrowser -Port "${APP_PORT}"