Skip to content
Draft
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
128 changes: 128 additions & 0 deletions certificate_data_encryption/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

===========================
Certificate Data Encryption
===========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:41d07edb455548e16222dca07093317dbcc0b014e6a8f471710a4b70dc1fb00b
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--env-lightgray.png?logo=github
:target: https://github.com/OCA/server-env/tree/18.0/certificate_data_encryption
:alt: OCA/server-env
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-env-18-0/server-env-18-0-certificate_data_encryption
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/server-env&target_branch=18.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module allows to store the passwords of the certificates and
private keys managed by the core ``certificate`` module in an
**encrypted** and **per environment** way (dev, staging, production),
instead of clear text in the database.

It connects the core ``certificate`` module with the OCA server-env
encryption mechanism (``server_environment_data_encryption`` and
``data_encryption``): the passwords become environment managed fields
(``server.env.mixin``) whose values are stored encrypted in the
``encrypted.data`` table using a Fernet key per environment.

Covered fields:

- ``certificate.certificate.pkcs12_password``
- ``certificate.key.password``

**Table of contents**

.. contents::
:local:

Usage
=====

Follow the configuration of the ``server_environment`` and
``server_environment_data_encryption`` modules:

- define ``running_env`` in the Odoo configuration file;

- define one Fernet key per environment in the ``[options]`` section,
e.g. ``encryption_key_prod = ZZZ``;

- generate the keys with:
``python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key())'``.

The passwords are **no longer stored in the**
``certificate.certificate`` and ``certificate.key`` **tables**: they are
set/changed from the forms (the screen shows which environment is being
edited) and are stored encrypted in the ``encrypted.data`` table, per
environment.

If no encryption key is configured for the current environment, the
module has no effect (default behavior of
``server_environment_data_encryption``).

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

Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-env/issues>`_.
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
`feedback <https://github.com/OCA/server-env/issues/new?body=module:%20certificate_data_encryption%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Akretion

Contributors
------------

- `Akretion <https://www.akretion.com/pt-BR>`__:

- Raphaël Valyi <raphael.valyi@akretion.com.br>

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-rvalyi| image:: https://github.com/rvalyi.png?size=40px
:target: https://github.com/rvalyi
:alt: rvalyi

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-rvalyi|

This module is part of the `OCA/server-env <https://github.com/OCA/server-env/tree/18.0/certificate_data_encryption>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
4 changes: 4 additions & 0 deletions certificate_data_encryption/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (C) 2026 Akretion (http://www.akretion.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import models
18 changes: 18 additions & 0 deletions certificate_data_encryption/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (C) 2026 Akretion (http://www.akretion.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Certificate Data Encryption",
"summary": "Store certificate passwords encrypted by environment",
"version": "18.0.1.0.0",
"development_status": "Beta",
"category": "Tools",
"website": "https://github.com/OCA/server-env",
"author": "Akretion, Odoo Community Association (OCA)",
"maintainers": ["rvalyi"],
"license": "AGPL-3",
"depends": [
"certificate",
"server_environment_data_encryption",
],
}
1 change: 1 addition & 0 deletions certificate_data_encryption/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import certificate
62 changes: 62 additions & 0 deletions certificate_data_encryption/models/certificate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Copyright (C) 2026 Akretion (http://www.akretion.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, api, models
from odoo.exceptions import ValidationError


class Certificate(models.Model):
_name = "certificate.certificate"
_inherit = ["certificate.certificate", "server.env.mixin"]

@property
def _server_env_fields(self):
return {"pkcs12_password": {}}

def _compute_server_env(self):
# While a record is being created (e.g. when Odoo precomputes the
# stored computed fields such as ``pem_certificate`` on a new
# record), the encrypted value cannot be resolved yet: the
# encrypted data store is keyed by record id. Skipping the
# computation for new records keeps the value provided in the
# creation values available, so the certificate data can still be
# extracted from the file exactly like without this module.
real_records = self.filtered(lambda r: r.id)
return super(Certificate, real_records)._compute_server_env()

@api.constrains("content", "pem_certificate")
def _constrains_certificate_loaded(self):
# The password is environment managed: it is no longer stored in
# the table and may be written alone (e.g. to define the value of
# another environment from the running one) or not be defined at
# all for the current environment. Check the file consistency
# directly from the content, as reading ``pem_certificate`` here
# could re-trigger its computation in the middle of a create (the
# check is done again once it is computed anyway).
for cert in self.filtered(lambda c: c.content and c.pkcs12_password):
content = cert.with_context(bin_size=False).content
password = cert.pkcs12_password.encode()
leaf_pem, _additional_pems, _format = cert._parse_certificate_content(
content, password
)
if not leaf_pem:
raise ValidationError(
_(
"This certificate could not be loaded. "
"Either the content or the password is erroneous."
)
)


class CertificateKey(models.Model):
_name = "certificate.key"
_inherit = ["certificate.key", "server.env.mixin"]

@property
def _server_env_fields(self):
return {"password": {}}

def _compute_server_env(self):
# See the comment in certificate.certificate._compute_server_env.
real_records = self.filtered(lambda r: r.id)
return super(CertificateKey, real_records)._compute_server_env()
3 changes: 3 additions & 0 deletions certificate_data_encryption/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
2 changes: 2 additions & 0 deletions certificate_data_encryption/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- [Akretion](https://www.akretion.com/pt-BR):
- Raphaël Valyi \<<raphael.valyi@akretion.com.br>\>
15 changes: 15 additions & 0 deletions certificate_data_encryption/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
This module allows to store the passwords of the certificates and
private keys managed by the core ``certificate`` module in an
**encrypted** and **per environment** way (dev, staging, production),
instead of clear text in the database.

It connects the core ``certificate`` module with the OCA server-env
encryption mechanism (``server_environment_data_encryption`` and
``data_encryption``): the passwords become environment managed fields
(``server.env.mixin``) whose values are stored encrypted in the
``encrypted.data`` table using a Fernet key per environment.

Covered fields:

- ``certificate.certificate.pkcs12_password``
- ``certificate.key.password``
18 changes: 18 additions & 0 deletions certificate_data_encryption/readme/USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Follow the configuration of the ``server_environment`` and
``server_environment_data_encryption`` modules:

- define ``running_env`` in the Odoo configuration file;
- define one Fernet key per environment in the ``[options]`` section,
e.g. ``encryption_key_prod = ZZZ``;

- generate the keys with: ``python -c 'from cryptography.fernet import
Fernet; print(Fernet.generate_key())'``.

The passwords are **no longer stored in the** ``certificate.certificate``
and ``certificate.key`` **tables**: they are set/changed from the forms
(the screen shows which environment is being edited) and are stored
encrypted in the ``encrypted.data`` table, per environment.

If no encryption key is configured for the current environment, the
module has no effect (default behavior of
``server_environment_data_encryption``).
1 change: 1 addition & 0 deletions certificate_data_encryption/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_certificate_data_encryption
Loading
Loading