Detect and warn when machine was set up without factory seal
Agent-Logs-Url: https://github.com/naturallaw777/staging_alpha/sessions/169de2bb-0655-4504-a270-8c0341c0d3dd Co-authored-by: naturallaw777 <99053422+naturallaw777@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
85aca0d022
commit
ac9ba4776c
@@ -2949,6 +2949,16 @@ async def api_security_status():
|
|||||||
"The default system password may be known to the factory. "
|
"The default system password may be known to the factory. "
|
||||||
"Please change your system and application passwords immediately."
|
"Please change your system and application passwords immediately."
|
||||||
)
|
)
|
||||||
|
elif status == "unsealed":
|
||||||
|
try:
|
||||||
|
with open(SECURITY_WARNING_FILE, "r") as f:
|
||||||
|
warning = f.read().strip()
|
||||||
|
except FileNotFoundError:
|
||||||
|
warning = (
|
||||||
|
"This machine was set up without the factory seal process. "
|
||||||
|
"Factory test data — including SSH keys, database contents, and wallet information — "
|
||||||
|
"may still be present on this system."
|
||||||
|
)
|
||||||
|
|
||||||
return {"status": status, "warning": warning}
|
return {"status": status, "warning": warning}
|
||||||
|
|
||||||
@@ -3027,14 +3037,21 @@ async def api_change_password(req: ChangePasswordRequest):
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise HTTPException(status_code=500, detail=f"Failed to write secrets file: {exc}")
|
raise HTTPException(status_code=500, detail=f"Failed to write secrets file: {exc}")
|
||||||
|
|
||||||
# Clear legacy security status so the warning banner is removed
|
# Clear legacy security status so the warning banner is removed — but only
|
||||||
for path in (SECURITY_STATUS_FILE, SECURITY_WARNING_FILE):
|
# for "legacy" machines (pre-seal era). For "unsealed" machines, changing
|
||||||
try:
|
# passwords is not enough; the factory residue (SSH keys, wallet data,
|
||||||
os.remove(path)
|
# databases) remains until a proper re-seal or re-install is performed.
|
||||||
except FileNotFoundError:
|
try:
|
||||||
pass
|
with open(SECURITY_STATUS_FILE, "r") as f:
|
||||||
except Exception:
|
current_status = f.read().strip()
|
||||||
pass # Non-fatal; don't block a successful password change
|
if current_status == "legacy":
|
||||||
|
os.remove(SECURITY_STATUS_FILE)
|
||||||
|
try:
|
||||||
|
os.remove(SECURITY_WARNING_FILE)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
except (FileNotFoundError, OSError):
|
||||||
|
pass
|
||||||
|
|
||||||
return {"ok": True}
|
return {"ok": True}
|
||||||
|
|
||||||
|
|||||||
@@ -602,11 +602,19 @@ function renderAutolaunchToggle(enabled) {
|
|||||||
var securityBanner = "";
|
var securityBanner = "";
|
||||||
if (_securityIsLegacy) {
|
if (_securityIsLegacy) {
|
||||||
var msg = _securityWarningMessage || "Your system may have factory default passwords. Please change your passwords to secure your system.";
|
var msg = _securityWarningMessage || "Your system may have factory default passwords. Please change your passwords to secure your system.";
|
||||||
|
var linkText, linkAction;
|
||||||
|
if (_securityStatus === "unsealed") {
|
||||||
|
linkText = "Contact Support";
|
||||||
|
linkAction = "openSupportModal(); return false;";
|
||||||
|
} else {
|
||||||
|
linkText = "Change Passwords";
|
||||||
|
linkAction = "openServiceDetailModal('root-password-setup.service', 'System Passwords', 'passwords'); return false;";
|
||||||
|
}
|
||||||
securityBanner =
|
securityBanner =
|
||||||
'<div class="security-inline-banner">' +
|
'<div class="security-inline-banner">' +
|
||||||
'<span class="security-inline-icon">⚠</span>' +
|
'<span class="security-inline-icon">⚠</span>' +
|
||||||
'<span class="security-inline-text">' + msg + '</span>' +
|
'<span class="security-inline-text">' + msg + '</span>' +
|
||||||
'<a class="security-inline-link" href="#" onclick="openServiceDetailModal(\'root-password-setup.service\', \'System Passwords\', \'passwords\'); return false;">Change Passwords</a>' +
|
'<a class="security-inline-link" href="#" onclick="' + linkAction + '">' + linkText + '</a>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,10 @@
|
|||||||
async function checkLegacySecurity() {
|
async function checkLegacySecurity() {
|
||||||
try {
|
try {
|
||||||
var data = await apiFetch("/api/security/status");
|
var data = await apiFetch("/api/security/status");
|
||||||
if (data && data.status === "legacy") {
|
if (data && (data.status === "legacy" || data.status === "unsealed")) {
|
||||||
_securityIsLegacy = true;
|
_securityIsLegacy = true;
|
||||||
_securityWarningMessage = data.warning || "This machine may have a known factory password. Please change your passwords immediately.";
|
_securityStatus = data.status;
|
||||||
|
_securityWarningMessage = data.warning || "This machine may have a security issue. Please review your system security.";
|
||||||
}
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// Non-fatal — silently ignore if the endpoint is unreachable
|
// Non-fatal — silently ignore if the endpoint is unreachable
|
||||||
|
|||||||
@@ -626,8 +626,11 @@ function openSystemChangePasswordModal(unit, name, icon) {
|
|||||||
resultEl.textContent = "✅ System password changed successfully.";
|
resultEl.textContent = "✅ System password changed successfully.";
|
||||||
submitBtn.textContent = "Change Password";
|
submitBtn.textContent = "Change Password";
|
||||||
submitBtn.disabled = false;
|
submitBtn.disabled = false;
|
||||||
// Hide the legacy security banner if it's visible
|
// Hide the legacy security banner if it's visible — but only for
|
||||||
if (typeof _securityIsLegacy !== "undefined" && _securityIsLegacy) {
|
// "legacy" status machines. For "unsealed" machines, changing passwords
|
||||||
|
// is not enough; the factory residue remains until a proper re-seal or re-install.
|
||||||
|
if (typeof _securityIsLegacy !== "undefined" && _securityIsLegacy &&
|
||||||
|
(typeof _securityStatus === "undefined" || _securityStatus !== "unsealed")) {
|
||||||
_securityIsLegacy = false;
|
_securityIsLegacy = false;
|
||||||
var banner = document.querySelector(".security-inline-banner");
|
var banner = document.querySelector(".security-inline-banner");
|
||||||
if (banner) banner.remove();
|
if (banner) banner.remove();
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ const $upgradeCloseBtn = document.getElementById("upgrade-close-btn");
|
|||||||
|
|
||||||
// Legacy security warning state (populated by checkLegacySecurity in security.js)
|
// Legacy security warning state (populated by checkLegacySecurity in security.js)
|
||||||
var _securityIsLegacy = false;
|
var _securityIsLegacy = false;
|
||||||
|
var _securityStatus = "ok"; // "ok", "legacy", or "unsealed"
|
||||||
var _securityWarningMessage = "";
|
var _securityWarningMessage = "";
|
||||||
|
|
||||||
// System status banner
|
// System status banner
|
||||||
|
|||||||
@@ -100,11 +100,23 @@ in
|
|||||||
};
|
};
|
||||||
path = [ pkgs.coreutils ];
|
path = [ pkgs.coreutils ];
|
||||||
script = ''
|
script = ''
|
||||||
# If already onboarded or sealed, nothing to do
|
# If sealed AND onboarded — fully clean, nothing to do
|
||||||
[ -f /var/lib/sovran-customer-onboarded ] && exit 0
|
[ -f /var/lib/sovran-factory-sealed ] && [ -f /var/lib/sovran-customer-onboarded ] && exit 0
|
||||||
|
|
||||||
|
# If sealed but not yet onboarded — seal was run, customer hasn't finished setup yet, that's fine
|
||||||
[ -f /var/lib/sovran-factory-sealed ] && exit 0
|
[ -f /var/lib/sovran-factory-sealed ] && exit 0
|
||||||
|
|
||||||
# If secrets exist but no sealed/onboarded flag, this is a legacy machine
|
# If onboarded but NOT sealed — installer ran without factory seal!
|
||||||
|
if [ -f /var/lib/sovran-customer-onboarded ] && [ ! -f /var/lib/sovran-factory-sealed ]; then
|
||||||
|
mkdir -p /var/lib/sovran
|
||||||
|
echo "unsealed" > /var/lib/sovran/security-status
|
||||||
|
cat > /var/lib/sovran/security-warning << 'EOF'
|
||||||
|
This machine was set up without the factory seal process. Factory test data — including SSH keys, database contents, and wallet information — may still be present on this system. It is strongly recommended to back up any important data and re-install using a fresh ISO, or contact Sovran Systems support for assistance.
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# No flags at all + secrets exist = legacy (pre-seal era) machine
|
||||||
if [ -f /var/lib/secrets/root-password ]; then
|
if [ -f /var/lib/secrets/root-password ]; then
|
||||||
mkdir -p /var/lib/sovran
|
mkdir -p /var/lib/sovran
|
||||||
echo "legacy" > /var/lib/sovran/security-status
|
echo "legacy" > /var/lib/sovran/security-status
|
||||||
|
|||||||
Reference in New Issue
Block a user