From 0b92294586f2f40ec0e6680ee4c93fe0f0206342 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Sun, 24 May 2026 12:22:40 -0400 Subject: [PATCH] fix(shopfloor-sec): narrow kiosk ir.config_parameter scope + doc accuracy Code-review findings on Phase A (Tablet PIN Session Redesign): I1: Security XML comment now honestly describes the kiosk as Internal User + explicit reads, not 'near-zero ACL'. base.group_user is kept (required for auth='user' HTTP routes to function) but the comment no longer overstates how locked-down the kiosk is. I2: New ir.rule scopes the kiosk's ir.config_parameter read to keys matching 'fp.tablet.%' or 'fp.shopfloor.%'. Combined with the existing model-level read ACL, kiosk can no longer enumerate third-party secrets (e.g. fusion_tasks.vapid_private_key) or arbitrary API keys stored in ICP. I3: post-migrate docstring now advises sysadmins to unlink the plaintext ICP password row after kiosk tablets are paired, to minimise plaintext-in-backups risk. Rotation procedure documented. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../migrations/19.0.33.0.0/post-migrate.py | 17 +++++++-- .../security/fp_tablet_kiosk_security.xml | 35 +++++++++++++++---- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/fusion_plating/fusion_plating_shopfloor/migrations/19.0.33.0.0/post-migrate.py b/fusion_plating/fusion_plating_shopfloor/migrations/19.0.33.0.0/post-migrate.py index ade00920..2cea7722 100644 --- a/fusion_plating/fusion_plating_shopfloor/migrations/19.0.33.0.0/post-migrate.py +++ b/fusion_plating/fusion_plating_shopfloor/migrations/19.0.33.0.0/post-migrate.py @@ -10,8 +10,21 @@ After this hook runs, retrieve the kiosk password via: 'fp.tablet.kiosk_password'))" Then sysadmin enters that password ONCE in the tablet browser to log -the kiosk session in. Browser cookie persists per the configured -session_db.session_lifetime. +the kiosk session in. Browser cookie persists per Odoo's configured +session lifetime. + +Security note: the generated password is stored in plaintext in +ir.config_parameter so a sysadmin can retrieve it. After the kiosk +tablets are paired (browser cookies established), DELETE the ICP key +to remove the plaintext from the DB + future backups: + + env['ir.config_parameter'].search([ + ('key', '=', 'fp.tablet.kiosk_password') + ]).unlink() + +If you ever need to re-pair a tablet later, rotate by setting a new +password on the fp_tablet_kiosk user form, then re-authenticate the +tablet browser with that new value. """ import logging import secrets diff --git a/fusion_plating/fusion_plating_shopfloor/security/fp_tablet_kiosk_security.xml b/fusion_plating/fusion_plating_shopfloor/security/fp_tablet_kiosk_security.xml index 88d2fe8f..fb50bdbf 100644 --- a/fusion_plating/fusion_plating_shopfloor/security/fp_tablet_kiosk_security.xml +++ b/fusion_plating/fusion_plating_shopfloor/security/fp_tablet_kiosk_security.xml @@ -1,14 +1,37 @@ + NO privilege_id (would clutter the role picker). + + The dedicated fp_tablet_kiosk user inherits the standard Internal + User reads via base.group_user (required for any auth='user' HTTP + route to function). On top of that, this group grants explicit + read on res.users (tile grid) and a NARROWED read on + ir.config_parameter (whitelisted keys only — see ir.rule below). + No write access to anything; no read on business records + (fp.job, sale.order, fp.certificate, fp.part.catalog, etc.). + + Threat model: a compromised kiosk session can enumerate users + and read whitelisted tablet/shopfloor config keys, nothing more. + --> Tablet Kiosk Session 100 + + + + Kiosk: read only fp.tablet/fp.shopfloor config keys + + + ['|', ('key', '=like', 'fp.tablet.%'), ('key', '=like', 'fp.shopfloor.%')] + + + + +