allowing upn login

This commit is contained in:
Ludwig Lehnert
2026-10-03 18:59:48 +00:00
parent 6ddc9ebcab
commit 2682658507
6 changed files with 155 additions and 18 deletions
+17
View File
@@ -120,6 +120,23 @@ ensure_user "$AD_WEB_ADMIN_USER" "$AD_WEB_ADMIN_PASSWORD" Preview Administrator
ensure_user report_svc "$AD_USER_PASSWORD" Report Service
ensure_user MSOL_sync "$AD_USER_PASSWORD" Directory Sync
# Windows' post-2000 logon name can differ from the pre-2000 account name,
# including a DNS suffix that differs from the domain's Kerberos realm.
for user in dave frank; do
user_dn=$(samba-tool user show "$user" | sed -n 's/^dn: //p')
if [[ $user == dave ]]; then
user_upn="david.davis@${AD_DNS_DOMAIN}"
else
user_upn="frank.foster@people.${AD_DNS_DOMAIN}"
fi
ldbmodify -H /var/lib/samba/private/sam.ldb <<EOF
dn: ${user_dn}
changetype: modify
replace: userPrincipalName
userPrincipalName: ${user_upn}
EOF
done
for group in Finance_Analysts Engineering_Leads FS_Finance FS_Engineering FS_Projects; do
ensure_group "$group"
done
+10 -1
View File
@@ -241,11 +241,20 @@ def main() -> int:
)
check(non_admin.status == 200 and non_admin.json().get("role") == "user", "valid non-admin domain user cannot sign in")
user_token = non_admin.json()["token"]
for username in (f"{WORKGROUP}\\alice", f"alice@{DNS_DOMAIN}", f"alice@{WORKGROUP}"):
for username in (f"{WORKGROUP}\\alice", f"alice@{DNS_DOMAIN}", f"alice@{DNS_DOMAIN.upper()}"):
formatted = http("/api/login", method="POST", value={"username": username, "password": USER_PASSWORD})
check(formatted.status == 200, f"qualified user login failed for {username}")
check(formatted.json().get("sid") == non_admin.json()["sid"] and formatted.json().get("role") == "user",
"login format changes identity or grants administration")
check(http("/api/login", method="POST", value={"username": f"alice@{WORKGROUP}", "password": USER_PASSWORD}).status == 401,
"UPN login accepts a NetBIOS suffix")
for account, upn in (("dave", f"david.davis@{DNS_DOMAIN}"), ("frank", f"frank.foster@people.{DNS_DOMAIN}")):
legacy = http("/api/login", method="POST", value={"username": f"{WORKGROUP}\\{account}", "password": USER_PASSWORD})
modern = http("/api/login", method="POST", value={"username": upn, "password": USER_PASSWORD})
check(legacy.status == modern.status == 200, f"UPN alias authentication failed for {upn}")
check(modern.json()["user"] == f"{WORKGROUP}\\{account}" and modern.json()["sid"] == legacy.json()["sid"],
"UPN prefix is confused with another account")
check(modern.json()["role"] == "user", "UPN alias receives unexpected admin access")
for endpoint in ("/api/overview", "/api/access", "/api/storage", "/api/trash", "/api/report", "/api/system"):
check(http(endpoint, token=user_token).status == 403, f"non-admin can read {endpoint}")
for endpoint in ("/api/access", "/api/actions/backup", "/api/actions/reconciliation", "/api/trash/restore"):
+30
View File
@@ -50,6 +50,36 @@ font=next(Path('/usr/share/fonts').rglob('NimbusSans-Regular.otf'))
draw=ImageDraw.Draw(image)
draw.text((120,200),'INVOICE SCAN\nCustomer reference SCANNEDUNIQUE742\nInvoice total 1500 EUR\nPayment due 30 October 2026',fill='black',font=ImageFont.truetype(str(font),44),spacing=40)
image.save(root/'scanned-invoice.pdf','PDF',resolution=150)
# Large portrait/landscape images and a small image for responsive preview checks.
# Generate them locally so the preview needs no external downloads or image assets.
def preview_image(path, width, height):
path.parent.mkdir(parents=True, exist_ok=True)
image = Image.new('RGB', (width, height), '#dceaf2')
draw = ImageDraw.Draw(image)
unit = min(width, height)
sun = unit // 9
center = (width * 3 // 4, height // 4)
draw.ellipse((center[0] - sun, center[1] - sun,
center[0] + sun, center[1] + sun), fill='#e7bb57')
draw.polygon([(0, height * 3 // 4), (width // 3, height // 3),
(width * 3 // 4, height * 4 // 5), (width, height // 2),
(width, height), (0, height)], fill='#7e9a82')
draw.polygon([(0, height * 9 // 10), (width // 2, height * 3 // 5),
(width, height * 4 // 5), (width, height), (0, height)], fill='#59796a')
margin = unit // 20
label_font = ImageFont.truetype(str(font), max(12, unit // 24))
draw.text((margin, margin), f'{width} × {height} px', fill='#304a60', font=label_font)
draw.text((margin, height - margin - unit // 20), 'IMAGEPREVIEW742', fill='white', font=label_font)
draw.rectangle((0, 0, width - 1, height - 1), outline='#304a60', width=max(2, unit // 100))
image.save(path)
photos = Path('/data/groups/data/Finance/Photos')
preview_image(photos/'portrait-4000x6000.jpg', 4000, 6000)
preview_image(photos/'landscape-6000x4000.png', 6000, 4000)
preview_image(photos/'small-320x240.png', 320, 240)
preview_image(Path('/data/private/alice/private-portrait.jpg'), 2400, 3600)
for folder in (root,Path('/data/private/alice')):
for name in ('Thumbs.db','THUMBS.DB','~$Locked.docx','~$Locked.pptx'):
(folder/name).write_text('IGNOREDARTIFACT742')