# ReBreak Unsupervised Sideload Profile — nginx Distribution Snippet # =================================================================== # Einbinden in den bestehenden mdm.rebreak.org / app.rebreak.org server-block. # Pre-generierte per-User-Profiles liegen unter /srv/rebreak/profiles/users/ # Layout: /srv/rebreak/profiles/users/.mobileconfig # Variante A: per-User-Token-gated Distribution (RECOMMENDED für Production) # --------------------------------------------------------------------------- # Backend signiert einen kurzlebigen Download-Token (JWT) und der User klickt # einen Link wie: # https://app.rebreak.org/profile/download?t=eyJhbGc... # nginx ruft das Backend (auth_request) auf um zu validieren bevor er das # Profile ausliefert. Profile selbst sind unsigned, aber der Zugriff ist # geschützt — verhindert dass Profiles auf öffentlichen URLs leaken. location = /profile/download { # JWT-Validation gegen Backend (Backend returnt 200 + X-User-Id Header) auth_request /auth/validate-profile-token; auth_request_set $user_id $upstream_http_x_user_id; # Internal-only Redirect zum echten Profile-File error_page 200 = @serve_profile; return 200; } location @serve_profile { internal; alias /srv/rebreak/profiles/users/$user_id.mobileconfig; # iOS-spezifischer Content-Type — Apple Aspen Profile # https://developer.apple.com/library/archive/featuredarticles/iPhoneConfigurationProfileRef/ default_type application/x-apple-aspen-config; # Forciert Download-Dialog statt Inline-Display in Safari → triggert # iOS-Profile-Install-Flow ab iOS 12.2 (Safari öffnet Settings.app). add_header Content-Disposition 'attachment; filename="ReBreak-Schutz.mobileconfig"'; # Strict Security-Headers add_header X-Content-Type-Options "nosniff" always; add_header Cache-Control "no-store, no-cache, must-revalidate" always; # HTTPS-Only — HSTS preload-ready add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; } location = /auth/validate-profile-token { internal; proxy_pass http://127.0.0.1:3000/api/profile/validate-token; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Original-URI $request_uri; # Token kommt als Query-Param, Backend liest's selber raus } # Variante B: static-served für interne Tests (NICHT Production) # --------------------------------------------------------------------------- # Eine generische .mobileconfig für Dev-Tests. Token-Auth weglassen — die URL # ist die Auth (security through obscurity, nur für interne Tester teilen). location = /dev/rebreak-schutz-test.mobileconfig { alias /srv/rebreak/profiles/dev/rebreak-iphone-unsupervised-sideload.mobileconfig; default_type application/x-apple-aspen-config; add_header Content-Disposition 'attachment; filename="ReBreak-Schutz-DEV.mobileconfig"'; add_header X-Content-Type-Options "nosniff" always; add_header Cache-Control "no-store" always; # IP-Whitelist für interne Tester (Beispiel — anpassen oder weglassen) # allow 49.13.55.22; # rebreak-server # allow 178.105.101.137; # rebreak-mdm # deny all; } # HTTPS-Enforcement (sollte global in main server-block sein, hier zur # Vollständigkeit — falls noch nicht gesetzt) # --------------------------------------------------------------------------- # iOS akzeptiert .mobileconfig-Download nur über HTTPS. HTTP-Versuche werden # entweder geredirected oder vom System silent verworfen. # server { # listen 80; # server_name app.rebreak.org; # return 301 https://$host$request_uri; # } # Deploy-Hinweise # --------------------------------------------------------------------------- # 1. Generator-Run auf rebreak-server: # cd /srv/rebreak/ops/mdm/profiles # python3 generate-unsupervised-profile.py \ # --batch /srv/rebreak/data/users-pending.csv \ # --output-dir /srv/rebreak/profiles/users/ \ # --org "ReBreak GmbH" # # 2. Permissions: # chown -R www-data:www-data /srv/rebreak/profiles/ # chmod 750 /srv/rebreak/profiles/ # chmod 640 /srv/rebreak/profiles/users/*.mobileconfig # # 3. nginx reload: # nginx -t && systemctl reload nginx # # 4. Verify-Curl (sollte 401 ohne Token zurückgeben): # curl -I https://app.rebreak.org/profile/download # # 5. Verify Content-Type mit echtem Token: # curl -I -H "Authorization: Bearer $TOKEN" \ # "https://app.rebreak.org/profile/download?t=$TOKEN" # Erwartet: Content-Type: application/x-apple-aspen-config