Files
Intune-Manager/README.md
T
marcoandClaude Opus 4.8 ea51bac772
Build & Release MSI / build-msi (push) Canceled after 0s
Policies-Tab: Export/Import (Settings Catalog, Compliance, Config)
Neuer Tab "Policies" zum Sichern und Wiederherstellen von Intune-Policies.

- Backend src/PolicyIO.ps1: typ-getrieben fuer configurationPolicies
  (Settings Catalog), deviceCompliancePolicies und deviceConfigurations
- Export als JSON-Download (einzeln/Bundle) + Server-Archiv unter %APPDATA%
- Import per Datei-Upload, immer Neuanlage (nie ueberschreiben), robust fuer
  Hashtable (PS7) und PSCustomObject (PS5.1); im Read-Only-Modus ausgeblendet
- Routen in src/Api.ps1; Config-Scope DeviceManagementConfiguration.* auch
  nach Settings-Save sichergestellt
- Frontend: Tab + View, Suche/Typ-Filter/Sortierung, Auswahl, Download/Upload
- Version 0.1.25 (Start.ps1, CHANGELOG, README)
- build-local.ps1: x64-.NET-Runtime fuer wix auf ARM64-Windows + echter
  Desktop-Pfad

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-19 14:25:29 +02:00

269 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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):
```powershell
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser -Force
```
- Browser (Edge, Chrome, Firefox)
## Start
```powershell
.\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:
```powershell
.\Start.ps1 -Port 8088
.\Start.ps1 -NoBrowser
```
Beenden: `Ctrl+C` im Terminal.
---
## 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.All` zeigt 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:**
1. Gruppe links auswaehlen
2. CSV hochladen **oder** UPNs/E-Mails direkt einfuegen (eine pro Zeile)
3. **„Benutzer aufloesen"** – Graph-Lookup via UPN/Mail → Vorschau mit ✓/✗
4. **„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.
```csv
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-exports` archiviert
### 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.
---
## 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.All`
> **Read+Cfg** = benoetigt `DeviceManagementConfiguration.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.ps1` sie automatisch (per CommandLine-Matching). Bei PID-4-Konflikt (http.sys) anderen Port waehlen: `.\Start.ps1 -Port 8088`.