Share accounts: per-site Samba passwords from the webapp

Tools > Share accounts sets the pxe-upload, blancco and clonezilla Samba
passwords. Saving one runs smbpasswd and writes it everywhere it is used:
startnet.cmd in boot.wim (pxe-upload), the served Blancco preferences and
the live config.img (blancco), the iPXE menu's Clonezilla entries
(clonezilla). Refused while a PC is imaging unless forced. Stored 0600 in
UPDATES_DIR/shares/accounts.json, never shown back.

- The stored values are the authority: the playbook only creates the
  Samba accounts, seeds the store from site-vars (pxe_upload_password,
  blancco_smb_password, clonezilla_smb_password) for accounts it does not
  hold, and runs "share_accounts apply" at the end of every run.
- Every startnet save re-pins SHAREPASS, so a restored snapshot cannot
  bring an old password back; new menu blocks use %SHAREUSER%/%SHAREPASS%.
- Shop floor unattend Order 4 reads the login from fetch-source.txt;
  Invoke-PostPpkg deletes that file once the PPKG is applied.
- Upload-Image.ps1 asks for the password unless -Pass is given.
- pxe_admin_password: the Linux pxe login. Required while the box still
  has the shipped "pxe"; set with chpasswd when it differs.
- Blancco site settings now also reach the live config.img (BIOS path).
This commit is contained in:
cproudlock
2026-10-17 12:29:06 -04:00
parent 5f7954ac88
commit fa79f76951
20 changed files with 1526 additions and 671 deletions

View File

@@ -45,14 +45,16 @@ def page():
@bp.route("/site-settings", methods=["POST"])
def site_settings():
"""Business location and licensing Wi-Fi: saved, then the served
preferences.xml is rendered again. The password is never shown back."""
preferences.xml and the live config.img are written again. The password
is never shown back."""
try:
with bu._lock:
blancco_prefs.save(request.form.get("business_location", ""),
request.form.get("wifi_ssid", ""),
request.form.get("wifi_password", ""))
changed = blancco_prefs.render()
except (OSError, ValueError) as e:
# Served preferences.xml and the live config.img (BIOS path).
changed = bu.refresh_live_prefs()
except (OSError, ValueError, bu.StageBlocked) as e:
flash(f"Blancco site settings not saved: {e}", "danger")
return _back()
s = blancco_prefs.public()

View File

@@ -0,0 +1,43 @@
"""Tools > Share accounts: the Samba passwords the imaging clients use
(pxe-upload, blancco, clonezilla). Logic in services/share_accounts.py."""
from flask import Blueprint, flash, redirect, render_template, request, url_for
from services import share_accounts as sa
from services.audit import audit
bp = Blueprint("share_accounts", __name__, url_prefix="/tools/share-accounts")
USED_BY = {
"pxe-upload": "WinPE and Shop Floor setup on every imaging PC; image and app uploads",
"blancco": "Blancco saving erasure reports to the blancco-reports share",
"clonezilla": "Clonezilla back up and restore (in the PXE boot menu)",
}
@bp.route("/")
def page():
return render_template("share_accounts.html", accounts=sa.public(), used_by=USED_BY,
busy=sa.busy(), rule=sa.PASSWORD_RULE)
@bp.route("/<account>", methods=["POST"])
def save(account):
pw = request.form.get("password", "")
if pw != request.form.get("confirm", ""):
flash(f"{account}: the two passwords differ; nothing changed.", "danger")
return redirect(url_for("share_accounts.page"))
force = request.form.get("force") == "1"
try:
done = sa.set_password(account, pw, force=force)
except sa.ApplyFailed as e:
audit("SHARE_PASSWORD_FAILED", f"{account}: {e}")
flash(f"{account} password stored, but applying it failed: {e}. "
"Fix the cause and save it again.", "danger")
return redirect(url_for("share_accounts.page"))
except (ValueError, RuntimeError, OSError) as e:
flash(f"{account} password not changed: {e}", "danger")
return redirect(url_for("share_accounts.page"))
audit("SHARE_PASSWORD", f"{account}{' (while PCs were imaging)' if force else ''}: " + "; ".join(done))
flash(f"{account} password changed. " + "; ".join(done) + ".", "success")
return redirect(url_for("share_accounts.page"))