webapp: technician to-do for the manual CMMC steps; count fallbacks as wiped
Technician To-Do (sidebar link with a count, and a banner on every page while anything is open) lists the playbook steps the server cannot do: 1. wipes still to tick on the Onsite Bin RITM (ENT-045/159) 2. monthly evidence packs to upload to Box (ENT-056/158), Mark uploaded 3. drives that failed to wipe, to destroy (COD recorded) 4. reports Blancco could not upload to the cloud (Resolved) Marks are stored in the Blancco state file; the counts are cached for 60s and refreshed on every mark, ServiceNow tick and cloud-status post. Results are now judged per drive. Blancco keeps every attempt in the report, so a NIST Purge that failed followed by a successful Clear fallback on the same drive appeared as two entries, and the Reports page rolled the whole report up to Failed. 20 such wipes since May showed as Failed; they were wiped (the work instruction counts the fallback as a success). The CSV marks those rows "Fallback: ... then erased with ...". One genuine failure remains: HNMD1V3, Seagate Z500R4KG, 2026-08-11.
This commit is contained in:
@@ -565,17 +565,10 @@ def blancco_reports():
|
||||
sysinfo = (data.get("hardware") or {}).get("system") or {}
|
||||
serial = sysinfo.get("serial", "") or ""
|
||||
model = sysinfo.get("model", "") or ""
|
||||
# Overall erasure result: each erasure entry has its own
|
||||
# 'state' (Successful / Failed / ...). If any drive failed
|
||||
# the report rolls up to Failed; otherwise Successful.
|
||||
erasures = data.get("erasures") or []
|
||||
states = [(e.get("state") or "").strip() for e in erasures if e.get("state")]
|
||||
if not states:
|
||||
result = ""
|
||||
elif any(s.lower() != "successful" for s in states):
|
||||
result = "Failed"
|
||||
else:
|
||||
result = "Successful"
|
||||
# Overall result per drive: Failed if any drive was not
|
||||
# wiped. A failed Purge followed by a successful Clear
|
||||
# fallback on the same drive is a successful wipe.
|
||||
result = blancco_report.report_result(data)
|
||||
cloud = blancco_evidence.cloud_status(
|
||||
state, (data.get("meta") or {}).get("document_id", ""))
|
||||
except Exception:
|
||||
@@ -724,6 +717,33 @@ def blancco_servicenow_mark(document_id):
|
||||
return redirect(url_for("blancco_servicenow", all=request.args.get("all")))
|
||||
|
||||
|
||||
@app.route("/reports/todo")
|
||||
def blancco_todo():
|
||||
"""Technician to-do: the playbook steps the server cannot do itself."""
|
||||
return render_template("reports_todo.html", todo=blancco_evidence.todo(),
|
||||
site=config.BLANCCO_SITE)
|
||||
|
||||
|
||||
@app.route("/reports/todo/<kind>/<key>", methods=["POST"])
|
||||
def blancco_todo_mark(kind, key):
|
||||
done = request.form.get("done", "1") == "1"
|
||||
try:
|
||||
blancco_evidence.mark(kind, key, done)
|
||||
except ValueError:
|
||||
abort(400)
|
||||
audit("REPORT_TODO", f"{kind} {key} {'done' if done else 'undone'}")
|
||||
return redirect(url_for("blancco_todo"))
|
||||
|
||||
|
||||
@app.route("/reports/evidence/file/<filename>")
|
||||
def blancco_evidence_file(filename):
|
||||
filename = secure_filename(filename)
|
||||
fpath = os.path.join(config.BLANCCO_REPORTS, "evidence", filename)
|
||||
if not os.path.isfile(fpath):
|
||||
abort(404)
|
||||
return send_file(fpath, as_attachment=True)
|
||||
|
||||
|
||||
@app.route("/reports/download/<filename>")
|
||||
def blancco_download_report(filename):
|
||||
filename = secure_filename(filename)
|
||||
@@ -1481,6 +1501,7 @@ def inject_globals():
|
||||
return {
|
||||
"all_image_types": config.IMAGE_TYPES,
|
||||
"all_friendly_names": config.FRIENDLY_NAMES,
|
||||
"blancco_todo": blancco_evidence.todo_counts(),
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user