Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions spp_pii_encryption/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,20 @@ After installing:
(last 4 characters), or Phonetic (Soundex for names)
4. Enable encryption and blind index options

Bulk migration of existing plaintext data (scan, dry-run, backup,
rollback) is provided separately and depends on the data classification
module.
To encrypt data that existed before encryption was enabled, use the
migration wizard at **Key Management > PII Encryption > Data
Migration**: scan the classification registry for PII fields on
encryption-capable models, preview with a dry run, then migrate in
batches. There is deliberately no in-app rollback or plaintext backup —
take a database snapshot before migrating.

UI Location
~~~~~~~~~~~

- **Configuration**: Key Management > PII Encryption > Field
Configuration
- **Audit Log**: Key Management > PII Encryption > Audit Log
- **Data Migration**: Key Management > PII Encryption > Data Migration

Security
~~~~~~~~
Expand Down Expand Up @@ -114,7 +118,8 @@ Extension Points
Dependencies
~~~~~~~~~~~~

``base``, ``spp_key_management``, ``spp_security``
``base``, ``spp_key_management``, ``spp_security``,
``spp_data_classification``

.. IMPORTANT::
This is an alpha version, the data model and design can change at any time without warning.
Expand All @@ -125,6 +130,47 @@ Dependencies
.. contents::
:local:

Changelog
=========

19.0.2.0.0
~~~~~~~~~~

- Re-add the PII data encryption migration wizard (Settings > Key
Management > PII Encryption > Data Migration): scans the
classification registry (``spp_data_classification``, new dependency)
for PII fields on encryption-capable models, previews the workload
with a dry run, and encrypts legacy plaintext values in place, batch
by batch, with per-record error isolation
- The wizard intentionally ships without the in-app rollback and
plaintext backup table it had in openspp-modules: the rollback never
worked (it relied on a ``skip_encryption`` context no code implements)
and a plaintext backup of the very values being encrypted contradicts
ADR-012's threat model. Take a database snapshot before migrating
- fix: a migration run now processes every batch until each field is
exhausted (previously only the first ``batch_size`` records were
touched while the summary claimed completion)
- fix: scanning a model the operator cannot read is logged and skipped
instead of aborting the whole scan
- fix: give ``spp.field.encryption.config``'s ``model_name`` an explicit
"Model Name" label — the related field inherited ir.model's "Model"
string and made Odoo warn about a label clash on every registry load
- fix(security): clicking the masked-field reveal toggle inside an
editable list no longer opens the row editor — the click used to
bubble to the cell and expose the plaintext input without a permission
check or an audit entry
- fix(security): list cells rendering a ``masked_char`` column no longer
carry the raw value in their hover tooltip (the list renderer copies
formatted char values into ``data-tooltip``, which bypassed the mask
entirely)

19.0.1.0.0
~~~~~~~~~~

- Initial migration to OpenSPP2 (encryption core: encrypted-field mixin,
blind-index search, field configuration, PII access audit log,
masked-field widget)

Bug Tracker
===========

Expand Down
1 change: 1 addition & 0 deletions spp_pii_encryption/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
from . import models
from . import wizard
4 changes: 3 additions & 1 deletion spp_pii_encryption/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "OpenSPP PII Encryption",
"summary": "Field-level encryption for PII data with searchable blind indexes",
"category": "OpenSPP/Configuration",
"version": "19.0.1.0.0",
"version": "19.0.2.0.0",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/OpenSPP2",
Expand All @@ -14,6 +14,7 @@
"base",
"spp_key_management", # Centralized key management
"spp_security",
"spp_data_classification", # Classification registry drives the migration scan
],
"external_dependencies": {
"python": [
Expand All @@ -26,6 +27,7 @@
"views/audit_log_views.xml",
"views/field_encryption_config_views.xml",
"views/menu.xml",
"wizard/encryption_migration_views.xml",
],
"assets": {
"web.assets_backend": [
Expand Down
3 changes: 3 additions & 0 deletions spp_pii_encryption/models/field_encryption_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class FieldEncryptionConfig(models.Model):
help="The model containing the field to encrypt",
)
model_name = fields.Char(
# Explicit label: the related field would inherit ir.model's "Model"
# string and clash with model_id's label (Odoo warns at every load).
string="Model Name",
related="model_id.model",
store=True,
index=True,
Expand Down
5 changes: 3 additions & 2 deletions spp_pii_encryption/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ After installing:
3. Choose the blind index type: Exact (full normalized match), Partial (last 4 characters), or Phonetic (Soundex for names)
4. Enable encryption and blind index options

Bulk migration of existing plaintext data (scan, dry-run, backup, rollback) is provided separately and depends on the data classification module.
To encrypt data that existed before encryption was enabled, use the migration wizard at **Key Management > PII Encryption > Data Migration**: scan the classification registry for PII fields on encryption-capable models, preview with a dry run, then migrate in batches. There is deliberately no in-app rollback or plaintext backup — take a database snapshot before migrating.

### UI Location

- **Configuration**: Key Management > PII Encryption > Field Configuration
- **Audit Log**: Key Management > PII Encryption > Audit Log
- **Data Migration**: Key Management > PII Encryption > Data Migration

### Security

Expand All @@ -49,4 +50,4 @@ Bulk migration of existing plaintext data (scan, dry-run, backup, rollback) is p

### Dependencies

`base`, `spp_key_management`, `spp_security`
`base`, `spp_key_management`, `spp_security`, `spp_data_classification`
28 changes: 28 additions & 0 deletions spp_pii_encryption/readme/HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
### 19.0.2.0.0

- Re-add the PII data encryption migration wizard (Settings > Key Management > PII Encryption >
Data Migration): scans the classification registry (`spp_data_classification`, new dependency)
for PII fields on encryption-capable models, previews the workload with a dry run, and encrypts
legacy plaintext values in place, batch by batch, with per-record error isolation
- The wizard intentionally ships without the in-app rollback and plaintext backup table it had in
openspp-modules: the rollback never worked (it relied on a `skip_encryption` context no code
implements) and a plaintext backup of the very values being encrypted contradicts ADR-012's
threat model. Take a database snapshot before migrating
- fix: a migration run now processes every batch until each field is exhausted (previously only
the first `batch_size` records were touched while the summary claimed completion)
- fix: scanning a model the operator cannot read is logged and skipped instead of aborting the
whole scan
- fix: give `spp.field.encryption.config`'s `model_name` an explicit "Model Name" label — the
related field inherited ir.model's "Model" string and made Odoo warn about a label clash on
every registry load
- fix(security): clicking the masked-field reveal toggle inside an editable list no longer opens
the row editor — the click used to bubble to the cell and expose the plaintext input without a
permission check or an audit entry
- fix(security): list cells rendering a `masked_char` column no longer carry the raw value in
their hover tooltip (the list renderer copies formatted char values into `data-tooltip`, which
bypassed the mask entirely)

### 19.0.1.0.0

- Initial migration to OpenSPP2 (encryption core: encrypted-field mixin, blind-index search,
field configuration, PII access audit log, masked-field widget)
6 changes: 6 additions & 0 deletions spp_pii_encryption/security/ir.model.access.csv
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ access_pii_audit_log_admin,PII Audit Log Admin,model_spp_pii_audit_log,group_enc
access_pii_audit_log_system,PII Audit Log System,model_spp_pii_audit_log,base.group_system,1,0,1,0
access_field_encryption_config_admin,Field Encryption Config Admin,model_spp_field_encryption_config,group_encryption_admin,1,1,1,1
access_field_encryption_config_system,Field Encryption Config System,model_spp_field_encryption_config,base.group_system,1,1,1,1
access_encryption_migration_wizard_admin,Encryption Migration Wizard Admin,model_spp_encryption_migration_wizard,group_encryption_admin,1,1,1,1
access_encryption_migration_wizard_system,Encryption Migration Wizard System,model_spp_encryption_migration_wizard,base.group_system,1,1,1,1
access_encryption_migration_scan_result_admin,Encryption Migration Scan Result Admin,model_spp_encryption_migration_scan_result,group_encryption_admin,1,1,1,1
access_encryption_migration_scan_result_system,Encryption Migration Scan Result System,model_spp_encryption_migration_scan_result,base.group_system,1,1,1,1
access_encryption_migration_log_admin,Encryption Migration Log Admin,model_spp_encryption_migration_log,group_encryption_admin,1,1,1,1
access_encryption_migration_log_system,Encryption Migration Log System,model_spp_encryption_migration_log,base.group_system,1,1,1,1
69 changes: 56 additions & 13 deletions spp_pii_encryption/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -427,16 +427,20 @@ <h1>Configuration</h1>
(last 4 characters), or Phonetic (Soundex for names)</li>
<li>Enable encryption and blind index options</li>
</ol>
<p>Bulk migration of existing plaintext data (scan, dry-run, backup,
rollback) is provided separately and depends on the data classification
module.</p>
<p>To encrypt data that existed before encryption was enabled, use the
migration wizard at <strong>Key Management &gt; PII Encryption &gt; Data
Migration</strong>: scan the classification registry for PII fields on
encryption-capable models, preview with a dry run, then migrate in
batches. There is deliberately no in-app rollback or plaintext backup —
take a database snapshot before migrating.</p>
</div>
<div class="section" id="ui-location">
<h1>UI Location</h1>
<ul class="simple">
<li><strong>Configuration</strong>: Key Management &gt; PII Encryption &gt; Field
Configuration</li>
<li><strong>Audit Log</strong>: Key Management &gt; PII Encryption &gt; Audit Log</li>
<li><strong>Data Migration</strong>: Key Management &gt; PII Encryption &gt; Data Migration</li>
</ul>
</div>
<div class="section" id="security">
Expand Down Expand Up @@ -485,7 +489,8 @@ <h1>Extension Points</h1>
</div>
<div class="section" id="dependencies">
<h1>Dependencies</h1>
<p><tt class="docutils literal">base</tt>, <tt class="docutils literal">spp_key_management</tt>, <tt class="docutils literal">spp_security</tt></p>
<p><tt class="docutils literal">base</tt>, <tt class="docutils literal">spp_key_management</tt>, <tt class="docutils literal">spp_security</tt>,
<tt class="docutils literal">spp_data_classification</tt></p>
<div class="admonition important">
<p class="first admonition-title">Important</p>
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
Expand All @@ -494,32 +499,70 @@ <h1>Dependencies</h1>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-4">Maintainers</a></li>
<li><a class="reference internal" href="#changelog" id="toc-entry-1">Changelog</a></li>
</ul>
</li>
</div>
<div class="section" id="changelog">
<h2><a class="toc-backref" href="#toc-entry-1">Changelog</a></h2>
</div>
</div>
<div class="section" id="section-1">
<h1>19.0.2.0.0</h1>
<ul class="simple">
<li>Re-add the PII data encryption migration wizard (Settings &gt; Key
Management &gt; PII Encryption &gt; Data Migration): scans the
classification registry (<tt class="docutils literal">spp_data_classification</tt>, new dependency)
for PII fields on encryption-capable models, previews the workload
with a dry run, and encrypts legacy plaintext values in place, batch
by batch, with per-record error isolation</li>
<li>The wizard intentionally ships without the in-app rollback and
plaintext backup table it had in openspp-modules: the rollback never
worked (it relied on a <tt class="docutils literal">skip_encryption</tt> context no code implements)
and a plaintext backup of the very values being encrypted contradicts
ADR-012’s threat model. Take a database snapshot before migrating</li>
<li>fix: a migration run now processes every batch until each field is
exhausted (previously only the first <tt class="docutils literal">batch_size</tt> records were
touched while the summary claimed completion)</li>
<li>fix: scanning a model the operator cannot read is logged and skipped
instead of aborting the whole scan</li>
<li>fix: give <tt class="docutils literal">spp.field.encryption.config</tt>’s <tt class="docutils literal">model_name</tt> an explicit
“Model Name” label — the related field inherited ir.model’s “Model”
string and made Odoo warn about a label clash on every registry load</li>
<li>fix(security): clicking the masked-field reveal toggle inside an
editable list no longer opens the row editor — the click used to
bubble to the cell and expose the plaintext input without a permission
check or an audit entry</li>
<li>fix(security): list cells rendering a <tt class="docutils literal">masked_char</tt> column no longer
carry the raw value in their hover tooltip (the list renderer copies
formatted char values into <tt class="docutils literal"><span class="pre">data-tooltip</span></tt>, which bypassed the mask
entirely)</li>
</ul>
</div>
<div class="section" id="section-2">
<h1>19.0.1.0.0</h1>
<ul class="simple">
<li>Initial migration to OpenSPP2 (encryption core: encrypted-field mixin,
blind-index search, field configuration, PII access audit log,
masked-field widget)</li>
</ul>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h2>
<h2>Bug Tracker</h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OpenSPP/OpenSPP2/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OpenSPP/OpenSPP2/issues/new?body=module:%20spp_pii_encryption%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-2">Credits</a></h2>
<h2>Credits</h2>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-3">Authors</a></h3>
<h3>Authors</h3>
<ul class="simple">
<li>OpenSPP.org</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-4">Maintainers</a></h3>
<h3>Maintainers</h3>
<p>Current maintainers:</p>
<p><a class="reference external image-reference" href="https://github.com/jeremi"><img alt="jeremi" src="https://github.com/jeremi.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/gonzalesedwin1123"><img alt="gonzalesedwin1123" src="https://github.com/gonzalesedwin1123.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OpenSPP/OpenSPP2/tree/19.0/spp_pii_encryption">OpenSPP/OpenSPP2</a> project on GitHub.</p>
Expand Down
15 changes: 15 additions & 0 deletions spp_pii_encryption/static/src/js/masked_field.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,26 @@

import {registry} from "@web/core/registry";
import {CharField} from "@web/views/fields/char/char_field";
import {ListRenderer} from "@web/views/list/list_renderer";
import {patch} from "@web/core/utils/patch";
import {useState} from "@odoo/owl";
import {useService} from "@web/core/utils/hooks";
import {user} from "@web/core/user";
import {_t} from "@web/core/l10n/translation";

// The list renderer copies every char cell's FORMATTED (raw) value into the
// cell's data-tooltip so truncated columns stay readable — which would leak
// the plaintext of a masked column on hover, bypassing the widget entirely.
// Masked columns get no tooltip.
patch(ListRenderer.prototype, {
getCellTitle(column, record) {
if (column.widget === "masked_char") {
return undefined;
}
return super.getCellTitle(column, record);
},
});

/**
* MaskedCharField - A field widget that displays masked PII values
* with the ability to reveal the actual value for authorized users.
Expand Down
2 changes: 1 addition & 1 deletion spp_pii_encryption/static/src/xml/masked_field.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
t-if="props.record.data[props.name]"
type="button"
class="btn btn-link btn-sm p-0 ms-2 o_masked_toggle"
t-on-click="toggleReveal"
t-on-click.stop="toggleReveal"
t-att-disabled="state.isLoading"
t-att-title="state.isRevealed ? 'Hide value' : 'Reveal value'"
>
Expand Down
1 change: 1 addition & 0 deletions spp_pii_encryption/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
# Key provider tests are now in spp_key_management
from . import test_encrypted_field_mixin
from . import test_encryption_migration
from . import test_field_encryption_config
from . import test_audit_log
Loading
Loading