Neu: - Administrative Vorlagen (ADMX / groupPolicyConfigurations) als vierter Policy-Typ fuer Export/Import (GET /api/policies/administrativetemplate) - Zuweisung direkt nach Import: pro Policy Include-/Exclude-Gruppen (POST /api/policies/assign, typ-spezifische /assign-Action) - Git-Snapshot: versioniertes Policy-Backup in lokalen Git-Ordner (Settings-Sektion policyBackup) - Import akzeptiert Git-Snapshot-Dateien (policyType neben exportType) Behoben: - Settings-Catalog-Import schema-konform: Collection-Properties immer als Array (repariert PS-5.1-Roundtrip), null -> [], Wrapper-@odata.type, read-only id entfernt - Import-Phantom-Fehler (@($null)-Geisterdurchlauf im Archiv-Pfad) - Frontend-Cache-Reset beim Tenant-Wechsel (resetClientState) - WAM-Anmeldefenster zuverlaessig im Vordergrund (AttachThreadInput) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Intune Manager – Web Edition
Modernes Web-Frontend fuer den Intune Manager. PowerShell startet einen lokalen HTTP-Server, der das Frontend ausliefert und die Microsoft Graph-Aufrufe ausfuehrt.
Voraussetzungen
- Windows mit PowerShell 5.1 oder PowerShell 7+
- Modul
Microsoft.Graph.Authentication(wird beim ersten Connect benoetigt):Install-Module Microsoft.Graph.Authentication -Scope CurrentUser -Force - Browser (Edge, Chrome, Firefox)
Start
.\Start.ps1
Optionen:
| Parameter | Standard | Beschreibung |
|---|---|---|
-Port |
8077 |
Port des lokalen HTTP-Servers |
-TenantId |
— | Ueberschreibt Tenant-ID aus Settings (nur dieser Start) |
-ClientId |
— | Ueberschreibt Client-ID aus Settings (nur dieser Start) |
-NoBrowser |
aus | Browser nicht automatisch oeffnen |
Beispiele:
.\Start.ps1 -Port 8088
.\Start.ps1 -NoBrowser
Beenden: Ctrl+C im Terminal.
Single- vs. Multi-Tenant
Unter Settings → Verbindung → Verbindungsmodus wählst du zwischen:
| Modus | Verhalten |
|---|---|
| Single-Tenant | Klassisch: ein Mandant (Tenant ID + App-Registrierung). Standard. |
| Multi-Tenant | Mehrere Mandanten mit je eigener App-Registrierung; Umschalten oben rechts |
Im Multi-Tenant-Modus legst du pro Mandant ein Profil an (Bezeichnung, Tenant ID, Client-ID Read/Write, optional Client-ID Read-Only). Der aktive Mandant ist markiert. Über das Dropdown in der Topbar wechselst du zwischen den Mandanten — der Wechsel trennt die aktuelle Verbindung und verbindet sofort neu mit dem gewählten Tenant (Login-Prompt erscheint). Alle Caches werden beim Wechsel geleert.
Die Scopes (RW/RO) gelten global für alle Profile. Jeder Mandant benötigt eine eigene App-Registrierung mit denselben delegierten Berechtigungen und (Admin-)Consent im jeweiligen Tenant. Bestehende Single-Tenant-Konfigurationen werden verlustfrei übernommen (Umschalten auf Multi bietet an, das vorhandene Setup als erstes Profil zu übernehmen).
Pro-Tenant-Vorgaben
Jedes Tenant-Profil kann eigene Vorgaben hinterlegen (z. B. Kunde A → abt-hm-*,
Kunde B → dept-*):
- Abteilungs-Präfixe
- Required-Gruppen-Naming (Präfix/Suffix)
- Available-Gruppen-Naming (Präfix/Suffix)
Bleibt ein Feld leer, gilt die globale Vorgabe aus den entsprechenden Einstellungs-Abschnitten (bei Naming greift der Fallback pro Feld einzeln). Beim Mandantenwechsel werden die Caches geleert, sodass die passenden Vorgaben gegen den aktiven Tenant wirken.
Verbindungsmodus (Read/Write vs. Read-Only)
Der Server probiert beim Verbinden zuerst die Read/Write-App-ID (clientId).
Schlaegt diese fehl, wird automatisch auf die Read-Only-App-ID (clientIdRo) zurueckgefallen.
| Modus | Anmelde-Ergebnis | Verhalten im Frontend |
|---|---|---|
| Read/Write | Normale Verbindung | Alle Funktionen verfuegbar |
| Read-Only | Fallback auf clientIdRo |
Schreib-Buttons/Tabs werden ausgeblendet |
Was wird im Read-Only-Modus ausgeblendet?
- App-Zuweisung (Required / Available hinzufuegen und entfernen)
- Gruppen erstellen und loeschen
- Tab „Benutzer hinzufuegen" im Group Management
- Tab „CSV-Import" im Group Management
- Session-Ausfuehren-Button
- Alle Rename-/Delete-Buttons
Konfiguration in den Einstellungen
Settings → Verbindung
Client-ID (Read/Write): <Azure App-Registration mit Schreibrechten>
Client-ID (Read-Only): <Azure App-Registration nur mit Leserechten> (optional)
Scopes RW: DeviceManagementApps.ReadWrite.All ...
Scopes RO: DeviceManagementApps.Read.All ...
Benoetigt Graph-Berechtigungen
| Funktion | Benoetigt |
|---|---|
| Apps anzeigen | DeviceManagementApps.Read.All |
| Gruppen anzeigen / Mitglieder | GroupMember.Read.All |
| User suchen | User.Read.All |
| Zuweisungen aendern | DeviceManagementApps.ReadWrite.All |
| Gruppen-Mitglieder aendern | GroupMember.ReadWrite.All |
| App-Installationszaehler (Report) | DeviceManagementManagedDevices.Read.All ⚠ |
| Geraete-Exportliste pro App | DeviceManagementManagedDevices.Read.All ⚠ |
⚠ Ohne
DeviceManagementManagedDevices.Read.Allzeigt der App-Report nur Zaehler = 0 und der Geraete-Export liefert keine Eintraege.
Navigation (Tabs)
| Tab | Beschreibung |
|---|---|
| App Management | Haupt-Ansicht: Apps laden, Gruppen zuweisen / entfernen |
| Group Management | Mitglieder anzeigen, exportieren, Benutzer hinzufuegen, CSV-Import |
| App Report | Installationszaehler pro App, Geraete-Export als CSV |
| Geräte | Geraete suchen, Detail-Panel, Aktionen (Sync, Wipe, …) |
| Policies | Policies exportieren (JSON-Download) und importieren (Neuanlage) |
Group Management
Mitglieder & Export
- Gruppe links suchen und auswaehlen
- Mitgliederliste (inkl. verschachtelte Gruppen) wird geladen
- Filter zum Einschraenken der Anzeige
- Als CSV exportieren laedt alle Mitglieder als
members-<Gruppe>-<Datum>.csv
Benutzer hinzufuegen (nur Read/Write)
- Benutzer per Name, UPN oder E-Mail suchen
- Mehrere Benutzer auswaehlen und gemeinsam hinzufuegen
CSV-Import (nur Read/Write)
Massenhaftes Hinzufuegen von Benutzern zu einer Gruppe per CSV-Datei.
Ablauf:
- Gruppe links auswaehlen
- CSV hochladen oder UPNs/E-Mails direkt einfuegen (eine pro Zeile)
- „Benutzer aufloesen" – Graph-Lookup via UPN/Mail → Vorschau mit ✓/✗
- „Gefundene importieren" – fuegt alle gefundenen Benutzer zur Gruppe hinzu
CSV-Format:
Die erste Zeile wird als optionaler Header erkannt.
Spalte mit dem Namen UserPrincipalName, Mail oder Email wird automatisch
ausgewaehlt. Ohne Header: erste Spalte mit @ wird verwendet.
DisplayName,UserPrincipalName,Mail
Max Mustermann,max.mustermann@firma.de,max.mustermann@firma.de
Erika Muster,erika.muster@firma.de,
Oder einfach eine UPN pro Zeile:
max.mustermann@firma.de
erika.muster@firma.de
Ergebnis-Anzeige nach Import:
| Chip / Status | Bedeutung |
|---|---|
| ✔ Gruen | Erfolgreich hinzugefuegt |
| ≈ Gelb | Bereits Mitglied (kein Fehler) |
| ✗ Rot | Fehler (Meldung in der Tabelle) |
| Grau | UPN nicht in Graph gefunden (nicht importiert) |
App Report
- Neu laden: laedt Installationszaehler fuer alle Apps (kann 1–2 Min. dauern)
- Tabelle sortierbar per Klick auf Spaltenheader
- Suche filtert nach App-Name, Publisher, Typ
- Als CSV exportieren: exportiert die gefilterte Tabelle
- Geraete-Export (pro Zeile): laedt alle Geraete mit Installationsstatus fuer diese App
Policies (Export / Import)
Sichert Intune-Policies als JSON und legt sie in einem (ggf. anderen) Tenant neu an. Unterstuetzte Typen:
| Typ | Graph-Collection |
|---|---|
| Settings Catalog | configurationPolicies |
| Compliance Policies | deviceCompliancePolicies |
| Konfigurationsprofile | deviceConfigurations |
Export
- Tabelle laedt alle drei Typen; Suche + Typ-Filter grenzen ein
- Policies per Checkbox auswaehlen → Export
- 1 Policy → eine JSON-Datei
- mehrere → eine gebündelte JSON-Datei (
intune-policies_<Datum>.json)
- Zusaetzlich wird jeder Export server-seitig unter
%APPDATA%\IntuneAppManager-Web\policy-exportsarchiviert
Import (nur Read/Write)
- Import… → eine oder mehrere JSON-Dateien waehlen (einzeln oder Bundle)
- Import legt die Policies immer als neue Policy an — bestehende Policies werden nie ueberschrieben
- Ergebnis-Toast meldet Erfolg/Fehler pro Policy
Beim Anlegen entfernt der Import instanzgebundene / schreibgeschuetzte Felder (
id, Zeitstempel,version, Zuweisungen, Status). Compliance-Policies bekommen bei Bedarf einen Default-scheduledActionsForRule-Block, den Graph beim Anlegen zwingend verlangt.
Benoetigt Graph-Berechtigung
DeviceManagementConfiguration.ReadWrite.All (Import) bzw.
DeviceManagementConfiguration.Read.All (nur Export). Der Scope wird beim Start
automatisch zur Verbindung ergaenzt — in der Azure-App-Registration muss die
Berechtigung aber vorhanden und (Admin-)zugestimmt sein.
Git-Snapshot (versioniertes Backup)
Button „Git-Snapshot" im Policies-Tab schreibt alle Policies aller Typen als JSON in einen konfigurierten lokalen Git-Ordner und committet sie automatisch — ideal als versioniertes Backup mit nachvollziehbarer History.
- Konfiguration: Settings → Policy-Backup (Git) — lokaler Repo-Pfad (wird bei
Bedarf angelegt und
git init-isiert) + optional automatischergit push(nutzt den vorhandenen Git-Credential-Helper; kein Token in der App). - Stabile Dateinamen (
<tenant>/<typ>/<name>__<id8>.json) und deterministische, zeitstempel-freie JSON-Ausgabe → saubere Git-Diffs zwischen Snapshots. Entfernte Policies verschwinden aus dem Snapshot. - Multi-Tenant: je Mandant ein eigener Unterordner (nach Profil-Label bzw. Tenant-ID).
- Gibt es keine Aenderungen seit dem letzten Snapshot, wird nichts committet.
Architektur
Intune Manager/
├── Start.ps1 Entry Point, Config, State
├── README.md diese Datei
├── src/
│ ├── Models.ps1 Settings-Schema und Defaults
│ ├── Graph.ps1 Microsoft Graph API Helpers
│ ├── Server.ps1 HTTP-Server (HttpListener)
│ ├── Router.ps1 Request-Routing
│ ├── Api.ps1 REST-API-Endpoints
│ └── PolicyIO.ps1 Policy Export/Import (Compliance, Config, Settings Catalog)
└── www/
├── index.html SPA-Shell
├── styles.css Dark Theme, Read-Only-Regeln
└── app.js Frontend-Logik (Vanilla JS)
REST-API (intern)
| Methode | Pfad | Rechte | Zweck |
|---|---|---|---|
| GET | /api/status |
— | Verbindungsstatus + ReadOnly-Flag |
| POST | /api/connect |
— | Microsoft Graph verbinden |
| POST | /api/disconnect |
— | Trennen |
| GET | /api/groups |
Read | Abteilungs-Gruppen (abt-hm-*) |
| GET | /api/groups/rpa |
Read | 3 vordefinierte RPA-Gruppen |
| GET | /api/groups/search?q= |
Read | Gruppen suchen |
| POST | /api/groups |
Write | Neue Required-Gruppe erstellen |
| POST | /api/groups/check |
Read | Gruppen-Name pruefen |
| POST | /api/groups/resolve-upns |
Read | UPN-Liste → UserId + DisplayName |
| GET | /api/groups/{id}/members |
Read | Mitglieder einer Gruppe |
| GET | /api/groups/{id}/members/export |
Read | Mitglieder als CSV |
| POST | /api/groups/{id}/members |
Write | Benutzer zur Gruppe hinzufuegen |
| DELETE | /api/groups/{id}/members/{uid} |
Write | Benutzer aus Gruppe entfernen |
| GET | /api/users?q= |
Read | Benutzer suchen |
| GET | /api/apps |
Read | Apps laden (cached) |
| POST | /api/apps/refresh |
Read | Apps neu laden |
| GET | /api/apps/report |
Read+MDM | Installationszaehler alle Apps |
| GET | /api/apps/devicestatus?appId= |
Read+MDM | Geraete-Installationsstatus einer App |
| GET | /api/membership?targets=&groupId= |
Read | Mitgliedschafts-Status pruefen |
| POST | /api/membership/bulk |
Read | Mehrere Mitgliedschaften pruefen |
| POST | /api/assignments/apply |
Write | Geplante Zuweisungen ausfuehren |
| GET | /api/policies/settingscatalog |
Read+Cfg | Settings-Catalog-Policies auflisten |
| GET | /api/policies/compliance |
Read+Cfg | Compliance-Policies auflisten |
| GET | /api/policies/configuration |
Read+Cfg | Konfigurationsprofile auflisten |
| POST | /api/policies/export |
Read+Cfg | Ausgewaehlte Policies als JSON exportieren |
| GET | /api/policies/exports |
— | Server-Archiv der Exporte auflisten |
| POST | /api/policies/import |
Write | Policies als Neuanlage importieren |
Read+MDM = benoetigt zusaetzlich
DeviceManagementManagedDevices.Read.AllRead+Cfg = benoetigtDeviceManagementConfiguration.Read.All(Export) bzw..ReadWrite.All(Import)
Hinweise
- Single-User-App – der lokale HTTP-Server ist fuer einen Benutzer ausgelegt.
- Auth lebt im PowerShell-Prozess – Disconnect oder Schliessen des Terminals beendet die Session.
- Cache – Apps werden im Serverprozess gecacht. Refresh-Knopf laedt neu.
- Port-Konflikt – laeuft bereits eine Instanz, beendet
Start.ps1sie automatisch (per CommandLine-Matching). Bei PID-4-Konflikt (http.sys) anderen Port waehlen:.\Start.ps1 -Port 8088.