small fixes
This commit is contained in:
@@ -1,15 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Apple mobileconfig profile generator HTTP server.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
./mobileconfig-generator.py \\
|
|
||||||
--domain billenius.com \\
|
|
||||||
--mail-host mail.billenius.com \\
|
|
||||||
--radicale-host cal.billenius.com \\
|
|
||||||
--account love:love@billenius.com:love_billenius.com \\
|
|
||||||
--port 8426
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import hashlib
|
import hashlib
|
||||||
import re
|
import re
|
||||||
@@ -98,7 +87,9 @@ def resolve_account(params):
|
|||||||
|
|
||||||
def deterministic_uuid(seed):
|
def deterministic_uuid(seed):
|
||||||
digest = hashlib.sha256(seed.encode("utf-8")).hexdigest()
|
digest = hashlib.sha256(seed.encode("utf-8")).hexdigest()
|
||||||
return f"{digest[:8]}-{digest[8:12]}-{digest[12:16]}-{digest[16:20]}-{digest[20:32]}"
|
return (
|
||||||
|
f"{digest[:8]}-{digest[8:12]}-{digest[12:16]}-{digest[16:20]}-{digest[20:32]}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def mobileconfig_payload(email, full_name):
|
def mobileconfig_payload(email, full_name):
|
||||||
@@ -219,7 +210,7 @@ def mobileconfig_payload(email, full_name):
|
|||||||
<key>PayloadDescription</key>
|
<key>PayloadDescription</key>
|
||||||
<string>Configures mail, calendar, and contacts for {values["email"]}.</string>
|
<string>Configures mail, calendar, and contacts for {values["email"]}.</string>
|
||||||
<key>PayloadDisplayName</key>
|
<key>PayloadDisplayName</key>
|
||||||
<string>{values["domain"]} Mail</string>
|
<string>{values["email"]}</string>
|
||||||
<key>PayloadIdentifier</key>
|
<key>PayloadIdentifier</key>
|
||||||
<string>com.billenius.mobileconfig.{values["identifier"]}</string>
|
<string>com.billenius.mobileconfig.{values["identifier"]}</string>
|
||||||
<key>PayloadOrganization</key>
|
<key>PayloadOrganization</key>
|
||||||
@@ -388,7 +379,10 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
payload = mobileconfig_payload(account["email"], full_name).encode("utf-8")
|
payload = mobileconfig_payload(account["email"], full_name).encode("utf-8")
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header("Content-Type", "application/x-apple-aspen-config")
|
self.send_header("Content-Type", "application/x-apple-aspen-config")
|
||||||
self.send_header("Content-Disposition", f'attachment; filename="{filename_base}.mobileconfig"')
|
self.send_header(
|
||||||
|
"Content-Disposition",
|
||||||
|
f'attachment; filename="{filename_base}.mobileconfig"',
|
||||||
|
)
|
||||||
self.send_header("Content-Length", str(len(payload)))
|
self.send_header("Content-Length", str(len(payload)))
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(payload)
|
self.wfile.write(payload)
|
||||||
@@ -409,7 +403,10 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
if parsed.path in ("/mobileconfig/", "/mobileconfig/index.html"):
|
if parsed.path in ("/mobileconfig/", "/mobileconfig/index.html"):
|
||||||
account = resolve_account(params)
|
account = resolve_account(params)
|
||||||
if account is None:
|
if account is None:
|
||||||
has_query = any(first(params.get(key)) for key in ("username", "user", "emailaddress"))
|
has_query = any(
|
||||||
|
first(params.get(key))
|
||||||
|
for key in ("username", "user", "emailaddress")
|
||||||
|
)
|
||||||
if has_query:
|
if has_query:
|
||||||
self.send_text("Unknown account", status=404)
|
self.send_text("Unknown account", status=404)
|
||||||
else:
|
else:
|
||||||
@@ -432,8 +429,10 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
self.send_profile(account, full_name, "billenius")
|
self.send_profile(account, full_name, "billenius")
|
||||||
return
|
return
|
||||||
|
|
||||||
if parsed.path.startswith("/mobileconfig/") and parsed.path.endswith(".mobileconfig"):
|
if parsed.path.startswith("/mobileconfig/") and parsed.path.endswith(
|
||||||
basename = parsed.path[len("/mobileconfig/"):-len(".mobileconfig")]
|
".mobileconfig"
|
||||||
|
):
|
||||||
|
basename = parsed.path[len("/mobileconfig/") : -len(".mobileconfig")]
|
||||||
account = ACCOUNT_BY_PATH.get(basename)
|
account = ACCOUNT_BY_PATH.get(basename)
|
||||||
if account is None:
|
if account is None:
|
||||||
self.send_text("Unknown account", status=404)
|
self.send_text("Unknown account", status=404)
|
||||||
@@ -455,7 +454,11 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument("--radicale-host", required=True)
|
parser.add_argument("--radicale-host", required=True)
|
||||||
parser.add_argument("--default-username", default=None)
|
parser.add_argument("--default-username", default=None)
|
||||||
parser.add_argument("--port", type=int, default=8426)
|
parser.add_argument("--port", type=int, default=8426)
|
||||||
parser.add_argument("--account", type=parse_account, action="append",
|
parser.add_argument(
|
||||||
help="username:email:legacyPath (repeatable)")
|
"--account",
|
||||||
|
type=parse_account,
|
||||||
|
action="append",
|
||||||
|
help="username:email:legacyPath (repeatable)",
|
||||||
|
)
|
||||||
init(parser.parse_args())
|
init(parser.parse_args())
|
||||||
ThreadingHTTPServer(("127.0.0.1", PORT), Handler).serve_forever()
|
ThreadingHTTPServer(("127.0.0.1", PORT), Handler).serve_forever()
|
||||||
|
|||||||
@@ -17,22 +17,21 @@ lib.mkIf hasMailDiscoveryConfig (
|
|||||||
|
|
||||||
safeLegacyPath = email: builtins.replaceStrings [ "@" "+" ] [ "_" "-" ] email;
|
safeLegacyPath = email: builtins.replaceStrings [ "@" "+" ] [ "_" "-" ] email;
|
||||||
|
|
||||||
accountEntries =
|
accountEntries = lib.filter (entry: entry.domain == domain) (
|
||||||
lib.filter (entry: entry.domain == domain) (
|
lib.mapAttrsToList (
|
||||||
lib.mapAttrsToList (
|
email: _:
|
||||||
email: _:
|
let
|
||||||
let
|
parts = lib.splitString "@" email;
|
||||||
parts = lib.splitString "@" email;
|
username = builtins.head parts;
|
||||||
username = builtins.head parts;
|
domainPart = lib.last parts;
|
||||||
domainPart = lib.last parts;
|
in
|
||||||
in
|
{
|
||||||
{
|
inherit email username;
|
||||||
inherit email username;
|
domain = domainPart;
|
||||||
domain = domainPart;
|
legacyPath = safeLegacyPath email;
|
||||||
legacyPath = safeLegacyPath email;
|
}
|
||||||
}
|
) cfg.loginAccounts
|
||||||
) cfg.loginAccounts
|
);
|
||||||
);
|
|
||||||
|
|
||||||
usernames = map (entry: entry.username) accountEntries;
|
usernames = map (entry: entry.username) accountEntries;
|
||||||
defaultUsername =
|
defaultUsername =
|
||||||
@@ -40,8 +39,8 @@ lib.mkIf hasMailDiscoveryConfig (
|
|||||||
|
|
||||||
generatorScript = ./mobileconfig-generator.py;
|
generatorScript = ./mobileconfig-generator.py;
|
||||||
|
|
||||||
accountArgs = lib.concatMapStrings (entry:
|
accountArgs = lib.concatMapStrings (
|
||||||
" --account ${entry.username}:${entry.email}:${entry.legacyPath}"
|
entry: " --account ${entry.username}:${entry.email}:${entry.legacyPath}"
|
||||||
) accountEntries;
|
) accountEntries;
|
||||||
|
|
||||||
defaultUsernameArg =
|
defaultUsernameArg =
|
||||||
@@ -61,7 +60,12 @@ lib.mkIf hasMailDiscoveryConfig (
|
|||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
DynamicUser = true;
|
DynamicUser = true;
|
||||||
ExecStart = "${pkgs.python3}/bin/python3 ${generatorScript} --domain ${domain} --mail-host ${cfg.fqdn} --radicale-host ${radicaleHost} --port ${toString mobileconfigPort}${defaultUsernameArg}${accountArgs}";
|
ExecStart = "${pkgs.python3}/bin/python3 \
|
||||||
|
${generatorScript} \
|
||||||
|
--domain ${domain} \
|
||||||
|
--mail-host ${cfg.fqdn} \
|
||||||
|
--radicale-host ${radicaleHost} \
|
||||||
|
--port ${toString mobileconfigPort}${defaultUsernameArg}${accountArgs}";
|
||||||
NoNewPrivileges = true;
|
NoNewPrivileges = true;
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
ProtectHome = true;
|
ProtectHome = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user