rebreak-monorepo/backend/server/api/magic/profile.mobileconfig.get.ts
chahinebrini d212452a5d fix(magic): bundle mobileconfig template via Nitro serverAssets
Previously read template via process.cwd() + 'ops/mdm/…' — but pm2
runs the bundled output from /root, not the repo root, so the path
resolved to /root/ops/mdm/… (does not exist) → HTTP 500 'Profile
template not found' after Mac registration.

Switch to Nitro's serverAssets (baseName 'mdm', dir '../ops/mdm')
which is bundled at build-time and read via
useStorage('assets:server'). cwd-independent + survives any deploy
layout change.
2026-06-03 09:46:13 +02:00

87 lines
2.8 KiB
TypeScript
Raw 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.

import { randomUUID } from "crypto";
import { findMagicDeviceByToken } from "../../db/devices";
/**
* GET /api/magic/profile.mobileconfig?token=<dnsToken>
*
* Generiert personalisiertes DNS-Configuration-Profile für macOS.
* Template: ops/mdm/rebreak-mac-dns-filter.mobileconfig (via Nitro serverAssets
* unter baseName "mdm" eingebundelt — siehe nitro.config.ts).
*
* Ersetzt:
* - ServerURL: /dns-query → /dns-query/{token}
* - PayloadUUID: 2× neu generieren (DNSSettings + Profile root)
* - PayloadIdentifier: unique pro Device
*
* TODO: Profile-Signierung via Apple Developer Certificate (Phase 2)
*/
export default defineEventHandler(async (event) => {
const query = getQuery(event);
const token = query.token as string | undefined;
if (!token) {
throw createError({
statusCode: 400,
message: "token query parameter required",
});
}
// Token in DB suchen (nur aktive, nicht revoked)
const device = await findMagicDeviceByToken(token);
if (!device) {
throw createError({
statusCode: 404,
message: "Invalid or revoked DNS token",
});
}
// Template via Nitro serverAssets lesen (build-time eingebundelt → cwd-unabhängig).
const storage = useStorage("assets:server");
const template = (await storage.getItem(
"mdm/rebreak-mac-dns-filter.mobileconfig",
)) as string | null;
if (!template) {
console.error(
"[Magic] Profile template missing in serverAssets (mdm/rebreak-mac-dns-filter.mobileconfig)",
);
throw createError({
statusCode: 500,
message: "Profile template not found",
});
}
// ServerURL ersetzen: /dns-query → /dns-query/{token}
const personalizedProfile = template
.replace(
"https://dns.rebreak.org/dns-query",
`https://dns.rebreak.org/dns-query/${token}`,
)
// PayloadUUID neu generieren (2 Stellen im Template)
.replace("7D2E8B1A-C3D4-4E76-8B23-A4B5C6D7E8F0", randomUUID().toUpperCase())
.replace("8C3F9A2B-D4E5-4F87-9A12-B5C6D7E8F901", randomUUID().toUpperCase())
// PayloadIdentifier unique machen (optional, verhindert Konflikt bei Multi-Device)
.replace(
"org.rebreak.protection.dns.filter",
`org.rebreak.protection.dns.filter.${device.deviceId.slice(0, 8)}`,
)
.replace(
"org.rebreak.protection.profile",
`org.rebreak.protection.profile.${device.deviceId.slice(0, 8)}`,
);
// Response-Headers
setHeader(event, "Content-Type", "application/x-apple-aspen-config");
setHeader(
event,
"Content-Disposition",
`attachment; filename="RebreakMagic-${device.deviceId.slice(0, 8)}.mobileconfig"`,
);
// TODO: Profile-Signierung via /usr/bin/security cms -S
// Requires: Apple Developer Certificate + Private Key in Keychain
// Siehe: https://developer.apple.com/documentation/devicemanagement/profile-specific_payload_keys
return personalizedProfile;
});