Repository navigation
RivetMSP 26.10.14
·
12 commits
to master
since this release
Ports RivetIT's released adoption (26.10.35 plus the 26.10.37 secret-box fix) of RivetCore 1.0.0-rc.10 RivetCore\Crypto (ADR-011) for stored secrets. DB 2.6.87 (one idempotent step gated on 2.6.86: widens the encrypted
columns so the new envelope fits, adds settings.config_vault_v3_enabled (0), config_vault_dek_wrap, config_vault_v3_prepared_at and api_tokens.token_enc_dek; no stored value changes; db.sql carries it and a fresh
import equals a migrated database). Nothing changes on an existing install until an administrator creates the key file; the credential vault stays on the legacy format until its flag is switched on.
Read docs/KEY_MANAGEMENT.md before deploying.
Deploy notes (in this order; take a database dump first):
- Back up the database, pull this tag and run
composer install --no-dev --no-plugins --no-scripts(nothing new is installed; the lock is unchanged). php scripts/update_cli.php --update_db(2.6.86 to 2.6.87). Safe to run before anything else; the app keeps working on theconfig.phpkey exactly as before.- As root, create the key file:
sudo php scripts/keys_cli.php generate. It creates/etc/rivetmsp0755 (the web user must be able to traverse it) andkeys.jsonroot:www-data0640, with theconfig.phpkey as kidk1. Check withphp scripts/keys_cli.php status: it must not say "NOT REACHABLE". - Take an offline copy of
/etc/rivetmsp/keys.jsonnow, apart from the dump and the backup passphrase. - Dry run, then move everything:
php scripts/rewrap_cli.php --dry-run,php scripts/rewrap_cli.php(repeats until a pass changes nothing; resumable).php scripts/keys_cli.php status --inventoryshows the result. - Leave the credential vault flag off (
config_vault_v3_enabledstays 0;scripts/vault_v3_cli.phpis for a later, deliberate step). - Rollback: set
$config_crypto_v3_settings = false;inconfig.php(new writes areENC2:again; v3 values already written stay readable by this release). Downgrading the code needs the values moved back first, or a restore of the pre-upgrade dump.
- Settings and two-factor seeds.
encryptSetting()/decryptSetting()(same signatures, an optional context) go throughRivetMSP\Crypto\SettingsCrypto/ RivetCore'sSettingsVault. With a key file, new values arev3:<kid>:...;ENC2:,ENC:and cleartext keep reading and move to v3 lazily (the settings row) and with the tool.users.user_tokenseeds are v3 of thetotppurpose bound to the user. A value that cannot be opened reads as empty (logged once, never the value); an unknown or damaged envelope (v4:,ENC3:, a truncatedv3:) now fails closed instead of being handed back as if it were cleartext; true legacy cleartext still reads. Flags$config_crypto_v3_settings,$config_crypto_v3_totp. - Tooling.
scripts/keys_cli.php(status, generate, fingerprint, add-key, set-active, retire),scripts/rewrap_cli.php(oneRewrapSourceper encrypted column; Core'sRewrapper: dry run, resumable, compare-and-set, never truncates a too-narrow column, one audit row per column and run) and Administration > Security > Encryption keys. The registry (src/Crypto/ColumnRegistry.php) is derived fromsecStragglerColumns()and also covers the RMM module's secrets (signing key, Mesh login key, queued job secrets, secret custom fields), including a composite-key source. - The key file directory.
generateas root creates the directory 0755 and the fileroot:www-data0640; the installer (deploy/install.sh) creates it as root after setup; status, the CLI and the panel say KEY FILE NOT REACHABLE (with the command that fixes it) when the web user cannot traverse the directory or read the file, instead of showing a plain legacy install. - Credential vault v3 (flag
config_vault_v3_enabled, default off,scripts/vault_v3_cli.php): fields sealed with the vault data key (AADcredential:<id>:<field>), per-uservw3:wraps at the next password login, mobile tokens wrap the data key, writes (including a restore from an uploaded backup) finalised to v3. Not enabled by this release. - Recovery. The backup manifests (in-app zip and
deploy/backup.sh) keep the fingerprint formula and add the key ring by kid and fingerprint (no key material);deploy/restore.shanddeploy/install.sh --restore-fromaccept--key-file/--restore-key-file; the setup wizard restore names the missing keys; the restore drill reports "Key file for this backup" and opens v3 samples. The key file is never in an archive: escrow it separately. - Ciphertext prefix checks accept
v3:everywhere (a v3 value would otherwise be mistaken for cleartext):secIsWrapped(), the cleartext-row SQL, the webhook URL masking on the list and edit pages, the drill's secret check,EndpointSecretBox(already since 26.10.13). A cleartext vault key or TOTP seed is wrapped in its own context.decryptSetting()loads Composer's autoloader itself, so a cron script that never did cannot silently read v3 values as empty. - Tests:
tests/crypto_settings.php,crypto_rewrap.php,crypto_vault.php,crypto_panel.php,tests/crypto_msp_integration.php(prefix sites, fail-closed, key file access, TOTP login over HTTP,cron/mail_queue.phpagainst a fake SMTP server with the password and an XOAUTH2 token, webhook queue delivery with the HMAC, every settings secret, provider credentials, all after a real rewrap),tests/crypto_rmm_after_rewrap.php(the RMM signing key signs a job over HTTP after a real rewrap; Mesh key, job and custom field secrets, Tactical / Level / Action1 / Sophos credentials; an unreadable key file), and RivetCore'sRewrapSourceConformanceTestCasefor the integer and string key sources plus a composite-key test.