From a82b19e785067c42b1086bc689020c7cf9c306ee Mon Sep 17 00:00:00 2001 From: vineela-afk Date: Tue, 16 Jan 2024 08:30:16 +0530 Subject: [PATCH 01/13] added keymanager --- g2p_encryption/models/keymanager_api.py | 355 ++++++++++++++++++ .../controllers/__init__.py | 1 + .../controllers/payments.py | 7 + g2p_registry_encryption/models/partner.py | 274 ++++++++++---- .../models/payment_file_keymanager.py | 97 +++++ .../models/payment_file_qrcode_config.py | 179 +++++++++ .../models/payment_key_set.py | 147 ++++++++ 7 files changed, 993 insertions(+), 67 deletions(-) create mode 100644 g2p_encryption/models/keymanager_api.py create mode 100644 g2p_registry_encryption/controllers/__init__.py create mode 100644 g2p_registry_encryption/controllers/payments.py create mode 100644 g2p_registry_encryption/models/payment_file_keymanager.py create mode 100644 g2p_registry_encryption/models/payment_file_qrcode_config.py create mode 100644 g2p_registry_encryption/models/payment_key_set.py diff --git a/g2p_encryption/models/keymanager_api.py b/g2p_encryption/models/keymanager_api.py new file mode 100644 index 0000000..5a9f450 --- /dev/null +++ b/g2p_encryption/models/keymanager_api.py @@ -0,0 +1,355 @@ +import requests +from datetime import datetime + +import requests + + +class OdooAuth(object): + def __init__(self, auth_url, auth_client_id, auth_client_secret, auth_grant_type): + self.auth_url = auth_url + self.auth_client_id = auth_client_id + self.auth_client_secret = auth_client_secret + self.auth_grant_type = auth_grant_type + + def get_access_token(self): + data = { + "client_id": self.auth_client_id, + "client_secret": self.auth_client_secret, + "grant_type": self.auth_grant_type, + } + response = requests.post(self.auth_url, data=data) + if response.status_code == 200: + access_token = response.json().get("access_token") + return access_token + else: + response.raise_for_status() + + +# odoo_token = { +# "auth_url": "https://keycloak.dev.openg2p.net/realms/mosip/protocol/openid-connect/token", +# "auth_client_id": "mosip-admin-client", +# "auth_client_secret": "F42OX9zwiaUfzwsk", +# "auth_grant_type": "client_credentials", +# } + +# odoo_auth = OdooAuth(**odoo_token) +# access_token = odoo_auth.get_access_token() +# print(f"Access Token: {access_token}") + + +class EncryptionModule(object): + def __init__(self, base_url, odoo_auth): + self.base_url = base_url + self.access_token = odoo_auth.get_access_token() + self.current_time = self.generate_current_time() + + def generate_current_time(self): + # Generate current timestamp in ISO 8601 format + return datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" + + def get_certificate(self, data): + url = f"{self.base_url}/getCertificate" + headers = {"Cookie": f"Authorization={self.access_token}"} + + params = { + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + } + response = requests.get(url, headers=headers, params=params) + return response.json().get("response", {}).get("certificate", None) + + def encrypt_data(self, data): + url = f"{self.base_url}/encrypt" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "timeStamp": self.current_time, + "data": data.get("data", "string"), + "salt": "string", + "aad": "string", + }, + } + response = requests.post(url, json=payload, headers=headers) + print(response.content) + + return response.json().get("response", {}).get("data", None) + + def jwt_encrypt_data(self, data): + url = f"{self.base_url}/jwtencrypt" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "data": "string", + "enableDefCompression": True, + "includeCertificate": True, + "includeCertHash": True, + "jwkSetUrl": "string", + "x509Certificate": "string", + }, + } + response = requests.post(url, json=payload, headers=headers) + return response.json() + + def jwt_decrypt_data(self, data): + url = f"{self.base_url}/jwtdecrypt" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "encData": "string", + }, + } + response = requests.post(url, json=payload, headers=headers) + return response.json() + + def decrypt_data(self, data): + url = f"{self.base_url}/decrypt" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "timeStamp": self.current_time, + "data": data.get("data", "string"), + "salt": "string", + "aad": "string", + }, + } + response = requests.post(url, json=payload, headers=headers) + return response.json().get("response", {}).get("data", None) + + def get_signing_public_key(self): + url = f"{self.base_url}/getSigningPublicKey" + headers = {"Cookie": f"Authorization={self.access_token}"} + + response = requests.get(url, headers=headers) + return response.json() + + def get_encryption_public_key(self): + url = f"{self.base_url}/getEncryptionPublicKey" + headers = {"Cookie": f"Authorization={self.access_token}"} + + response = requests.get(url, headers=headers) + return response.json() + + def encrypt_data_with_pin(self, data): + url = f"{self.base_url}/encryptWithPin" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": {"data": "string", "userPin": "string"}, + } + response = requests.post(url, json=payload, headers=headers) + return response.json() + + def decrypt_data_with_pin(self, data): + url = f"{self.base_url}/decryptWithPin" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": {"data": "string", "userPin": "string"}, + } + response = requests.post(url, json=payload, headers=headers) + return response.json() + + def jwt_verify(self, data): + url = f"{self.base_url}/jwtVerify" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "jwtSignatureData": "string", + "actualData": "string", + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "certificateData": "string", + "validateTrust": True, + "domain": "string", + }, + } + response = requests.post(url, json=payload, headers=headers) + return response.json() + + def jwt_sign(self, data): + data_to_sign = data.get("dataToSign", None) + + if data_to_sign is None: + print("Data to sign is null. Skipping JWT signing.") + return None + url = f"{self.base_url}/jwtSign" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "dataToSign": data.get("dataToSign", "string"), + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "includePayload": True, + "includeCertificate": True, + "includeCertHash": True, + "certificateUrl": data.get("certificateUrl", "string"), + }, + } + response = requests.post(url, json=payload, headers=headers) + try: + jwt_signed_data = ( + response.json().get("response", {}).get("jwtSignedData", None) + ) + except ValueError: + print("Error parsing response JSON. JWT signing failed.") + jwt_signed_data = None + + return jwt_signed_data + + def jws_sign(self, data): + url = f"{self.base_url}/jwsSign" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "dataToSign": "string", + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "includePayload": True, + "includeCertificate": True, + "includeCertHash": True, + "certificateUrl": "string", + "validateJson": True, + "b64JWSHeaderParam": True, + "signAlgorithm": "string", + }, + } + response = requests.post(url, json=payload, headers=headers) + return response.json() + + def generate_masterkey_optional(self, data, object_type): + url = f"{self.base_url}/generateMasterKey/{object_type}" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "force": True, + "commonName": "string", + "organizationUnit": "string", + "organization": "string", + "location": "string", + "state": "string", + "country": "string", + }, + } + response = requests.post(url, json=payload, headers=headers) + return response.json() + + def generate_csr(self, data): + url = f"{self.base_url}/generateCsr" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "applicationId": data.get("applicationId", "string"), + "referenceId": data.get("referenceId", "string"), + "commonName": "string", + "organizationUnit": "string", + "organization": "string", + "location": "string", + "state": "string", + "country": "string", + }, + } + response = requests.post(url, json=payload, headers=headers) + return response.json() + + def generate_symmetric_key(self, data): + url = f"{self.base_url}/generateSymmetricKey" + headers = {"Cookie": f"Authorization={self.access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": self.current_time, + "metadata": {}, + "request": { + "applicationId": "string", + "referenceId": "string", + "force": True, + }, + } + + response = requests.post(url, json=payload, headers=headers) + return response.json() + + +# odoo_token = { +# "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", +# "auth_client_id": "openg2p-admin-client", +# "auth_client_secret": "x75SU2hqKQX7IPob", +# "auth_grant_type": "client_credentials", +# } + +# odoo_auth = OdooAuth(**odoo_token) +# access_token = odoo_auth.get_access_token() +# print(f"Access Token: {access_token}") + +# odoo_api = EncryptionModule( +# base_url="https://dev.openg2p.net/v1/keymanager", +# odoo_auth=odoo_auth, +# ) + +# certificate_data = odoo_api.get_certificate( +# { +# "applicationId": "KERNEL", +# "referenceId": "SIGN", +# } +# ) +# print("certificate Data:", certificate_data) +# data_to_encrypt = { +# "applicationId": "KERNEL", +# "referenceId": "SIGN", +# "dataToSign": "aGVsbG8gd29ybGQ=", +# "certificateUrl": certificate_data, +# } +# encrypted_data = odoo_api.jwt_sign(data_to_encrypt) +# print("Encrypted Data:", encrypted_data) diff --git a/g2p_registry_encryption/controllers/__init__.py b/g2p_registry_encryption/controllers/__init__.py new file mode 100644 index 0000000..8ac3dc0 --- /dev/null +++ b/g2p_registry_encryption/controllers/__init__.py @@ -0,0 +1 @@ +from . import payments diff --git a/g2p_registry_encryption/controllers/payments.py b/g2p_registry_encryption/controllers/payments.py new file mode 100644 index 0000000..f52f3e6 --- /dev/null +++ b/g2p_registry_encryption/controllers/payments.py @@ -0,0 +1,7 @@ +from odoo.addons.base_rest.controllers import main + + +class RegistryApiController(main.RestController): + _root_path = "/api/v1/payments/" + _collection_name = "base.rest.payment.services" + _default_auth = "user" diff --git a/g2p_registry_encryption/models/partner.py b/g2p_registry_encryption/models/partner.py index ea8b402..28cb064 100644 --- a/g2p_registry_encryption/models/partner.py +++ b/g2p_registry_encryption/models/partner.py @@ -1,10 +1,135 @@ -import logging +# import logging -from odoo import api, fields, models +# from odoo import api, fields, models -from odoo.addons.g2p_encryption.models.crypto import AESCipher +# from odoo.addons.g2p_encryption.models.crypto import AESCipher -_logger = logging.getLogger(__name__) +# _logger = logging.getLogger(__name__) + + +# class EncryptedPartner(models.Model): +# _inherit = "res.partner" + +# # is_encrypted = fields.Boolean("Is encrypted?") + +# name_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field("name", "name_decrypted"), store=False +# ) +# family_name_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field( +# "family_name", "family_name_decrypted" +# ), +# store=False, +# ) +# given_name_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field("given_name", "given_name_decrypted"), +# store=False, +# ) +# addl_name_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field("addl_name", "addl_name_decrypted"), +# store=False, +# ) +# email_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field("email", "email_decrypted"), +# store=False, +# ) +# phone_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field("phone", "phone_decrypted"), +# store=False, +# ) +# mobile_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field("mobile", "mobile_decrypted"), +# store=False, +# ) +# address_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field("address", "address_decrypted"), +# store=False, +# ) +# birth_place_decrypted = fields.Char( +# compute=lambda self: self._decrypt_field( +# "birth_place", "birth_place_decrypted" +# ), +# store=False, +# ) + +# @api.model +# def create(self, vals): +# record = super(EncryptedPartner, self).create(vals) +# # TODO encryption key should be moved to a secret vault. +# encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") +# if encryption_key: +# crypto = AESCipher(encryption_key) +# record["name"] = crypto.encrypt(record["name"]) if record["name"] else None +# record["family_name"] = ( +# crypto.encrypt(record["family_name"]) if record["family_name"] else None +# ) +# record["given_name"] = ( +# crypto.encrypt(record["given_name"]) if record["given_name"] else None +# ) +# record["addl_name"] = ( +# crypto.encrypt(record["addl_name"]) if record["addl_name"] else None +# ) +# record["display_name"] = ( +# crypto.encrypt(record["display_name"]) +# if record["display_name"] +# else None +# ) +# record["email"] = ( +# crypto.encrypt(record["email"]) if record["email"] else None +# ) +# record["phone"] = ( +# crypto.encrypt(record["phone"]) if record["phone"] else None +# ) +# record["mobile"] = ( +# crypto.encrypt(record["mobile"]) if record["mobile"] else None +# ) +# record["address"] = ( +# crypto.encrypt(record["address"]) if record["address"] else None +# ) +# record["birth_place"] = ( +# crypto.encrypt(record["birth_place"]) if record["birth_place"] else None +# ) + +# return record + +# # @api.model +# # def write(self, vals): +# # record = super(EncryptedPartner, self).create(vals) +# # #TODO encryption key should be moved to a secret vault. +# # encryption_key = self.env['ir.config_parameter'].get_param('g2p_enc_key', '') +# # if encryption_key: +# # crypto = AESCipher(encryption_key) +# # record["name"] = crypto.encrypt(record["name"]) if record["name"] else None +# # record["family_name"] = crypto.encrypt(record["family_name"]) if record["family_name"] else None +# # record["given_name"] = crypto.encrypt(record["given_name"]) if record["given_name"] else None +# # record["addl_name"] = crypto.encrypt(record["addl_name"]) if record["addl_name"] else None +# # record["display_name"] = crypto.encrypt(record["display_name"]) if record["display_name"] else None +# # record["email"] = crypto.encrypt(record["email"]) if record["email"] else None +# # record["phone"] = crypto.encrypt(record["phone"]) if record["phone"] else None +# # record["mobile"] = crypto.encrypt(record["mobile"]) if record["mobile"] else None +# # record["address"] = crypto.encrypt(record["address"]) if record["address"] else None +# # record["birth_place"] = crypto.encrypt(record["birth_place"]) if record["birth_place"] else None + +# # return record + +# def _decrypt_field(self, actual_field, decrypted_field): +# # TODO encryption key should be moved to a secret vault. +# encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") +# if encryption_key: +# crypto = AESCipher(encryption_key) +# for rec in self: +# if rec[actual_field]: +# rec[decrypted_field] = crypto.decrypt(rec[actual_field]) +# else: +# rec[decrypted_field] = "" +# _logger.info("%s , %s", decrypted_field, rec[decrypted_field]) + + +import base64 +from odoo import fields + +from odoo import models, fields, api +from odoo.addons.g2p_encryption.models.keymanager_api import EncryptionModule, OdooAuth class EncryptedPartner(models.Model): @@ -55,71 +180,86 @@ class EncryptedPartner(models.Model): @api.model def create(self, vals): record = super(EncryptedPartner, self).create(vals) - # TODO encryption key should be moved to a secret vault. - encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") - if encryption_key: - crypto = AESCipher(encryption_key) - record["name"] = crypto.encrypt(record["name"]) if record["name"] else None - record["family_name"] = ( - crypto.encrypt(record["family_name"]) if record["family_name"] else None - ) - record["given_name"] = ( - crypto.encrypt(record["given_name"]) if record["given_name"] else None - ) - record["addl_name"] = ( - crypto.encrypt(record["addl_name"]) if record["addl_name"] else None - ) - record["display_name"] = ( - crypto.encrypt(record["display_name"]) - if record["display_name"] - else None - ) - record["email"] = ( - crypto.encrypt(record["email"]) if record["email"] else None - ) - record["phone"] = ( - crypto.encrypt(record["phone"]) if record["phone"] else None - ) - record["mobile"] = ( - crypto.encrypt(record["mobile"]) if record["mobile"] else None - ) - record["address"] = ( - crypto.encrypt(record["address"]) if record["address"] else None - ) - record["birth_place"] = ( - crypto.encrypt(record["birth_place"]) if record["birth_place"] else None + odoo_token = { + "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", + "auth_client_id": "openg2p-admin-client", + "auth_client_secret": "x75SU2hqKQX7IPob", + "auth_grant_type": "client_credentials", + } + + odoo_auth = OdooAuth(**odoo_token) + base_url = "https://dev.openg2p.net/v1/keymanager" + encryption_module_instance = EncryptionModule(base_url, odoo_auth) + application_id = "REGISTRATION" + reference_id = "string" + + # access_token = odoo_auth.get_access_token() + # print(f"Access Token: {access_token}") + + def encrypt_field(field_value): + encoded_field_value = base64.b64encode(field_value.encode()).decode() + # print(f"Original Field Value: {field_value}") + encrypted_data = encryption_module_instance.encrypt_data( + { + "applicationId": application_id, + "referenceId": reference_id, + "data": encoded_field_value, + } ) + return encrypted_data - return record + record["name"] = encrypt_field(record["name"]) if record["name"] else None + record["family_name"] = ( + encrypt_field(record["family_name"]) if record["family_name"] else None + ) + record["given_name"] = ( + encrypt_field(record["given_name"]) if record["given_name"] else None + ) + record["addl_name"] = ( + encrypt_field(record["addl_name"]) if record["addl_name"] else None + ) + record["display_name"] = ( + encrypt_field(record["display_name"]) if record["display_name"] else None + ) + record["email"] = encrypt_field(record["email"]) if record["email"] else None + record["phone"] = encrypt_field(record["phone"]) if record["phone"] else None + record["mobile"] = encrypt_field(record["mobile"]) if record["mobile"] else None + record["address"] = ( + encrypt_field(record["address"]) if record["address"] else None + ) + record["birth_place"] = ( + encrypt_field(record["birth_place"]) if record["birth_place"] else None + ) - # @api.model - # def write(self, vals): - # record = super(EncryptedPartner, self).create(vals) - # #TODO encryption key should be moved to a secret vault. - # encryption_key = self.env['ir.config_parameter'].get_param('g2p_enc_key', '') - # if encryption_key: - # crypto = AESCipher(encryption_key) - # record["name"] = crypto.encrypt(record["name"]) if record["name"] else None - # record["family_name"] = crypto.encrypt(record["family_name"]) if record["family_name"] else None - # record["given_name"] = crypto.encrypt(record["given_name"]) if record["given_name"] else None - # record["addl_name"] = crypto.encrypt(record["addl_name"]) if record["addl_name"] else None - # record["display_name"] = crypto.encrypt(record["display_name"]) if record["display_name"] else None - # record["email"] = crypto.encrypt(record["email"]) if record["email"] else None - # record["phone"] = crypto.encrypt(record["phone"]) if record["phone"] else None - # record["mobile"] = crypto.encrypt(record["mobile"]) if record["mobile"] else None - # record["address"] = crypto.encrypt(record["address"]) if record["address"] else None - # record["birth_place"] = crypto.encrypt(record["birth_place"]) if record["birth_place"] else None - - # return record + print("create methoddd", record) + return record def _decrypt_field(self, actual_field, decrypted_field): - # TODO encryption key should be moved to a secret vault. - encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") - if encryption_key: - crypto = AESCipher(encryption_key) - for rec in self: - if rec[actual_field]: - rec[decrypted_field] = crypto.decrypt(rec[actual_field]) - else: - rec[decrypted_field] = "" - _logger.info("%s , %s", decrypted_field, rec[decrypted_field]) + odoo_token = { + "auth_url": "https://keycloak.dev.openg2p.net/realms/mosip/protocol/openid-connect/token", + "auth_client_id": "openg2p-admin-client", + "auth_client_secret": "x75SU2hqKQX7IPob", + "auth_grant_type": "client_credentials", + } + + odoo_auth = OdooAuth(**odoo_token) + base_url = "https://dev.openg2p.net/v1/keymanager" + encryption_module_instance = EncryptionModule(base_url, odoo_auth) + application_id = "KERNEL" + reference_id = "SIGN" + + def decrypt_field(field_value): + return encryption_module_instance.decrypt_data( + { + "applicationId": application_id, + "referenceId": reference_id, + "data": field_value, + } + ) + + for rec in self: + if rec[actual_field]: + rec[decrypted_field] = decrypt_field(rec[actual_field]) + else: + rec[decrypted_field] = "" + # print(decrypted_field, ",", rec[decrypted_field]) diff --git a/g2p_registry_encryption/models/payment_file_keymanager.py b/g2p_registry_encryption/models/payment_file_keymanager.py new file mode 100644 index 0000000..790e4cc --- /dev/null +++ b/g2p_registry_encryption/models/payment_file_keymanager.py @@ -0,0 +1,97 @@ +# import uuid +# from datetime import datetime, timedelta +# from urllib.parse import urlparse + + +# import requests +# from odoo import api, fields, models + + +# class G2PCryptoKeySet(models.Model): +# _name = "g2p.crypto.key.set" +# _description = "G2P Crypto Key Set" + +# _order = "id desc" + + +# name = fields.Char(string="kid", required=True) + +# type = fields.Selection( +# [ +# ("rsa", "RSA"), +# ], +# default="rsa", +# ) + +# size = fields.Selection( +# [ +# ("2048", "2048"), +# ("3072", "3072"), +# ("4096", "4096"), +# ], +# default="2048", +# ) + +# priv_key = fields.Char(compute="_compute_priv_key", store=True) +# pub_cert = fields.Char(compute="_compute_pub_cert", store=True) + +# jwk = fields.Char(compute="_compute_jwk", store=True) + +# use = fields.Selection( +# [ +# ("sig", "Signature"), +# ("enc", "Encryption"), +# ], +# default="sig", +# ) +# status = fields.Selection( +# [ +# ("active", "Active"), +# ], +# default="active", +# ) + +# file_payment_manager_id = fields.Many2one( +# "g2p.program.payment.manager.file", ondelete="cascade" +# ) + +# _sql_constraints = [ +# ( +# "name_unique", +# "unique (name)", +# "Name/KID of the key set should be unique", +# ), +# ] +# @api.model +# def create(self, values): +# if not values.get("name", None): +# values["name"] = str(uuid.uuid4()) +# return super(G2PCryptoKeySet, self).create(values) + +# @api.depends("type", "size") +# def _compute_priv_key(self): +# for rec in self: +# if rec.type == "rsa": +# priv_key_data = self.get_encryption_public_key() +# rec.priv_key = priv_key_data.get("private_key") + +# @api.depends("priv_key") +# def _compute_pub_cert(self): +# for rec in self: +# if rec.type == "rsa": +# pub_key_data = self.get_signing_public_key() +# rec.pub_cert = pub_key_data.get("public_key") + +# def get_signing_public_key(self): +# url = f"{self.base_url}/tpmsigning/publickey" +# headers = {"Authorization": f"Bearer {self.api_key}"} + +# response = requests.post(url, headers=headers) +# return response.json() + +# def get_encryption_public_key(self): +# url = f"{self.base_url}/tpmencryption/publickey" +# headers = {"Authorization": f"Bearer {self.api_key}"} + +# response = requests.post(url, headers=headers) +# return response.json() diff --git a/g2p_registry_encryption/models/payment_file_qrcode_config.py b/g2p_registry_encryption/models/payment_file_qrcode_config.py new file mode 100644 index 0000000..4d5bfc5 --- /dev/null +++ b/g2p_registry_encryption/models/payment_file_qrcode_config.py @@ -0,0 +1,179 @@ +# import base64 +# import json +# from io import BytesIO + +# import qrcode +# import qrcode.image.svg +# from barcode import Code128 # pylint: disable=[W7936] +# from jose import jwt # pylint: disable=[W7936] + +# from odoo import _, api, fields, models +# from odoo.exceptions import ValidationError + + +# class G2PPaymentFileQRCodeConfig(models.Model): +# _name = "g2p.payment.file.qrcode.config" +# _description = "Payment File Config" +# _order = "id asc" + +# name = fields.Char(required=True) + +# type = fields.Selection( +# [ +# ("qrcode", "QR code"), +# ("code-128-barcode", "Code 128 Barcode"), +# ] +# ) +# data_type = fields.Selection( +# [ +# ("string", "String"), +# ("json", "JSON"), +# ("jwt", "JWT"), +# # Not implemented +# # ("cwt", "CWT"), +# ] +# ) + +# qrcode_version = fields.Integer(default=None) +# qrcode_error_correct = fields.Selection( +# [ +# ("0", "ERROR_CORRECT_M"), +# ("1", "ERROR_CORRECT_L"), +# ("2", "ERROR_CORRECT_H"), +# ("3", "ERROR_CORRECT_Q"), +# ], +# default="0", +# ) +# qrcode_box_size = fields.Integer(default=10) +# qrcode_border = fields.Integer(default=4) + +# body_string = fields.Char(string="Body") + +# payment_config_id = fields.Many2one("g2p.payment.file.config", ondelete="cascade") + +# @api.constrains("type", "data_type") +# def _constrains_type_and_data_type(self): +# if self.type.endswith("barcode") and self.data_type not in ("string",): +# raise ValidationError( +# _( +# f"Barcode must be of data type String. Cannot be of type {self.data_type}" +# ) +# ) + +# def render_datas_and_store( +# self, +# res_model, +# res_ids, +# crypto_ket_set_id, +# res_id_field_in_qrcode_model=None, +# template_engine="inline_template", +# ): +# datas = self._render_data( +# self.data_type, +# self.body_string, +# res_model, +# res_ids, +# crypto_ket_set_id, +# template_engine=template_engine, +# ) +# create_vals = [] +# for res_id in datas: +# val = { +# "qrcode_config_id": self.id, +# "data": datas[res_id], +# } +# if res_id_field_in_qrcode_model: +# val[res_id_field_in_qrcode_model] = res_id +# create_vals.append(val) +# QrcodeFile = self.env["g2p.payment.file.qrcode"] +# return QrcodeFile.create(create_vals) + + # @api.model + # def _render_data( + # self, + # data_type, + # template_src, + # res_model, + # res_ids, + # key_set, + # template_engine="inline_template", + # ): + # RenderMixin = self.env["mail.render.mixin"] + # datas = RenderMixin._render_template( + # template_src, + # res_model, + # res_ids, + # engine=template_engine, + # ) + # if data_type == "string": + # pass + # elif data_type == "json": + # for res_id in res_ids: + # # the following should throw exception if not json + # json.loads(datas[res_id]) + # elif data_type == "jwt": + # kid = key_set.name + # priv_key = key_set.priv_key.encode() + # for res_id in res_ids: + # payload = json.loads(datas[res_id]) + # datas[res_id] = jwt.encode( + # payload, priv_key, algorithm="RS256", headers={"kid": kid} + # ) + # return datas + + +# class G2PPaymentFileQRCode(models.TransientModel): +# _name = "g2p.payment.file.qrcode" +# _description = "Payment File QR Code" +# _order = "id desc" + +# qrcode_config_id = fields.Many2one("g2p.payment.file.qrcode.config") + +# data = fields.Char() + +# content_base64 = fields.Char(compute="_compute_qrcode_content", store=False) +# content_htmlsafe = fields.Char(compute="_compute_qrcode_content", store=False) + +# payment_batch_id = fields.Many2one("g2p.payment.batch") +# payment_id = fields.Many2one("g2p.payment") + +# def _compute_qrcode_content(self): +# for rec in self: +# config = rec.qrcode_config_id +# if config.type == "code-128-barcode": +# rec._generate_code128_barcode() +# elif config.type == "qrcode": +# rec._generate_qrcode() + +# def _generate_code128_barcode(self): +# self.ensure_one() +# byte_buffer = BytesIO() +# Code128(self.data).write(byte_buffer) +# byte_buffer.seek(0) +# self.content_base64 = base64.b64encode(byte_buffer.read()).decode() +# self.content_htmlsafe = "data:image/svg+xml;base64," + self.content_base64 +# byte_buffer.close() + +# def _generate_qrcode(self): +# self.ensure_one() +# config = self.qrcode_config_id +# img = qrcode.make( +# data=self.data, +# version=config.qrcode_version if config.qrcode_version else None, +# error_correction=int(config.qrcode_error_correct), +# box_size=config.qrcode_box_size, +# border=config.qrcode_border, +# image_factory=qrcode.image.svg.SvgPathImage, +# ) +# byte_buffer = BytesIO() +# img.save(byte_buffer) +# byte_buffer.seek(0) +# self.content_base64 = base64.b64encode(byte_buffer.read()).decode() +# self.content_htmlsafe = "data:image/svg+xml;base64," + self.content_base64 +# byte_buffer.close() + +# def get_by_name(self, name: str): +# for rec in self: +# if rec.qrcode_config_id and rec.qrcode_config_id.name == name: +# return rec +# return None diff --git a/g2p_registry_encryption/models/payment_key_set.py b/g2p_registry_encryption/models/payment_key_set.py new file mode 100644 index 0000000..315f9be --- /dev/null +++ b/g2p_registry_encryption/models/payment_key_set.py @@ -0,0 +1,147 @@ +# import base64 +# import json +# import uuid +# from datetime import datetime, timedelta +# from urllib.parse import urlparse + +# from cryptography import x509 +# from cryptography.hazmat.primitives import hashes, serialization +# from cryptography.hazmat.primitives.asymmetric import rsa +# from cryptography.x509.oid import NameOID +# from jose import constants, jwk # pylint: disable=[W7936] + +# from odoo import api, fields, models + + +# class G2PCryptoKeySet(models.Model): +# _name = "g2p.crypto.key.set" +# _description = "G2P Crypto Key Set" +# _order = "id desc" + +# name = fields.Char(string="kid", required=True) + +# type = fields.Selection( +# [ +# ("rsa", "RSA"), +# ], +# default="rsa", +# ) + +# size = fields.Selection( +# [ +# ("2048", "2048"), +# ("3072", "3072"), +# ("4096", "4096"), +# ], +# default="2048", +# ) + +# priv_key = fields.Char(compute="_compute_priv_key", store=True) +# pub_cert = fields.Char(compute="_compute_pub_cert", store=True) + +# jwk = fields.Char(compute="_compute_jwk", store=True) + +# use = fields.Selection( +# [ +# ("sig", "Signature"), +# ("enc", "Encryption"), +# ], +# default="sig", +# ) +# status = fields.Selection( +# [ +# ("active", "Active"), +# ], +# default="active", +# ) + +# file_payment_manager_id = fields.Many2one( +# "g2p.program.payment.manager.file", ondelete="cascade" +# ) + +# _sql_constraints = [ +# ( +# "name_unique", +# "unique (name)", +# "Name/KID of the key set should be unique", +# ), +# ] + +# @api.model +# def create(self, values): +# if not values.get("name", None): +# values["name"] = str(uuid.uuid4()) +# return super(G2PCryptoKeySet, self).create(values) + +# @api.depends("type", "size") +# def _compute_priv_key(self): +# for rec in self: +# if rec.type == "rsa": +# priv_key = rsa.generate_private_key(65537, int(rec.size)) +# rec.priv_key = priv_key.private_bytes( +# encoding=serialization.Encoding.PEM, +# format=serialization.PrivateFormat.PKCS8, +# # Hardcoding no encryption for now +# encryption_algorithm=serialization.NoEncryption(), +# ).decode() +# else: +# rec.priv_key = None + +# @api.depends("priv_key") +# def _compute_pub_cert(self): +# web_base_url = self.env["ir.config_parameter"].get_param("web.base.url") +# web_base_hostname = urlparse(web_base_url).netloc +# for rec in self: +# if rec.type == "rsa": +# priv_key = serialization.load_pem_private_key( +# data=rec.priv_key.encode(), +# password=None, +# ) +# pub_key = priv_key.public_key() +# sub_name = x509.Name( +# [x509.NameAttribute(NameOID.COMMON_NAME, web_base_hostname)] +# ) +# alt_names = [x509.DNSName(web_base_hostname)] +# san = x509.SubjectAlternativeName(alt_names) + +# utcnow = datetime.utcnow() +# # No signer as of now. +# # TODO: Add a common signer cert for openg2p, +# # which signs every newly created cert. +# # (Probably a oca/vault based implementation) +# cert = ( +# x509.CertificateBuilder() +# .subject_name(sub_name) +# .issuer_name(sub_name) +# .public_key(pub_key) +# .serial_number(1000) +# .not_valid_before(utcnow) +# .not_valid_after(utcnow + timedelta(days=10 * 365)) +# .add_extension(san, False) +# .sign(priv_key, hashes.SHA256()) +# ) +# rec.pub_cert = cert.public_bytes(encoding=serialization.Encoding.PEM) +# else: +# rec.pub_cert = None + +# @api.depends("pub_cert", "use") +# def _compute_jwk(self): +# for key_set in self: +# certificate = x509.load_pem_x509_certificate(key_set.pub_cert.encode()) +# cert_x5c = base64.b64encode( +# certificate.public_bytes(serialization.Encoding.DER) +# ).decode() +# pub_key = certificate.public_key() +# # TODO: For now hardcoding alogrithm +# pub_key_jwk = jwk.RSAKey( +# algorithm=constants.ALGORITHMS.RS256, +# key=pub_key.public_bytes( +# encoding=serialization.Encoding.PEM, +# format=serialization.PublicFormat.SubjectPublicKeyInfo, +# ).decode(), +# ).to_dict() +# pub_key_jwk["kid"] = key_set.name +# pub_key_jwk["use"] = key_set.use +# pub_key_jwk["x5c"] = [cert_x5c] +# key_set.jwk = json.dumps(pub_key_jwk) +# #a certificate contains public key but signed by private key From adcd7d9662667eedf69a2e7670fd243604cc68cb Mon Sep 17 00:00:00 2001 From: vineela-afk Date: Tue, 30 Jan 2024 11:16:30 +0530 Subject: [PATCH 02/13] added the read to change the cache --- g2p_encryption/models/keymanager_api.py | 30 +- g2p_registry_encryption/__manifest__.py | 8 +- g2p_registry_encryption/models/__init__.py | 2 +- g2p_registry_encryption/models/partner.py | 452 ++++++++++-------- .../models/registry_config.py | 31 ++ g2p_registry_encryption/security/security.xml | 7 + .../views/decrypt_file.xml | 14 + .../views/res_config_view.xml | 32 ++ 8 files changed, 359 insertions(+), 217 deletions(-) create mode 100644 g2p_registry_encryption/models/registry_config.py create mode 100644 g2p_registry_encryption/security/security.xml create mode 100644 g2p_registry_encryption/views/decrypt_file.xml create mode 100644 g2p_registry_encryption/views/res_config_view.xml diff --git a/g2p_encryption/models/keymanager_api.py b/g2p_encryption/models/keymanager_api.py index 5a9f450..328574f 100644 --- a/g2p_encryption/models/keymanager_api.py +++ b/g2p_encryption/models/keymanager_api.py @@ -76,7 +76,7 @@ def encrypt_data(self, data): }, } response = requests.post(url, json=payload, headers=headers) - print(response.content) + # print(response.content) return response.json().get("response", {}).get("data", None) @@ -137,7 +137,10 @@ def decrypt_data(self, data): }, } response = requests.post(url, json=payload, headers=headers) - return response.json().get("response", {}).get("data", None) + response = response.json().get("response", {}) + if response: + response = response.get("data", {}) + return response def get_signing_public_key(self): url = f"{self.base_url}/getSigningPublicKey" @@ -201,11 +204,6 @@ def jwt_verify(self, data): return response.json() def jwt_sign(self, data): - data_to_sign = data.get("dataToSign", None) - - if data_to_sign is None: - print("Data to sign is null. Skipping JWT signing.") - return None url = f"{self.base_url}/jwtSign" headers = {"Cookie": f"Authorization={self.access_token}"} payload = { @@ -218,9 +216,9 @@ def jwt_sign(self, data): "applicationId": data.get("applicationId", "string"), "referenceId": data.get("referenceId", "string"), "includePayload": True, - "includeCertificate": True, - "includeCertHash": True, - "certificateUrl": data.get("certificateUrl", "string"), + # "includeCertificate": True, + # "includeCertHash": True, + # "certificateUrl": data.get("certificateUrl", "string"), }, } response = requests.post(url, json=payload, headers=headers) @@ -229,7 +227,7 @@ def jwt_sign(self, data): response.json().get("response", {}).get("jwtSignedData", None) ) except ValueError: - print("Error parsing response JSON. JWT signing failed.") + # print("Error parsing response JSON. JWT signing failed.") jwt_signed_data = None return jwt_signed_data @@ -351,5 +349,11 @@ def generate_symmetric_key(self, data): # "dataToSign": "aGVsbG8gd29ybGQ=", # "certificateUrl": certificate_data, # } -# encrypted_data = odoo_api.jwt_sign(data_to_encrypt) -# print("Encrypted Data:", encrypted_data) +# data_to_encrypt = { +# "applicationId": "REGISTRATION", +# "referenceId": "", +# "data": "c-UgAvGn5o_iAOpSauP29SAlRRbmEEwhl3UkgK3u_0RR4u_ayqcB5aAuaDD5YDonsNxATVvt9UEqbyHtdTEnIb-U3KcdW7DtgvbT_n1yD4oeIvSK6hTx7bCjrlOrs-4JT8VN6J6heS19cuhtV88wj3Hmr0GBGIpfDSHkW4auOfVDiw8dlVUm6YiwhnGBvF4AJ2Nb7h_Hbm0XbO-JRNKHjIjPXqfJ0qjDSW4Si_d89u9iwNGMZy0xCXJbeBaHf6HTY3uQMwC-dqJgbR-W4kjXrsy8jbSa_PXaMOWoQCKf4AOUZZ6L9Bqv_l7HiaHKPdW_RU-e3r48MMtFLLDLnhy5N9CGpploF5JgKe8_Wnok42m-1lTb2HjwjCI2pJcm6WVvI0tFWV9TUExJVFRFUiOMwXdK6x8x6v2DhUcv434Bl-s88jQ1cFPFwQ", +# } +# decrypted_data = odoo_api.decrypt_data(data_to_encrypt) +# print("Decrypted Data:", decrypted_data) + diff --git a/g2p_registry_encryption/__manifest__.py b/g2p_registry_encryption/__manifest__.py index abe7f6d..2c892e6 100644 --- a/g2p_registry_encryption/__manifest__.py +++ b/g2p_registry_encryption/__manifest__.py @@ -7,8 +7,12 @@ "website": "https://openg2p.org", "license": "Other OSI approved licence", "development_status": "Alpha", - "depends": ["g2p_encryption", "g2p_registry_base"], - "data": [], + "depends": ["g2p_encryption", "g2p_registry_base", "g2p_registry_individual"], + "data": [ + "views/decrypt_file.xml", + "views/res_config_view.xml", + "security/security.xml", + ], "assets": { "web.assets_backend": [], "web.assets_qweb": [], diff --git a/g2p_registry_encryption/models/__init__.py b/g2p_registry_encryption/models/__init__.py index b4a972b..fddb317 100644 --- a/g2p_registry_encryption/models/__init__.py +++ b/g2p_registry_encryption/models/__init__.py @@ -1 +1 @@ -from . import partner, phone_number, reg_ids +from . import partner, phone_number, reg_ids, registry_config diff --git a/g2p_registry_encryption/models/partner.py b/g2p_registry_encryption/models/partner.py index 28cb064..d0e22e9 100644 --- a/g2p_registry_encryption/models/partner.py +++ b/g2p_registry_encryption/models/partner.py @@ -1,130 +1,3 @@ -# import logging - -# from odoo import api, fields, models - -# from odoo.addons.g2p_encryption.models.crypto import AESCipher - -# _logger = logging.getLogger(__name__) - - -# class EncryptedPartner(models.Model): -# _inherit = "res.partner" - -# # is_encrypted = fields.Boolean("Is encrypted?") - -# name_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field("name", "name_decrypted"), store=False -# ) -# family_name_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field( -# "family_name", "family_name_decrypted" -# ), -# store=False, -# ) -# given_name_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field("given_name", "given_name_decrypted"), -# store=False, -# ) -# addl_name_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field("addl_name", "addl_name_decrypted"), -# store=False, -# ) -# email_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field("email", "email_decrypted"), -# store=False, -# ) -# phone_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field("phone", "phone_decrypted"), -# store=False, -# ) -# mobile_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field("mobile", "mobile_decrypted"), -# store=False, -# ) -# address_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field("address", "address_decrypted"), -# store=False, -# ) -# birth_place_decrypted = fields.Char( -# compute=lambda self: self._decrypt_field( -# "birth_place", "birth_place_decrypted" -# ), -# store=False, -# ) - -# @api.model -# def create(self, vals): -# record = super(EncryptedPartner, self).create(vals) -# # TODO encryption key should be moved to a secret vault. -# encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") -# if encryption_key: -# crypto = AESCipher(encryption_key) -# record["name"] = crypto.encrypt(record["name"]) if record["name"] else None -# record["family_name"] = ( -# crypto.encrypt(record["family_name"]) if record["family_name"] else None -# ) -# record["given_name"] = ( -# crypto.encrypt(record["given_name"]) if record["given_name"] else None -# ) -# record["addl_name"] = ( -# crypto.encrypt(record["addl_name"]) if record["addl_name"] else None -# ) -# record["display_name"] = ( -# crypto.encrypt(record["display_name"]) -# if record["display_name"] -# else None -# ) -# record["email"] = ( -# crypto.encrypt(record["email"]) if record["email"] else None -# ) -# record["phone"] = ( -# crypto.encrypt(record["phone"]) if record["phone"] else None -# ) -# record["mobile"] = ( -# crypto.encrypt(record["mobile"]) if record["mobile"] else None -# ) -# record["address"] = ( -# crypto.encrypt(record["address"]) if record["address"] else None -# ) -# record["birth_place"] = ( -# crypto.encrypt(record["birth_place"]) if record["birth_place"] else None -# ) - -# return record - -# # @api.model -# # def write(self, vals): -# # record = super(EncryptedPartner, self).create(vals) -# # #TODO encryption key should be moved to a secret vault. -# # encryption_key = self.env['ir.config_parameter'].get_param('g2p_enc_key', '') -# # if encryption_key: -# # crypto = AESCipher(encryption_key) -# # record["name"] = crypto.encrypt(record["name"]) if record["name"] else None -# # record["family_name"] = crypto.encrypt(record["family_name"]) if record["family_name"] else None -# # record["given_name"] = crypto.encrypt(record["given_name"]) if record["given_name"] else None -# # record["addl_name"] = crypto.encrypt(record["addl_name"]) if record["addl_name"] else None -# # record["display_name"] = crypto.encrypt(record["display_name"]) if record["display_name"] else None -# # record["email"] = crypto.encrypt(record["email"]) if record["email"] else None -# # record["phone"] = crypto.encrypt(record["phone"]) if record["phone"] else None -# # record["mobile"] = crypto.encrypt(record["mobile"]) if record["mobile"] else None -# # record["address"] = crypto.encrypt(record["address"]) if record["address"] else None -# # record["birth_place"] = crypto.encrypt(record["birth_place"]) if record["birth_place"] else None - -# # return record - -# def _decrypt_field(self, actual_field, decrypted_field): -# # TODO encryption key should be moved to a secret vault. -# encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") -# if encryption_key: -# crypto = AESCipher(encryption_key) -# for rec in self: -# if rec[actual_field]: -# rec[decrypted_field] = crypto.decrypt(rec[actual_field]) -# else: -# rec[decrypted_field] = "" -# _logger.info("%s , %s", decrypted_field, rec[decrypted_field]) - - import base64 from odoo import fields @@ -135,51 +8,10 @@ class EncryptedPartner(models.Model): _inherit = "res.partner" - # is_encrypted = fields.Boolean("Is encrypted?") - - name_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("name", "name_decrypted"), store=False - ) - family_name_decrypted = fields.Char( - compute=lambda self: self._decrypt_field( - "family_name", "family_name_decrypted" - ), - store=False, - ) - given_name_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("given_name", "given_name_decrypted"), - store=False, - ) - addl_name_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("addl_name", "addl_name_decrypted"), - store=False, - ) - email_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("email", "email_decrypted"), - store=False, - ) - phone_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("phone", "phone_decrypted"), - store=False, - ) - mobile_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("mobile", "mobile_decrypted"), - store=False, - ) - address_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("address", "address_decrypted"), - store=False, - ) - birth_place_decrypted = fields.Char( - compute=lambda self: self._decrypt_field( - "birth_place", "birth_place_decrypted" - ), - store=False, - ) + is_encrypted = fields.Boolean("Is encrypted?") @api.model def create(self, vals): - record = super(EncryptedPartner, self).create(vals) odoo_token = { "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", "auth_client_id": "openg2p-admin-client", @@ -193,12 +25,8 @@ def create(self, vals): application_id = "REGISTRATION" reference_id = "string" - # access_token = odoo_auth.get_access_token() - # print(f"Access Token: {access_token}") - def encrypt_field(field_value): encoded_field_value = base64.b64encode(field_value.encode()).decode() - # print(f"Original Field Value: {field_value}") encrypted_data = encryption_module_instance.encrypt_data( { "applicationId": application_id, @@ -208,35 +36,120 @@ def encrypt_field(field_value): ) return encrypted_data - record["name"] = encrypt_field(record["name"]) if record["name"] else None - record["family_name"] = ( - encrypt_field(record["family_name"]) if record["family_name"] else None + vals["name"] = encrypt_field(vals.get("name")) if vals.get("name") else None + vals["family_name"] = ( + encrypt_field(vals.get("family_name")) if vals.get("family_name") else None ) - record["given_name"] = ( - encrypt_field(record["given_name"]) if record["given_name"] else None + vals["given_name"] = ( + encrypt_field(vals.get("given_name")) if vals.get("given_name") else None ) - record["addl_name"] = ( - encrypt_field(record["addl_name"]) if record["addl_name"] else None + vals["addl_name"] = ( + encrypt_field(vals.get("addl_name")) if vals.get("addl_name") else None ) - record["display_name"] = ( - encrypt_field(record["display_name"]) if record["display_name"] else None + vals["display_name"] = ( + encrypt_field(vals.get("display_name")) + if vals.get("display_name") + else None ) - record["email"] = encrypt_field(record["email"]) if record["email"] else None - record["phone"] = encrypt_field(record["phone"]) if record["phone"] else None - record["mobile"] = encrypt_field(record["mobile"]) if record["mobile"] else None - record["address"] = ( - encrypt_field(record["address"]) if record["address"] else None + vals["email"] = encrypt_field(vals.get("email")) if vals.get("email") else None + vals["phone"] = encrypt_field(vals.get("phone")) if vals.get("phone") else None + vals["mobile"] = ( + encrypt_field(vals.get("mobile")) if vals.get("mobile") else None ) - record["birth_place"] = ( - encrypt_field(record["birth_place"]) if record["birth_place"] else None + vals["address"] = ( + encrypt_field(vals.get("address")) if vals.get("address") else None ) + vals["birth_place"] = ( + encrypt_field(vals.get("birth_place")) if vals.get("birth_place") else None + ) + vals["is_encrypted"] = bool(vals.get("name")) - print("create methoddd", record) + record = super(EncryptedPartner, self).create(vals) return record - def _decrypt_field(self, actual_field, decrypted_field): + def write(self, vals): + odoo_token = { + "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", + "auth_client_id": "openg2p-admin-client", + "auth_client_secret": "x75SU2hqKQX7IPob", + "auth_grant_type": "client_credentials", + } + + odoo_auth = OdooAuth(**odoo_token) + base_url = "https://dev.openg2p.net/v1/keymanager" + encryption_module_instance = EncryptionModule(base_url, odoo_auth) + application_id = "REGISTRATION" + reference_id = "string" + + def encrypt_field(field_value): + encoded_field_value = base64.b64encode(field_value.encode()).decode() + encrypted_data = encryption_module_instance.encrypt_data( + { + "applicationId": application_id, + "referenceId": reference_id, + "data": encoded_field_value, + } + ) + return encrypted_data + + for record in self: + if "name" in vals: + vals["name"] = ( + encrypt_field(vals.get("name")) if vals.get("name") else None + ) + if "family_name" in vals: + vals["family_name"] = ( + encrypt_field(vals.get("family_name")) + if vals.get("family_name") + else None + ) + if "given_name" in vals: + vals["given_name"] = ( + encrypt_field(vals.get("given_name")) + if vals.get("given_name") + else None + ) + if "addl_name" in vals: + vals["addl_name"] = ( + encrypt_field(vals.get("addl_name")) + if vals.get("addl_name") + else None + ) + if "display_name" in vals: + vals["display_name"] = ( + encrypt_field(vals.get("display_name")) + if vals.get("display_name") + else None + ) + if "email" in vals: + vals["email"] = ( + encrypt_field(vals.get("email")) if vals.get("email") else None + ) + if "phone" in vals: + vals["phone"] = ( + encrypt_field(vals.get("phone")) if vals.get("phone") else None + ) + if "mobile" in vals: + vals["mobile"] = ( + encrypt_field(vals.get("mobile")) if vals.get("mobile") else None + ) + if "address" in vals: + vals["address"] = ( + encrypt_field(vals.get("address")) if vals.get("address") else None + ) + if "birth_place" in vals: + vals["birth_place"] = ( + encrypt_field(vals.get("birth_place")) + if vals.get("birth_place") + else None + ) + + result = super(EncryptedPartner, self).write(vals) + return result + + def _read(self, fields): odoo_token = { - "auth_url": "https://keycloak.dev.openg2p.net/realms/mosip/protocol/openid-connect/token", + "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", "auth_client_id": "openg2p-admin-client", "auth_client_secret": "x75SU2hqKQX7IPob", "auth_grant_type": "client_credentials", @@ -245,21 +158,158 @@ def _decrypt_field(self, actual_field, decrypted_field): odoo_auth = OdooAuth(**odoo_token) base_url = "https://dev.openg2p.net/v1/keymanager" encryption_module_instance = EncryptionModule(base_url, odoo_auth) - application_id = "KERNEL" - reference_id = "SIGN" + application_id = "REGISTRATION" + reference_id = "" def decrypt_field(field_value): - return encryption_module_instance.decrypt_data( + decrypted_data = encryption_module_instance.decrypt_data( { "applicationId": application_id, "referenceId": reference_id, "data": field_value, } ) + while decrypted_data and len(decrypted_data) % 4 != 0: + decrypted_data += "=" + if field_value and not decrypted_data: + return field_value + decoded_value = base64.b64decode(decrypted_data).decode("utf-8") + + return decoded_value + + is_decrypt_fields_enabled = self.env["ir.config_parameter"].get_param( + "g2p_registry.decrypt_fields", default=False + ) + super(EncryptedPartner, self)._read(fields) + + for record in self: + if is_decrypt_fields_enabled and record["is_encrypted"]: + if "name" in record and record["name"]: + decrytt = decrypt_field(record["name"]) + self.env.cache.set(record, self._fields["name"], decrytt) + if "family_name" in record and record["family_name"]: + decrytt = decrypt_field(record["family_name"]) + self.env.cache.set(record, self._fields["family_name"], decrytt) + if "addl_name" in record and record["addl_name"]: + decrytt = decrypt_field(record["addl_name"]) + self.env.cache.set(record, self._fields["addl_name"], decrytt) + if "display_name" in record and record["display_name"]: + decrytt = decrypt_field(record["display_name"]) + self.env.cache.set(record, self._fields["display_name"], decrytt) + if "given_name" in record and record["given_name"]: + decrytt = decrypt_field(record["given_name"]) + self.env.cache.set(record, self._fields["given_name"], decrytt) + if "email" in record and record["email"]: + decrytt = decrypt_field(record["email"]) + self.env.cache.set(record, self._fields["email"], decrytt) + if "phone" in record and record["phone"]: + decrytt = decrypt_field(record["phone"]) + self.env.cache.set(record, self._fields["phone"], decrytt) + if "address" in record and record["address"]: + decrytt = decrypt_field(record["address"]) + self.env.cache.set(record, self._fields["address"], decrytt) + if "birth_place" in record and record["birth_place"]: + decrytt = decrypt_field(record["birth_place"]) + self.env.cache.set(record, self._fields["birth_place"], decrytt) + if "birth_place" in record and record["birth_place"]: + decrytt = decrypt_field(record["birth_place"]) + self.env.cache.set(record, self._fields["birth_place"], decrytt) + # if "is_encrypted" in record: + # record["is_encrypted"] = False + + + + +# def read(self, fields=None, load="_classic_read"): +# odoo_token = { +# "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", +# "auth_client_id": "openg2p-admin-client", +# "auth_client_secret": "x75SU2hqKQX7IPob", +# "auth_grant_type": "client_credentials", +# } + +# odoo_auth = OdooAuth(**odoo_token) +# base_url = "https://dev.openg2p.net/v1/keymanager" +# encryption_module_instance = EncryptionModule(base_url, odoo_auth) +# application_id = "REGISTRATION" +# reference_id = "" + +# def decrypt_field(field_value): +# decrypted_data = encryption_module_instance.decrypt_data( +# { +# "applicationId": application_id, +# "referenceId": reference_id, +# "data": field_value, +# } +# ) +# while len(decrypted_data) % 4 != 0: +# decrypted_data += "=" +# decoded_value = base64.b64decode(decrypted_data).decode("utf-8") +# return decoded_value + +# is_decrypt_fields_enabled = self.env["ir.config_parameter"].get_param( +# "g2p_registry.decrypt_fields", default=False +# ) +# records = super(EncryptedPartner, self).read(fields=fields, load=load) + +# for record in records: +# if is_decrypt_fields_enabled: +# if "name" in record: +# record["name"] = ( +# decrypt_field(record.get("name")) +# if record.get("name") +# else None +# ) +# if "family_name" in record: +# record["family_name"] = ( +# decrypt_field(record.get("family_name")) +# if record.get("family_name") +# else None +# ) +# if "given_name" in record: +# record["given_name"] = ( +# decrypt_field(record.get("given_name")) +# if record.get("given_name") +# else None +# ) +# if "addl_name" in record: +# record["addl_name"] = ( +# decrypt_field(record.get("addl_name")) +# if record.get("addl_name") +# else None +# ) +# if "display_name" in record: +# record["display_name"] = ( +# decrypt_field(record.get("display_name")) +# if record.get("display_name") +# else None +# ) +# if "email" in record: +# record["email"] = ( +# decrypt_field(record.get("email")) +# if record.get("email") +# else None +# ) +# # if "phone" in record: +# # record["phone"] = ( +# # decrypt_field(record.get("phone")) +# # if record.get("phone") +# # else None +# # ) - for rec in self: - if rec[actual_field]: - rec[decrypted_field] = decrypt_field(rec[actual_field]) - else: - rec[decrypted_field] = "" - # print(decrypted_field, ",", rec[decrypted_field]) +# if "address" in record: +# record["address"] = ( +# decrypt_field(record.get("address")) +# if record.get("address") +# else None +# ) +# if "birth_place" in record: +# record["birth_place"] = ( +# decrypt_field(record.get("birth_place")) +# if record.get("birth_place") +# else None +# ) +# if "is_encrypted" in record: +# record["is_encrypted"] = False +# # print("========going to registry or encyrtping", records) +# return records diff --git a/g2p_registry_encryption/models/registry_config.py b/g2p_registry_encryption/models/registry_config.py new file mode 100644 index 0000000..b855c8e --- /dev/null +++ b/g2p_registry_encryption/models/registry_config.py @@ -0,0 +1,31 @@ +from odoo import api, fields, models + + +class RegistryConfigDecrypt(models.TransientModel): + + _inherit = "res.config.settings" + + decrypt_fields = fields.Boolean("Decrypt Fields", default=False, store=True) + # partner_name = fields.Char( + # string="Partner Name", + # related="partner_id.name", + # store=False, + # readonly=True, + # ) + + def set_values(self): + res = super(RegistryConfigDecrypt, self).set_values() + params = self.env["ir.config_parameter"].sudo() + params.set_param("g2p_registry.decrypt_fields", self.decrypt_fields) + return res + + @api.model + def get_values(self): + res = super(RegistryConfigDecrypt, self).get_values() + params = self.env["ir.config_parameter"].sudo() + res.update( + decrypt_fields=params.get_param( + "g2p_registry.decrypt_fields", default=False + ), + ) + return res diff --git a/g2p_registry_encryption/security/security.xml b/g2p_registry_encryption/security/security.xml new file mode 100644 index 0000000..7536060 --- /dev/null +++ b/g2p_registry_encryption/security/security.xml @@ -0,0 +1,7 @@ + + + + Crypto Admin + + + diff --git a/g2p_registry_encryption/views/decrypt_file.xml b/g2p_registry_encryption/views/decrypt_file.xml new file mode 100644 index 0000000..7d8c999 --- /dev/null +++ b/g2p_registry_encryption/views/decrypt_file.xml @@ -0,0 +1,14 @@ + + + view_individual_registrant_encrypted + res.partner + + + + + + + + + + \ No newline at end of file diff --git a/g2p_registry_encryption/views/res_config_view.xml b/g2p_registry_encryption/views/res_config_view.xml new file mode 100644 index 0000000..8eb4828 --- /dev/null +++ b/g2p_registry_encryption/views/res_config_view.xml @@ -0,0 +1,32 @@ + + + + openg2p.res.config.settings.view.inherit.setup + res.config.settings + + + + +
+
+
+
+
+
+ +
+
+ Decryption of the fields is through this option so be careful +
+
+
+
+
+
+
+
From b007aa10fc956050c6698d595b8ceb73da2c782c Mon Sep 17 00:00:00 2001 From: vineela-afk Date: Thu, 8 Feb 2024 10:13:22 +0530 Subject: [PATCH 03/13] added the overall keymanager functionality --- g2p_encryption/models/keymanager_api.py | 12 +- g2p_registry_encryption/models/partner.py | 262 ++++-------------- .../models/payment_file_qrcode_config.py | 64 ++--- .../models/registry_config.py | 8 +- g2p_registry_encryption/security/security.xml | 2 +- .../views/decrypt_file.xml | 9 +- .../views/res_config_view.xml | 4 +- 7 files changed, 103 insertions(+), 258 deletions(-) diff --git a/g2p_encryption/models/keymanager_api.py b/g2p_encryption/models/keymanager_api.py index 328574f..a83353c 100644 --- a/g2p_encryption/models/keymanager_api.py +++ b/g2p_encryption/models/keymanager_api.py @@ -1,4 +1,3 @@ -import requests from datetime import datetime import requests @@ -141,6 +140,10 @@ def decrypt_data(self, data): if response: response = response.get("data", {}) return response + # response = requests.post(url, json=payload, headers=headers) + # print(response.content) + + # return response.json().get("response", {}).get("data", None) def get_signing_public_key(self): url = f"{self.base_url}/getSigningPublicKey" @@ -349,11 +352,6 @@ def generate_symmetric_key(self, data): # "dataToSign": "aGVsbG8gd29ybGQ=", # "certificateUrl": certificate_data, # } -# data_to_encrypt = { -# "applicationId": "REGISTRATION", -# "referenceId": "", -# "data": "c-UgAvGn5o_iAOpSauP29SAlRRbmEEwhl3UkgK3u_0RR4u_ayqcB5aAuaDD5YDonsNxATVvt9UEqbyHtdTEnIb-U3KcdW7DtgvbT_n1yD4oeIvSK6hTx7bCjrlOrs-4JT8VN6J6heS19cuhtV88wj3Hmr0GBGIpfDSHkW4auOfVDiw8dlVUm6YiwhnGBvF4AJ2Nb7h_Hbm0XbO-JRNKHjIjPXqfJ0qjDSW4Si_d89u9iwNGMZy0xCXJbeBaHf6HTY3uQMwC-dqJgbR-W4kjXrsy8jbSa_PXaMOWoQCKf4AOUZZ6L9Bqv_l7HiaHKPdW_RU-e3r48MMtFLLDLnhy5N9CGpploF5JgKe8_Wnok42m-1lTb2HjwjCI2pJcm6WVvI0tFWV9TUExJVFRFUiOMwXdK6x8x6v2DhUcv434Bl-s88jQ1cFPFwQ", -# } + # decrypted_data = odoo_api.decrypt_data(data_to_encrypt) # print("Decrypted Data:", decrypted_data) - diff --git a/g2p_registry_encryption/models/partner.py b/g2p_registry_encryption/models/partner.py index d0e22e9..76ea343 100644 --- a/g2p_registry_encryption/models/partner.py +++ b/g2p_registry_encryption/models/partner.py @@ -1,7 +1,8 @@ import base64 -from odoo import fields +import json + +from odoo import api, fields, models -from odoo import models, fields, api from odoo.addons.g2p_encryption.models.keymanager_api import EncryptionModule, OdooAuth @@ -9,6 +10,8 @@ class EncryptedPartner(models.Model): _inherit = "res.partner" is_encrypted = fields.Boolean("Is encrypted?") + encrypted_val = fields.Char("Encrypted value") + # encrypted_val = fields.Binary("Encrypted value") @api.model def create(self, vals): @@ -26,7 +29,8 @@ def create(self, vals): reference_id = "string" def encrypt_field(field_value): - encoded_field_value = base64.b64encode(field_value.encode()).decode() + json_data = json.dumps(field_value) + encoded_field_value = base64.b64encode((json_data).encode()).decode() encrypted_data = encryption_module_instance.encrypt_data( { "applicationId": application_id, @@ -36,34 +40,19 @@ def encrypt_field(field_value): ) return encrypted_data - vals["name"] = encrypt_field(vals.get("name")) if vals.get("name") else None - vals["family_name"] = ( - encrypt_field(vals.get("family_name")) if vals.get("family_name") else None - ) - vals["given_name"] = ( - encrypt_field(vals.get("given_name")) if vals.get("given_name") else None - ) - vals["addl_name"] = ( - encrypt_field(vals.get("addl_name")) if vals.get("addl_name") else None - ) - vals["display_name"] = ( - encrypt_field(vals.get("display_name")) - if vals.get("display_name") - else None - ) - vals["email"] = encrypt_field(vals.get("email")) if vals.get("email") else None - vals["phone"] = encrypt_field(vals.get("phone")) if vals.get("phone") else None - vals["mobile"] = ( - encrypt_field(vals.get("mobile")) if vals.get("mobile") else None - ) - vals["address"] = ( - encrypt_field(vals.get("address")) if vals.get("address") else None - ) - vals["birth_place"] = ( - encrypt_field(vals.get("birth_place")) if vals.get("birth_place") else None - ) vals["is_encrypted"] = bool(vals.get("name")) - + vals["encrypted_val"] = encrypt_field(vals) + + vals["name"] = "encrypted" + vals["family_name"] = "encrypted" + vals["given_name"] = "encrypted" + vals["addl_name"] = "encrypted" + vals["display_name"] = "encrypted" + vals["address"] = "encrypted" + vals["birth_place"] = "encrypted" + # for field, value in vals.items(): + # if isinstance(value, str): + # vals[field] = "encrypted" record = super(EncryptedPartner, self).create(vals) return record @@ -92,57 +81,22 @@ def encrypt_field(field_value): ) return encrypted_data - for record in self: - if "name" in vals: - vals["name"] = ( - encrypt_field(vals.get("name")) if vals.get("name") else None - ) - if "family_name" in vals: - vals["family_name"] = ( - encrypt_field(vals.get("family_name")) - if vals.get("family_name") - else None - ) - if "given_name" in vals: - vals["given_name"] = ( - encrypt_field(vals.get("given_name")) - if vals.get("given_name") - else None - ) - if "addl_name" in vals: - vals["addl_name"] = ( - encrypt_field(vals.get("addl_name")) - if vals.get("addl_name") - else None - ) - if "display_name" in vals: - vals["display_name"] = ( - encrypt_field(vals.get("display_name")) - if vals.get("display_name") - else None - ) - if "email" in vals: - vals["email"] = ( - encrypt_field(vals.get("email")) if vals.get("email") else None - ) - if "phone" in vals: - vals["phone"] = ( - encrypt_field(vals.get("phone")) if vals.get("phone") else None - ) - if "mobile" in vals: - vals["mobile"] = ( - encrypt_field(vals.get("mobile")) if vals.get("mobile") else None - ) - if "address" in vals: - vals["address"] = ( - encrypt_field(vals.get("address")) if vals.get("address") else None - ) - if "birth_place" in vals: - vals["birth_place"] = ( - encrypt_field(vals.get("birth_place")) - if vals.get("birth_place") - else None - ) + vals["is_encrypted"] = bool(vals.get("name")) + vals["encrypted_val"] = encrypt_field(vals) + if "name" in vals: + vals["name"] = "encrypted" + if "family_name" in vals: + vals["family_name"] = "encrypted" + if "given_name" in vals: + vals["given_name"] = "encrypted" + if "addl_name" in vals: + vals["addl_name"] = "encrypted" + if "display_name" in vals: + vals["display_name"] = "encrypted" + if "address" in vals: + vals["address"] = "encrypted" + if "birth_place" in vals: + vals["birth_place"] = "encrypted" result = super(EncryptedPartner, self).write(vals) return result @@ -181,135 +135,31 @@ def decrypt_field(field_value): "g2p_registry.decrypt_fields", default=False ) super(EncryptedPartner, self)._read(fields) - for record in self: if is_decrypt_fields_enabled and record["is_encrypted"]: + d = decrypt_field(record["encrypted_val"]) + decrytt = json.loads(d) + # print(decrytt["name"]) + if "name" in record and record["name"]: - decrytt = decrypt_field(record["name"]) - self.env.cache.set(record, self._fields["name"], decrytt) + self.env.cache.set(record, self._fields["name"], decrytt["name"]) if "family_name" in record and record["family_name"]: - decrytt = decrypt_field(record["family_name"]) - self.env.cache.set(record, self._fields["family_name"], decrytt) + self.env.cache.set( + record, self._fields["family_name"], decrytt["family_name"] + ) if "addl_name" in record and record["addl_name"]: - decrytt = decrypt_field(record["addl_name"]) - self.env.cache.set(record, self._fields["addl_name"], decrytt) - if "display_name" in record and record["display_name"]: - decrytt = decrypt_field(record["display_name"]) - self.env.cache.set(record, self._fields["display_name"], decrytt) + self.env.cache.set( + record, self._fields["addl_name"], decrytt["addl_name"] + ) if "given_name" in record and record["given_name"]: - decrytt = decrypt_field(record["given_name"]) - self.env.cache.set(record, self._fields["given_name"], decrytt) + self.env.cache.set( + record, self._fields["given_name"], decrytt["given_name"] + ) + if "display_name" in record and record["name"]: + self.env.cache.set( + record, + self._fields["display_name"], + decrytt["name"], + ) if "email" in record and record["email"]: - decrytt = decrypt_field(record["email"]) - self.env.cache.set(record, self._fields["email"], decrytt) - if "phone" in record and record["phone"]: - decrytt = decrypt_field(record["phone"]) - self.env.cache.set(record, self._fields["phone"], decrytt) - if "address" in record and record["address"]: - decrytt = decrypt_field(record["address"]) - self.env.cache.set(record, self._fields["address"], decrytt) - if "birth_place" in record and record["birth_place"]: - decrytt = decrypt_field(record["birth_place"]) - self.env.cache.set(record, self._fields["birth_place"], decrytt) - if "birth_place" in record and record["birth_place"]: - decrytt = decrypt_field(record["birth_place"]) - self.env.cache.set(record, self._fields["birth_place"], decrytt) - # if "is_encrypted" in record: - # record["is_encrypted"] = False - - - - -# def read(self, fields=None, load="_classic_read"): -# odoo_token = { -# "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", -# "auth_client_id": "openg2p-admin-client", -# "auth_client_secret": "x75SU2hqKQX7IPob", -# "auth_grant_type": "client_credentials", -# } - -# odoo_auth = OdooAuth(**odoo_token) -# base_url = "https://dev.openg2p.net/v1/keymanager" -# encryption_module_instance = EncryptionModule(base_url, odoo_auth) -# application_id = "REGISTRATION" -# reference_id = "" - -# def decrypt_field(field_value): -# decrypted_data = encryption_module_instance.decrypt_data( -# { -# "applicationId": application_id, -# "referenceId": reference_id, -# "data": field_value, -# } -# ) -# while len(decrypted_data) % 4 != 0: -# decrypted_data += "=" -# decoded_value = base64.b64decode(decrypted_data).decode("utf-8") -# return decoded_value - -# is_decrypt_fields_enabled = self.env["ir.config_parameter"].get_param( -# "g2p_registry.decrypt_fields", default=False -# ) -# records = super(EncryptedPartner, self).read(fields=fields, load=load) - -# for record in records: -# if is_decrypt_fields_enabled: -# if "name" in record: -# record["name"] = ( -# decrypt_field(record.get("name")) -# if record.get("name") -# else None -# ) -# if "family_name" in record: -# record["family_name"] = ( -# decrypt_field(record.get("family_name")) -# if record.get("family_name") -# else None -# ) -# if "given_name" in record: -# record["given_name"] = ( -# decrypt_field(record.get("given_name")) -# if record.get("given_name") -# else None -# ) -# if "addl_name" in record: -# record["addl_name"] = ( -# decrypt_field(record.get("addl_name")) -# if record.get("addl_name") -# else None -# ) -# if "display_name" in record: -# record["display_name"] = ( -# decrypt_field(record.get("display_name")) -# if record.get("display_name") -# else None -# ) -# if "email" in record: -# record["email"] = ( -# decrypt_field(record.get("email")) -# if record.get("email") -# else None -# ) -# # if "phone" in record: -# # record["phone"] = ( -# # decrypt_field(record.get("phone")) -# # if record.get("phone") -# # else None -# # ) - -# if "address" in record: -# record["address"] = ( -# decrypt_field(record.get("address")) -# if record.get("address") -# else None -# ) -# if "birth_place" in record: -# record["birth_place"] = ( -# decrypt_field(record.get("birth_place")) -# if record.get("birth_place") -# else None -# ) -# if "is_encrypted" in record: -# record["is_encrypted"] = False -# # print("========going to registry or encyrtping", records) -# return records + self.env.cache.set(record, self._fields["email"], decrytt["email"]) diff --git a/g2p_registry_encryption/models/payment_file_qrcode_config.py b/g2p_registry_encryption/models/payment_file_qrcode_config.py index 4d5bfc5..7dbcf68 100644 --- a/g2p_registry_encryption/models/payment_file_qrcode_config.py +++ b/g2p_registry_encryption/models/payment_file_qrcode_config.py @@ -88,38 +88,38 @@ # QrcodeFile = self.env["g2p.payment.file.qrcode"] # return QrcodeFile.create(create_vals) - # @api.model - # def _render_data( - # self, - # data_type, - # template_src, - # res_model, - # res_ids, - # key_set, - # template_engine="inline_template", - # ): - # RenderMixin = self.env["mail.render.mixin"] - # datas = RenderMixin._render_template( - # template_src, - # res_model, - # res_ids, - # engine=template_engine, - # ) - # if data_type == "string": - # pass - # elif data_type == "json": - # for res_id in res_ids: - # # the following should throw exception if not json - # json.loads(datas[res_id]) - # elif data_type == "jwt": - # kid = key_set.name - # priv_key = key_set.priv_key.encode() - # for res_id in res_ids: - # payload = json.loads(datas[res_id]) - # datas[res_id] = jwt.encode( - # payload, priv_key, algorithm="RS256", headers={"kid": kid} - # ) - # return datas +# @api.model +# def _render_data( +# self, +# data_type, +# template_src, +# res_model, +# res_ids, +# key_set, +# template_engine="inline_template", +# ): +# RenderMixin = self.env["mail.render.mixin"] +# datas = RenderMixin._render_template( +# template_src, +# res_model, +# res_ids, +# engine=template_engine, +# ) +# if data_type == "string": +# pass +# elif data_type == "json": +# for res_id in res_ids: +# # the following should throw exception if not json +# json.loads(datas[res_id]) +# elif data_type == "jwt": +# kid = key_set.name +# priv_key = key_set.priv_key.encode() +# for res_id in res_ids: +# payload = json.loads(datas[res_id]) +# datas[res_id] = jwt.encode( +# payload, priv_key, algorithm="RS256", headers={"kid": kid} +# ) +# return datas # class G2PPaymentFileQRCode(models.TransientModel): diff --git a/g2p_registry_encryption/models/registry_config.py b/g2p_registry_encryption/models/registry_config.py index b855c8e..8bdefb6 100644 --- a/g2p_registry_encryption/models/registry_config.py +++ b/g2p_registry_encryption/models/registry_config.py @@ -5,13 +5,7 @@ class RegistryConfigDecrypt(models.TransientModel): _inherit = "res.config.settings" - decrypt_fields = fields.Boolean("Decrypt Fields", default=False, store=True) - # partner_name = fields.Char( - # string="Partner Name", - # related="partner_id.name", - # store=False, - # readonly=True, - # ) + decrypt_fields = fields.Boolean(default=False, store=True) def set_values(self): res = super(RegistryConfigDecrypt, self).set_values() diff --git a/g2p_registry_encryption/security/security.xml b/g2p_registry_encryption/security/security.xml index 7536060..6a53fb3 100644 --- a/g2p_registry_encryption/security/security.xml +++ b/g2p_registry_encryption/security/security.xml @@ -1,5 +1,5 @@ - + Crypto Admin diff --git a/g2p_registry_encryption/views/decrypt_file.xml b/g2p_registry_encryption/views/decrypt_file.xml index 7d8c999..d9e70d2 100644 --- a/g2p_registry_encryption/views/decrypt_file.xml +++ b/g2p_registry_encryption/views/decrypt_file.xml @@ -2,13 +2,14 @@ view_individual_registrant_encrypted res.partner - - + + - + + - \ No newline at end of file + diff --git a/g2p_registry_encryption/views/res_config_view.xml b/g2p_registry_encryption/views/res_config_view.xml index 8eb4828..5f4170e 100644 --- a/g2p_registry_encryption/views/res_config_view.xml +++ b/g2p_registry_encryption/views/res_config_view.xml @@ -21,7 +21,9 @@
- Decryption of the fields is through this option so be careful + Decryption of the fields is through this option so be careful From 4faac21d62c1b976d0fda43b1fe983e7e4b203ad Mon Sep 17 00:00:00 2001 From: vineela-afk Date: Wed, 14 Feb 2024 11:54:03 +0530 Subject: [PATCH 04/13] added final changes --- g2p_encryption/models/crypto.py | 34 ------------------------- g2p_encryption/models/keymanager_api.py | 34 ------------------------- 2 files changed, 68 deletions(-) delete mode 100644 g2p_encryption/models/crypto.py diff --git a/g2p_encryption/models/crypto.py b/g2p_encryption/models/crypto.py deleted file mode 100644 index a9b6bef..0000000 --- a/g2p_encryption/models/crypto.py +++ /dev/null @@ -1,34 +0,0 @@ -import base64 -import hashlib -import logging - -from Crypto import Random -from Crypto.Cipher import AES - -_logger = logging.getLogger(__name__) - - -class AESCipher(object): - def __init__(self, key): - self.bs = AES.block_size - self.key = hashlib.sha256(key.encode()).digest() - - def encrypt(self, raw): - raw = self._pad(raw) - iv = Random.new().read(AES.block_size) - cipher = AES.new(self.key, AES.MODE_CBC, iv) - return base64.b64encode(iv + cipher.encrypt(raw.encode())) - - def decrypt(self, enc): - _logger.info("ENC String:", enc) - enc = base64.b64decode(enc) - iv = enc[: AES.block_size] - cipher = AES.new(self.key, AES.MODE_CBC, iv) - return self._unpad(cipher.decrypt(enc[AES.block_size :])).decode("utf-8") - - def _pad(self, s): - return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs) - - @staticmethod - def _unpad(s): - return s[: -ord(s[len(s) - 1 :])] diff --git a/g2p_encryption/models/keymanager_api.py b/g2p_encryption/models/keymanager_api.py index a83353c..3dbaaae 100644 --- a/g2p_encryption/models/keymanager_api.py +++ b/g2p_encryption/models/keymanager_api.py @@ -321,37 +321,3 @@ def generate_symmetric_key(self, data): response = requests.post(url, json=payload, headers=headers) return response.json() - - -# odoo_token = { -# "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", -# "auth_client_id": "openg2p-admin-client", -# "auth_client_secret": "x75SU2hqKQX7IPob", -# "auth_grant_type": "client_credentials", -# } - -# odoo_auth = OdooAuth(**odoo_token) -# access_token = odoo_auth.get_access_token() -# print(f"Access Token: {access_token}") - -# odoo_api = EncryptionModule( -# base_url="https://dev.openg2p.net/v1/keymanager", -# odoo_auth=odoo_auth, -# ) - -# certificate_data = odoo_api.get_certificate( -# { -# "applicationId": "KERNEL", -# "referenceId": "SIGN", -# } -# ) -# print("certificate Data:", certificate_data) -# data_to_encrypt = { -# "applicationId": "KERNEL", -# "referenceId": "SIGN", -# "dataToSign": "aGVsbG8gd29ybGQ=", -# "certificateUrl": certificate_data, -# } - -# decrypted_data = odoo_api.decrypt_data(data_to_encrypt) -# print("Decrypted Data:", decrypted_data) From 9fad0d95a2ca4bdb330f8d3e5ab606dd46212e19 Mon Sep 17 00:00:00 2001 From: Lalith Kota Date: Fri, 23 Feb 2024 18:05:31 +0530 Subject: [PATCH 05/13] Initial Commit for reorganization of security --- README.md | 10 +- g2p_encryption/README.rst | 57 --- g2p_encryption/__manifest__.py | 9 +- g2p_encryption/data/default_provider.xml | 9 + g2p_encryption/models/__init__.py | 2 +- g2p_encryption/models/encryption_provider.py | 28 ++ g2p_encryption/models/keymanager_api.py | 323 -------------- g2p_encryption/readme/DESCRIPTION.rst | 2 +- g2p_encryption/security/groups.xml | 7 + g2p_encryption/security/ir.model.access.csv | 2 + g2p_encryption/static/description/index.html | 415 ------------------ g2p_encryption/views/encryption_provider.xml | 45 ++ g2p_encryption_rest_api/__init__.py | 2 + g2p_encryption_rest_api/__manifest__.py | 21 + .../controllers/__init__.py | 1 + g2p_encryption_rest_api/controllers/main.py | 7 + .../readme/DESCRIPTION.rst | 1 + g2p_encryption_rest_api/services/__init__.py | 1 + .../services/well_known.py | 38 ++ .../static/description/icon.png | Bin 0 -> 3985 bytes requirements.txt | 2 - .../odoo/addons/g2p_encryption_keymanager | 1 + setup/g2p_encryption_keymanager/setup.py | 6 + .../odoo/addons/g2p_encryption_rest_api | 1 + setup/g2p_encryption_rest_api/setup.py | 6 + test-requirements.txt | 1 + 26 files changed, 191 insertions(+), 806 deletions(-) delete mode 100644 g2p_encryption/README.rst create mode 100644 g2p_encryption/data/default_provider.xml create mode 100644 g2p_encryption/models/encryption_provider.py delete mode 100644 g2p_encryption/models/keymanager_api.py create mode 100644 g2p_encryption/security/groups.xml create mode 100644 g2p_encryption/security/ir.model.access.csv delete mode 100644 g2p_encryption/static/description/index.html create mode 100644 g2p_encryption/views/encryption_provider.xml create mode 100644 g2p_encryption_rest_api/__init__.py create mode 100644 g2p_encryption_rest_api/__manifest__.py create mode 100644 g2p_encryption_rest_api/controllers/__init__.py create mode 100644 g2p_encryption_rest_api/controllers/main.py create mode 100644 g2p_encryption_rest_api/readme/DESCRIPTION.rst create mode 100644 g2p_encryption_rest_api/services/__init__.py create mode 100644 g2p_encryption_rest_api/services/well_known.py create mode 100644 g2p_encryption_rest_api/static/description/icon.png delete mode 100644 requirements.txt create mode 120000 setup/g2p_encryption_keymanager/odoo/addons/g2p_encryption_keymanager create mode 100644 setup/g2p_encryption_keymanager/setup.py create mode 120000 setup/g2p_encryption_rest_api/odoo/addons/g2p_encryption_rest_api create mode 100644 setup/g2p_encryption_rest_api/setup.py diff --git a/README.md b/README.md index f70e469..3a8f9e6 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# OpenG2P Security +# OpenG2P Security ### (_Alpha version_) ### -This repo contains modules for the encryption of the registry. Refer to [OpenG2P Docs](https://docs.openg2p.org/v/1.1). +This repo contains modules for the encryption of the registry. Refer to [OpenG2P Docs](https://docs.openg2p.org/). @@ -16,8 +16,10 @@ Available addons ---------------- addon | version | maintainers | summary --- | --- | --- | --- -[g2p_encryption](g2p_encryption/) | 15.0.1.2.0 | | G2P: Encryption -[g2p_registry_encryption](g2p_registry_encryption/) | 15.0.1.2.0 | | G2P:Registry Encryption +[g2p_encryption](g2p_encryption/) | 15.0.1.2.0 | | G2P Encryption: Base +[g2p_encryption_keymanager](g2p_encryption_keymanager/) | 15.0.1.2.0 | | G2P Encryption: Keymanager +[g2p_encryption_rest_api](g2p_encryption_rest_api/) | 15.0.1.2.0 | | G2P Encryption: Rest API +[g2p_registry_encryption](g2p_registry_encryption/) | 15.0.1.2.0 | | G2P Registry: Encryption [//]: # (end addons) diff --git a/g2p_encryption/README.rst b/g2p_encryption/README.rst deleted file mode 100644 index bfefbff..0000000 --- a/g2p_encryption/README.rst +++ /dev/null @@ -1,57 +0,0 @@ -=============== -G2P: Encryption -=============== - -.. - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! This file is generated by oca-gen-addon-readme !! - !! changes will be overwritten. !! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:04f5f0d02e2f5b06062b0403ad80dc8ba932f2489ce2e21cd6aeb2ca30e8d3da - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png - :target: https://odoo-community.org/page/development-status - :alt: Alpha -.. |badge2| image:: https://img.shields.io/badge/github-OpenG2P%2Fopeng2p--security-lightgray.png?logo=github - :target: https://github.com/OpenG2P/openg2p-security/tree/15.0-develop/g2p_encryption - :alt: OpenG2P/openg2p-security - -|badge1| |badge2| - -OpenG2P Encryption - -.. IMPORTANT:: - This is an alpha version, the data model and design can change at any time without warning. - Only for development or testing purpose, do not use in production. - `More details on development status `_ - -**Table of contents** - -.. contents:: - :local: - -Bug Tracker -=========== - -Bugs are tracked on `GitHub 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 `_. - -Do not contact contributors directly about support or help with technical issues. - -Credits -======= - -Authors -~~~~~~~ - -* OpenG2P - -Maintainers -~~~~~~~~~~~ - -This module is part of the `OpenG2P/openg2p-security `_ project on GitHub. - -You are welcome to contribute. diff --git a/g2p_encryption/__manifest__.py b/g2p_encryption/__manifest__.py index 87bd470..2f76096 100644 --- a/g2p_encryption/__manifest__.py +++ b/g2p_encryption/__manifest__.py @@ -1,5 +1,5 @@ { - "name": "G2P: Encryption", + "name": "G2P Encryption: Base", "category": "G2P", "version": "15.0.1.2.0", "sequence": 1, @@ -8,8 +8,11 @@ "license": "Other OSI approved licence", "development_status": "Alpha", "depends": [], - "external_dependencies": {"python": ["pycrypto"]}, - "data": [], + "data": [ + "security/groups.xml", + "security/ir.model.access.csv", + "views/encryption_provider.xml", + ], "assets": { "web.assets_backend": [], "web.assets_qweb": [], diff --git a/g2p_encryption/data/default_provider.xml b/g2p_encryption/data/default_provider.xml new file mode 100644 index 0000000..ac42138 --- /dev/null +++ b/g2p_encryption/data/default_provider.xml @@ -0,0 +1,9 @@ + + + + + Default Encryption Provider + + diff --git a/g2p_encryption/models/__init__.py b/g2p_encryption/models/__init__.py index a2795d2..56c044c 100644 --- a/g2p_encryption/models/__init__.py +++ b/g2p_encryption/models/__init__.py @@ -1 +1 @@ -from . import crypto +from . import encryption_provider diff --git a/g2p_encryption/models/encryption_provider.py b/g2p_encryption/models/encryption_provider.py new file mode 100644 index 0000000..7adb097 --- /dev/null +++ b/g2p_encryption/models/encryption_provider.py @@ -0,0 +1,28 @@ +from odoo import api, fields, models + + +class G2PEncryptionProvider(models.Model): + _name = "g2p.encryption.provider" + _description = "G2P Encryption Provider" + + name = fields.Char(required=True) + type = fields.Selection(selection="_selection_provider_type") + + @api.model + def _selection_provider_type(self): + return [] + + def encrypt_data(self, data, **kwargs): + raise NotImplementedError() + + def decrypt_data(self, data, **kwargs): + raise NotImplementedError() + + def sign_jwt(self, data, **kwargs): + raise NotImplementedError() + + def verifiy_jwt(self, data, **kwargs): + raise NotImplementedError() + + def get_jwks(self, **kwargs): + raise NotImplementedError() diff --git a/g2p_encryption/models/keymanager_api.py b/g2p_encryption/models/keymanager_api.py deleted file mode 100644 index 3dbaaae..0000000 --- a/g2p_encryption/models/keymanager_api.py +++ /dev/null @@ -1,323 +0,0 @@ -from datetime import datetime - -import requests - - -class OdooAuth(object): - def __init__(self, auth_url, auth_client_id, auth_client_secret, auth_grant_type): - self.auth_url = auth_url - self.auth_client_id = auth_client_id - self.auth_client_secret = auth_client_secret - self.auth_grant_type = auth_grant_type - - def get_access_token(self): - data = { - "client_id": self.auth_client_id, - "client_secret": self.auth_client_secret, - "grant_type": self.auth_grant_type, - } - response = requests.post(self.auth_url, data=data) - if response.status_code == 200: - access_token = response.json().get("access_token") - return access_token - else: - response.raise_for_status() - - -# odoo_token = { -# "auth_url": "https://keycloak.dev.openg2p.net/realms/mosip/protocol/openid-connect/token", -# "auth_client_id": "mosip-admin-client", -# "auth_client_secret": "F42OX9zwiaUfzwsk", -# "auth_grant_type": "client_credentials", -# } - -# odoo_auth = OdooAuth(**odoo_token) -# access_token = odoo_auth.get_access_token() -# print(f"Access Token: {access_token}") - - -class EncryptionModule(object): - def __init__(self, base_url, odoo_auth): - self.base_url = base_url - self.access_token = odoo_auth.get_access_token() - self.current_time = self.generate_current_time() - - def generate_current_time(self): - # Generate current timestamp in ISO 8601 format - return datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" - - def get_certificate(self, data): - url = f"{self.base_url}/getCertificate" - headers = {"Cookie": f"Authorization={self.access_token}"} - - params = { - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - } - response = requests.get(url, headers=headers, params=params) - return response.json().get("response", {}).get("certificate", None) - - def encrypt_data(self, data): - url = f"{self.base_url}/encrypt" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "timeStamp": self.current_time, - "data": data.get("data", "string"), - "salt": "string", - "aad": "string", - }, - } - response = requests.post(url, json=payload, headers=headers) - # print(response.content) - - return response.json().get("response", {}).get("data", None) - - def jwt_encrypt_data(self, data): - url = f"{self.base_url}/jwtencrypt" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "data": "string", - "enableDefCompression": True, - "includeCertificate": True, - "includeCertHash": True, - "jwkSetUrl": "string", - "x509Certificate": "string", - }, - } - response = requests.post(url, json=payload, headers=headers) - return response.json() - - def jwt_decrypt_data(self, data): - url = f"{self.base_url}/jwtdecrypt" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "encData": "string", - }, - } - response = requests.post(url, json=payload, headers=headers) - return response.json() - - def decrypt_data(self, data): - url = f"{self.base_url}/decrypt" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "timeStamp": self.current_time, - "data": data.get("data", "string"), - "salt": "string", - "aad": "string", - }, - } - response = requests.post(url, json=payload, headers=headers) - response = response.json().get("response", {}) - if response: - response = response.get("data", {}) - return response - # response = requests.post(url, json=payload, headers=headers) - # print(response.content) - - # return response.json().get("response", {}).get("data", None) - - def get_signing_public_key(self): - url = f"{self.base_url}/getSigningPublicKey" - headers = {"Cookie": f"Authorization={self.access_token}"} - - response = requests.get(url, headers=headers) - return response.json() - - def get_encryption_public_key(self): - url = f"{self.base_url}/getEncryptionPublicKey" - headers = {"Cookie": f"Authorization={self.access_token}"} - - response = requests.get(url, headers=headers) - return response.json() - - def encrypt_data_with_pin(self, data): - url = f"{self.base_url}/encryptWithPin" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": {"data": "string", "userPin": "string"}, - } - response = requests.post(url, json=payload, headers=headers) - return response.json() - - def decrypt_data_with_pin(self, data): - url = f"{self.base_url}/decryptWithPin" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": {"data": "string", "userPin": "string"}, - } - response = requests.post(url, json=payload, headers=headers) - return response.json() - - def jwt_verify(self, data): - url = f"{self.base_url}/jwtVerify" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "jwtSignatureData": "string", - "actualData": "string", - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "certificateData": "string", - "validateTrust": True, - "domain": "string", - }, - } - response = requests.post(url, json=payload, headers=headers) - return response.json() - - def jwt_sign(self, data): - url = f"{self.base_url}/jwtSign" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "dataToSign": data.get("dataToSign", "string"), - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "includePayload": True, - # "includeCertificate": True, - # "includeCertHash": True, - # "certificateUrl": data.get("certificateUrl", "string"), - }, - } - response = requests.post(url, json=payload, headers=headers) - try: - jwt_signed_data = ( - response.json().get("response", {}).get("jwtSignedData", None) - ) - except ValueError: - # print("Error parsing response JSON. JWT signing failed.") - jwt_signed_data = None - - return jwt_signed_data - - def jws_sign(self, data): - url = f"{self.base_url}/jwsSign" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "dataToSign": "string", - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "includePayload": True, - "includeCertificate": True, - "includeCertHash": True, - "certificateUrl": "string", - "validateJson": True, - "b64JWSHeaderParam": True, - "signAlgorithm": "string", - }, - } - response = requests.post(url, json=payload, headers=headers) - return response.json() - - def generate_masterkey_optional(self, data, object_type): - url = f"{self.base_url}/generateMasterKey/{object_type}" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "force": True, - "commonName": "string", - "organizationUnit": "string", - "organization": "string", - "location": "string", - "state": "string", - "country": "string", - }, - } - response = requests.post(url, json=payload, headers=headers) - return response.json() - - def generate_csr(self, data): - url = f"{self.base_url}/generateCsr" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "applicationId": data.get("applicationId", "string"), - "referenceId": data.get("referenceId", "string"), - "commonName": "string", - "organizationUnit": "string", - "organization": "string", - "location": "string", - "state": "string", - "country": "string", - }, - } - response = requests.post(url, json=payload, headers=headers) - return response.json() - - def generate_symmetric_key(self, data): - url = f"{self.base_url}/generateSymmetricKey" - headers = {"Cookie": f"Authorization={self.access_token}"} - payload = { - "id": "string", - "version": "string", - "requesttime": self.current_time, - "metadata": {}, - "request": { - "applicationId": "string", - "referenceId": "string", - "force": True, - }, - } - - response = requests.post(url, json=payload, headers=headers) - return response.json() diff --git a/g2p_encryption/readme/DESCRIPTION.rst b/g2p_encryption/readme/DESCRIPTION.rst index 4266c24..faa2b08 100644 --- a/g2p_encryption/readme/DESCRIPTION.rst +++ b/g2p_encryption/readme/DESCRIPTION.rst @@ -1 +1 @@ -OpenG2P Encryption +OpenG2P Encryption: Base diff --git a/g2p_encryption/security/groups.xml b/g2p_encryption/security/groups.xml new file mode 100644 index 0000000..6a53fb3 --- /dev/null +++ b/g2p_encryption/security/groups.xml @@ -0,0 +1,7 @@ + + + + Crypto Admin + + + diff --git a/g2p_encryption/security/ir.model.access.csv b/g2p_encryption/security/ir.model.access.csv new file mode 100644 index 0000000..5c445d8 --- /dev/null +++ b/g2p_encryption/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +encryption_provider_crypto_admin,Encryption Provider Crypto Admin,g2p_encryption.model_g2p_encryption_provider,g2p_encryption.crypto_admin,1,1,1,1 diff --git a/g2p_encryption/static/description/index.html b/g2p_encryption/static/description/index.html deleted file mode 100644 index dac1b0a..0000000 --- a/g2p_encryption/static/description/index.html +++ /dev/null @@ -1,415 +0,0 @@ - - - - - - -G2P: Encryption - - - -
-

G2P: Encryption

- - -

Alpha OpenG2P/openg2p-security

-

OpenG2P Encryption

-
-

Important

-

This is an alpha version, the data model and design can change at any time without warning. -Only for development or testing purpose, do not use in production. -More details on development status

-
-

Table of contents

- -
-

Bug Tracker

-

Bugs are tracked on GitHub 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.

-

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

-
-
-

Credits

-
-

Authors

-
    -
  • OpenG2P
  • -
-
-
-

Maintainers

-

This module is part of the OpenG2P/openg2p-security project on GitHub.

-

You are welcome to contribute.

-
-
-
- - diff --git a/g2p_encryption/views/encryption_provider.xml b/g2p_encryption/views/encryption_provider.xml new file mode 100644 index 0000000..079f9f3 --- /dev/null +++ b/g2p_encryption/views/encryption_provider.xml @@ -0,0 +1,45 @@ + + + + + view_encryption_provider_list_tree + g2p.encryption.provider + 1 + + + + + + + + + + view_encryption_provider_form + g2p.encryption.provider + 1 + +
+ + + + +
+ + + Encryption Provider + g2p.encryption.provider + tree,form + Manage encryption providers. + + + +
diff --git a/g2p_encryption_rest_api/__init__.py b/g2p_encryption_rest_api/__init__.py new file mode 100644 index 0000000..d6d6244 --- /dev/null +++ b/g2p_encryption_rest_api/__init__.py @@ -0,0 +1,2 @@ +from . import controllers +from . import services diff --git a/g2p_encryption_rest_api/__manifest__.py b/g2p_encryption_rest_api/__manifest__.py new file mode 100644 index 0000000..7d588de --- /dev/null +++ b/g2p_encryption_rest_api/__manifest__.py @@ -0,0 +1,21 @@ +{ + "name": "G2P Encryption: Rest API", + "category": "G2P", + "version": "15.0.1.2.0", + "sequence": 1, + "author": "OpenG2P", + "website": "https://openg2p.org", + "license": "Other OSI approved licence", + "development_status": "Alpha", + "depends": ["g2p_encryption", "base_rest"], + "data": [], + "assets": { + "web.assets_backend": [], + "web.assets_qweb": [], + }, + "demo": [], + "images": [], + "application": False, + "installable": True, + "auto_install": False, +} diff --git a/g2p_encryption_rest_api/controllers/__init__.py b/g2p_encryption_rest_api/controllers/__init__.py new file mode 100644 index 0000000..12a7e52 --- /dev/null +++ b/g2p_encryption_rest_api/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/g2p_encryption_rest_api/controllers/main.py b/g2p_encryption_rest_api/controllers/main.py new file mode 100644 index 0000000..aa8710b --- /dev/null +++ b/g2p_encryption_rest_api/controllers/main.py @@ -0,0 +1,7 @@ +from odoo.addons.base_rest.controllers.main import RestController + + +class SecurityController(RestController): + _root_path = "/api/v1/security/" + _collection_name = "base.rest.security.services" + _default_auth = "user" diff --git a/g2p_encryption_rest_api/readme/DESCRIPTION.rst b/g2p_encryption_rest_api/readme/DESCRIPTION.rst new file mode 100644 index 0000000..d1c072e --- /dev/null +++ b/g2p_encryption_rest_api/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +OpenG2P Encryption REST API diff --git a/g2p_encryption_rest_api/services/__init__.py b/g2p_encryption_rest_api/services/__init__.py new file mode 100644 index 0000000..8672f70 --- /dev/null +++ b/g2p_encryption_rest_api/services/__init__.py @@ -0,0 +1 @@ +from . import security diff --git a/g2p_encryption_rest_api/services/well_known.py b/g2p_encryption_rest_api/services/well_known.py new file mode 100644 index 0000000..8075d80 --- /dev/null +++ b/g2p_encryption_rest_api/services/well_known.py @@ -0,0 +1,38 @@ +import logging + +from odoo.addons.base_rest import restapi +from odoo.addons.component.core import Component + +_logger = logging.getLogger(__name__) + + +class WellknownRestService(Component): + _name = "security_well_known.rest.service" + _inherit = ["base.rest.service"] + _usage = ".well-known" + _collection = "base.rest.security.services" + _description = """ + Security Well-Known API Services + """ + + @restapi.method( + [ + ( + [ + "/jwks.json", + ], + "GET", + ) + ], + auth="public", + ) + def get_jwks(self): + encryption_providers = self.env["g2p.encryption.provider"].sudo().search([]) + jwks = [] + for prov in encryption_providers: + prov_jwks = prov.get_jwks() + try: + jwks.extend(prov_jwks.get("keys", []) if prov_jwks else []) + except Exception as e: + _logger.error("Unable to get JWKS from list of encryption providers", e) + return {"keys": jwks} diff --git a/g2p_encryption_rest_api/static/description/icon.png b/g2p_encryption_rest_api/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5ecb429ea9ceb3863d46ea852dc9c9f78d4e901b GIT binary patch literal 3985 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 literal 0 HcmV?d00001 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index a7a166e..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -# generated from manifests external_dependencies -pycrypto diff --git a/setup/g2p_encryption_keymanager/odoo/addons/g2p_encryption_keymanager b/setup/g2p_encryption_keymanager/odoo/addons/g2p_encryption_keymanager new file mode 120000 index 0000000..dc54ebc --- /dev/null +++ b/setup/g2p_encryption_keymanager/odoo/addons/g2p_encryption_keymanager @@ -0,0 +1 @@ +../../../../g2p_encryption_keymanager \ No newline at end of file diff --git a/setup/g2p_encryption_keymanager/setup.py b/setup/g2p_encryption_keymanager/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/g2p_encryption_keymanager/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/g2p_encryption_rest_api/odoo/addons/g2p_encryption_rest_api b/setup/g2p_encryption_rest_api/odoo/addons/g2p_encryption_rest_api new file mode 120000 index 0000000..517f73a --- /dev/null +++ b/setup/g2p_encryption_rest_api/odoo/addons/g2p_encryption_rest_api @@ -0,0 +1 @@ +../../../../g2p_encryption_rest_api \ No newline at end of file diff --git a/setup/g2p_encryption_rest_api/setup.py b/setup/g2p_encryption_rest_api/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/g2p_encryption_rest_api/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/test-requirements.txt b/test-requirements.txt index 82491db..3e4e76f 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1 +1,2 @@ git+https://github.com/OpenG2P/openg2p-registry@15.0-develop#subdirectory=setup/g2p_registry_base +git+https://github.com/OpenG2P/openg2p-registry@15.0-develop#subdirectory=setup/g2p_registry_individual From 774f3fa419d866a0d380fea19580ec365db5a97c Mon Sep 17 00:00:00 2001 From: Lalith Kota Date: Fri, 23 Feb 2024 18:21:44 +0530 Subject: [PATCH 06/13] Added readmes and fixed base module errors --- g2p_encryption/README.rst | 54 +++ g2p_encryption/__manifest__.py | 1 + .../__pycache__/__init__.cpython-310.pyc | Bin 206 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 213 -> 0 bytes .../models/__pycache__/crypto.cpython-310.pyc | Bin 1600 -> 0 bytes .../__pycache__/json_field.cpython-310.pyc | Bin 1344 -> 0 bytes .../__pycache__/partner.cpython-310.pyc | Bin 1041 -> 0 bytes g2p_encryption/static/description/index.html | 413 ++++++++++++++++++ g2p_encryption_rest_api/README.rst | 54 +++ g2p_encryption_rest_api/services/__init__.py | 2 +- .../services/well_known.py | 2 +- .../static/description/index.html | 413 ++++++++++++++++++ .../__pycache__/__init__.cpython-310.pyc | Bin 215 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 264 -> 0 bytes .../models/__pycache__/crypto.cpython-310.pyc | Bin 1568 -> 0 bytes .../__pycache__/json_field.cpython-310.pyc | Bin 1344 -> 0 bytes .../__pycache__/partner.cpython-310.pyc | Bin 2839 -> 0 bytes .../__pycache__/phone_number.cpython-310.pyc | Bin 1515 -> 0 bytes .../__pycache__/reg_ids.cpython-310.pyc | Bin 1474 -> 0 bytes 19 files changed, 937 insertions(+), 2 deletions(-) create mode 100644 g2p_encryption/README.rst delete mode 100644 g2p_encryption/__pycache__/__init__.cpython-310.pyc delete mode 100644 g2p_encryption/models/__pycache__/__init__.cpython-310.pyc delete mode 100644 g2p_encryption/models/__pycache__/crypto.cpython-310.pyc delete mode 100644 g2p_encryption/models/__pycache__/json_field.cpython-310.pyc delete mode 100644 g2p_encryption/models/__pycache__/partner.cpython-310.pyc create mode 100644 g2p_encryption/static/description/index.html create mode 100644 g2p_encryption_rest_api/README.rst create mode 100644 g2p_encryption_rest_api/static/description/index.html delete mode 100644 g2p_registry_encryption/__pycache__/__init__.cpython-310.pyc delete mode 100644 g2p_registry_encryption/models/__pycache__/__init__.cpython-310.pyc delete mode 100644 g2p_registry_encryption/models/__pycache__/crypto.cpython-310.pyc delete mode 100644 g2p_registry_encryption/models/__pycache__/json_field.cpython-310.pyc delete mode 100644 g2p_registry_encryption/models/__pycache__/partner.cpython-310.pyc delete mode 100644 g2p_registry_encryption/models/__pycache__/phone_number.cpython-310.pyc delete mode 100644 g2p_registry_encryption/models/__pycache__/reg_ids.cpython-310.pyc diff --git a/g2p_encryption/README.rst b/g2p_encryption/README.rst new file mode 100644 index 0000000..9c8391a --- /dev/null +++ b/g2p_encryption/README.rst @@ -0,0 +1,54 @@ +==================== +G2P Encryption: Base +==================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/github-OpenG2P%2Fopeng2p--security-lightgray.png?logo=github + :target: https://github.com/OpenG2P/openg2p-security/tree/15.0-develop/g2p_encryption + :alt: OpenG2P/openg2p-security + +|badge1| |badge2| + +OpenG2P Encryption: Base + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* OpenG2P + +Maintainers +~~~~~~~~~~~ + +This module is part of the `OpenG2P/openg2p-security `_ project on GitHub. + +You are welcome to contribute. diff --git a/g2p_encryption/__manifest__.py b/g2p_encryption/__manifest__.py index 2f76096..d91e065 100644 --- a/g2p_encryption/__manifest__.py +++ b/g2p_encryption/__manifest__.py @@ -12,6 +12,7 @@ "security/groups.xml", "security/ir.model.access.csv", "views/encryption_provider.xml", + "data/default_provider.xml", ], "assets": { "web.assets_backend": [], diff --git a/g2p_encryption/__pycache__/__init__.cpython-310.pyc b/g2p_encryption/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index affb012e1708cc4f9f0e9bc90443ab7dcd269050..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206 zcmd1j<>g`kg5w#gDWX97F^Gc(44TX@8G*u@ zjJMcw^HWlDiv2X1ZZQ;r^sHnkVgXWM;#ZJa^x#Rv7kKfcmmo>7!8RL`6zP+EkN}Z#Ff<38kRvIgXhT|hp_C|gBE{rGF)rvZlfHKmjs+WtPdiWI zrzj(R&%B0K^QdKQp{%wW{s4au?kY701yEj<0vk9uZEuw;gO;5)vFB)nwqv&e%Ue*o a30w$cO%!77`eDAquxs=_JrdI8ocsVS>ou?d diff --git a/g2p_encryption/models/__pycache__/crypto.cpython-310.pyc b/g2p_encryption/models/__pycache__/crypto.cpython-310.pyc deleted file mode 100644 index d17810771866cc75a040a303f51db697d0dc8b28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1600 zcmZ{kOK%%D5POI3E!^ZJ6t)Z_F@ho}+A3~ORe`EN0bLfWC1b6;+Eqv@ zhK0>Z4)Qlv$NZrlckr#Qz`XX*}JN`4{25$+WcuJo3C=nFa^9q%JpApH)t z-tSQ+@+nCC$J0TK)9W7`qjvcm1WC}%kO?Z-6&Z5Dg##m)7aokR@I?TlCwyQ;zYsXO=xPz|3Ul#8x0hFL6?jY1W_X?pe7BU zIPcga0zi1_RzUa-5P%l|jz&Rol_0oo1u)B|Ufm{& zW!)J}81)bwSMdvp^|Z!n8~&+)sU2M7h4T#HS|1i-O+e*UJ8l_ajE`{77uaF#tr7Yf zR5Yj&Ym+wVCNSE+!|2-X9Y&Z*Ok7ngM<5h%fhNEQI91Z;WRDmul6!MYxA8{MpRGurLzCoF)CotSU$yYGv@#c|EMiAjuomf2?`^$ZEYfx#8YX;xlrh8&3%=+s;=>_VuTu} z0ur#m3B15(e3L5t4_+&*ABAOay&jfDUf;frS~;wr#rjS2^3g=brrP;m?riX)4&i%5 OR8&2AGh5VpPE&32onEzkl5A+9UY1oglHp$Z8Jq#nYdJuM(>*)eU(CJy!nXp~!f zviIP9z}Rn6=9fg}C2sc&1u)Mt{(k^-sB%JI;(!?xRlwU4kp< ze12gDO|&fpnq?eVCV*!Fh)lvFgbI2f7D zt!Gbr-;Dk2#(AN828`Lv0nErXn7D1$RqX9=jTNb?QHKU}>3UZu-SLr+UzGXqBjnqw zl&?V1VbjgaT6GIE`l@ZEDx(ThPKKlIi_#Q%>9!Fxo+-C&^t0rghF&^de)8ehyqsts zSzQ9^gh5exSq@y) zOc0SzrKJMeTO@9iSR+C0n#y(a}2;~!{a6BiaR?4@P`ZCGOI=J$(IvQ)g*bJW{ z#jayGOEK*u5?4j85sj0jCmiE;)SQ?}A$cN_sMD%{Nm~v1<*_>|%y@sRtG`z^cb4ku iCA}$26Xe7C52N5kz_ZdO-V^WO3MXJVSCHUt=RfSNuYf9*_Y?ajJz9Sz57Y@LI^d+zgRk%h|G9xvf z;|ZzJz~Ois&8ST^CljZ3)PCjG&J<7Rl9e`Aw|3Qj?an;z&hZEIb#vm?UgPC$qk(^c z)T^4#f|}Hz&#}D^(D~DvSh$WZH!~Hcvgl_g4603rq7urio$QrN6e&9sV}s24o!WwW zi=QjoMQ_EpdQ=LfJkX4nDv?yeIHI^PD<`6A11j4rIF@-<8K1Qwj1SQ*U_IYZE%Lsh z7fG&-r$j0hH|q;?CX1#9hz-ut+*^8IL~@(^28PO5nkQN_c7txeM5l5nqDrKvh1}hH z`6Buz)tN4nR78?Xxtnk<3mwT)6wuwS7U@W3)i_$TYSTgTs9m0DG03nSt1h(Dfupy8 zZIJtzk^lq8>v#ih@}1(#hll^IL)c=|3rxUR0Vp$ORvClnquk0J#?D7czOV!=D_}RX zO4)5RZc{{)*mM_7rXtT7Q;)&kvPV{WVwoL=9ghxx1&Crww{Y`%1o^4$zWEHwZeW|? wnSBgfNWy;+2wMc80Xu-jFhAKZ)r4HCpsB@HV1k3TvDf&nj1GQ4I(Uox1$i + + + + + +G2P Encryption: Base + + + +
+

G2P Encryption: Base

+ + +

Alpha OpenG2P/openg2p-security

+

OpenG2P Encryption: Base

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • OpenG2P
  • +
+
+
+

Maintainers

+

This module is part of the OpenG2P/openg2p-security project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/g2p_encryption_rest_api/README.rst b/g2p_encryption_rest_api/README.rst new file mode 100644 index 0000000..beae759 --- /dev/null +++ b/g2p_encryption_rest_api/README.rst @@ -0,0 +1,54 @@ +======================== +G2P Encryption: Rest API +======================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/github-OpenG2P%2Fopeng2p--security-lightgray.png?logo=github + :target: https://github.com/OpenG2P/openg2p-security/tree/15.0-develop/g2p_encryption_rest_api + :alt: OpenG2P/openg2p-security + +|badge1| |badge2| + +OpenG2P Encryption REST API + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* OpenG2P + +Maintainers +~~~~~~~~~~~ + +This module is part of the `OpenG2P/openg2p-security `_ project on GitHub. + +You are welcome to contribute. diff --git a/g2p_encryption_rest_api/services/__init__.py b/g2p_encryption_rest_api/services/__init__.py index 8672f70..403ae06 100644 --- a/g2p_encryption_rest_api/services/__init__.py +++ b/g2p_encryption_rest_api/services/__init__.py @@ -1 +1 @@ -from . import security +from . import well_known diff --git a/g2p_encryption_rest_api/services/well_known.py b/g2p_encryption_rest_api/services/well_known.py index 8075d80..a6cdb4c 100644 --- a/g2p_encryption_rest_api/services/well_known.py +++ b/g2p_encryption_rest_api/services/well_known.py @@ -30,8 +30,8 @@ def get_jwks(self): encryption_providers = self.env["g2p.encryption.provider"].sudo().search([]) jwks = [] for prov in encryption_providers: - prov_jwks = prov.get_jwks() try: + prov_jwks = prov.get_jwks() jwks.extend(prov_jwks.get("keys", []) if prov_jwks else []) except Exception as e: _logger.error("Unable to get JWKS from list of encryption providers", e) diff --git a/g2p_encryption_rest_api/static/description/index.html b/g2p_encryption_rest_api/static/description/index.html new file mode 100644 index 0000000..7804e98 --- /dev/null +++ b/g2p_encryption_rest_api/static/description/index.html @@ -0,0 +1,413 @@ + + + + + + +G2P Encryption: Rest API + + + +
+

G2P Encryption: Rest API

+ + +

Alpha OpenG2P/openg2p-security

+

OpenG2P Encryption REST API

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • OpenG2P
  • +
+
+
+

Maintainers

+

This module is part of the OpenG2P/openg2p-security project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/g2p_registry_encryption/__pycache__/__init__.cpython-310.pyc b/g2p_registry_encryption/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index aee75ff67d0b13aea99125ff263cce238935d872..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215 zcmYk0F$%&!5Jh*RhzNl+UO`9^S5jDscmf+cEtZfSlEq|a+1((yfd{eiN@=aUf|V01 zKg|EUf#DCv@q&>a_mx^wzDD?0L~x+-37KMwH>~An&Y6l%ESZV;T+2 zjWTttm6hyZ16Fw3_aaYJ|YwkScMLd*)K(0G9sOqJWrL)keUdO;u^RN4pE gOE9JDZO~|hl-lSZ<=Xbcd`I0~1N-q6KXxbV3*?byb`bfM|S0-M831`ES zfBUl~`=`UW!;)>p9U@w zdAm&$MRaiqXQ4gg#d*kY?QT diff --git a/g2p_registry_encryption/models/__pycache__/crypto.cpython-310.pyc b/g2p_registry_encryption/models/__pycache__/crypto.cpython-310.pyc deleted file mode 100644 index a90b2d310346fca0e00e0accc07fdeb0103d39d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1568 zcmZ{kPjA~c6u|jMqGZR((jaZpZUce>JNS?|2)dw$qFCz|0|qn$mcuY#1X*NiIkM!E z^nw`b$=UaikNrx#_SCPi)83QZ)af<}B;TXR_sHLSPsQeDo51tOyC38QC*&h4>yHP@ zPteRW=p>OeBZFq70}49J*n|%_#W|jN6Mx`S@-va1^lymtm00jWAn7^jicesHoOP)a zzs0#MCLr+_ug?>lUVq>ijmxJXD1vSVOj5~i$bd^OJs82f6fpWSkRgmh1+pdEH)KHv zq1*s>9oGWm{d77~I$>+}QN~;Kp_v2dEE&_1M9lKaD{18~$&yxLNnkFJblFEXH<5fJ7D4i z(OWS5{d;dzOjOURWRw?&C#T1~t3qFzX`HBDA&cTLma@oAub8U*?aB1esAQ&7d))&i z0w?-p|-q;77S+8Ox84J*Zk}dgrZo{fovXWPA;J1PN_Mn{;?SmnRgcnU? zsS&*6xw>+mR-hwMEwDo{E`0OrtJhKgW#5TmY}Dx!*BYKaS@8^3SJs%VT~BY~4zA-X z$I?HYNa`@xWSj0AG`j~Knl^}{O}FU|lDPMU#LDRZgZKqDT2j#lLtXA?y@Fs)O>x)d$4XFnnBOU zbiVZ^MwmJYh3U@^%D0Dm3`z~Z^F?o?am+xCA<%e3 z*D*G>X);lER7j1k*4)>DtMe9X5pQU4DkLEby-@Q diff --git a/g2p_registry_encryption/models/__pycache__/json_field.cpython-310.pyc b/g2p_registry_encryption/models/__pycache__/json_field.cpython-310.pyc deleted file mode 100644 index ec1dce7e95174a7b4a04b6fd82a61d38d53bc2e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1344 zcmaJ>&2AGh5VpPE&32onEzkl5A+9UY1oglHp$Z8Jq#nYdJuM(>*)eU(CJy!nXp~!f zviIP9z}Rn6=9fg}C2sc&1u)Mt{(k^-sB%JI;(!?xRlwU4kp< ze12gDO|&fpnq?eVCV*!Fh)lvFgbI2f7D zt!Gbr-;Dk2#(AN828`Lv0nErXn7D1$RqX9=jTNb?QHKU}>3UZu-SLr+UzGXqBjnqw zl&?V1VbjgaT6GIE`l@ZEDx(ThPKKlIi_#Q%>9!Fxo+-C&^t0rghF&^de)8ehyqsts zSzQ9^gh5exSq@y) zOc0SzrKJMeTO@9iSR+C0n#y(a}2;~!{a6BiaR?4@P`ZCGOI=J$(IvQ)g*bJW{ z#jayGOEK*u5?4j85sj0jCmiE;)SQ?}A$cN_sMD%{Nm~v1<*_>|%y@sRtG`z^cb4ku iCA}$26Xe7C52Nr5T4O%wNJ0tc7k~%Bs?k$csI#`lPi^A0$eaqzHJpz$(pe(M=L2K*_2)D zlU4Z|04UmnAf#az;F_q4Ytf@V*DfyZ(i`i#{+1%K7PR&V! zIa_4d_zUJCLn@t}kVh;Vn$npjj7OO;fRLu2hQKx-J>J>~(>*Q%e7}0(itx&Q2jFBv z8JQT2PE2m?+st4l*aXYJ7!yZnoQkHQG>wYJRT{UVX(~;#qG>5jtDZLs^e4oVllTvdH>u@r+Cc&xu7QOW>b@>_3hJag^qqeea7r=Hj?5 zcs5G)AfRgV8c;@eY{31Z127}!5F%z=7%-K&DXrL_a@j-l7%!&1q_Q_3c`6E^u`(X* zToTcPS+4x?UNYt5oCkYxvUdOTyW^h{@ia^QfR7WFBx^onNt}(7l*haG)3uBT2O`Xm z#xU>%-wm@|9C=*tBTVA4j_|nH!zewH?t0`;x0(L{m;C}m-yz4VuWx-cf9tEEAsaz5 zO%HM|?JQ3O|4&bd2F!-LZ}0fiFgo&-6ILpN`R+LrnEe9Rpmwfd0f&8nE((hP|8J|c z8y@mln_7M;*R_OhuW6|X&X2UArBbYGM{TX%j%+^l!$>ZuN8S0+Yc=;_r+Z1v<$`+D zogbH8bABi*+hN3IUq9IZU{-Cs0RnlG7PEHO`G0y`U$?jO?3?u99;LOX`JjV$MwQTW-(HQ+i^} z3}&qoaeHQ+J6gV=F%)8y*AZ=C?-eY_C2K3z0rp|Rf?TqWVjIAISFj+LY(udwuulpW z zq$YyN-pjhJRs~Z*H%g#KG(9hf{4DdlN}U|S47kn=*V8u!hDBX^<6nN3aeV!a`mUE5 zU>eRZTtD8})G`JDsR&ICQV|+knTn&_C{mGpNq)R>V$bXuyd!Qw5KJv!Pk=ZYpO?No$uK6JDL zJARNK_>pd=a-rwYxlX}!e#0j18V&ZZoB!0+vXp? zHZWY4uBSSJ=gF4mLAO1KILIB(dj{)L?calU!Wa%zVXjYF*2bPML=%jP6@=>us|fEP zyoYcT;TFON2v{+st(v*OxC>mn>=tPe@F<$6hU#bc@De2okmA#uoS6X<^Pzx299NP39RF0t7!r^07d^wn$aKsqtBgRN4tB#iaEgme@loh9| ZrQxdJ45B^t0MAhwetR9dY;@=~;~zPSZR7v| diff --git a/g2p_registry_encryption/models/__pycache__/phone_number.cpython-310.pyc b/g2p_registry_encryption/models/__pycache__/phone_number.cpython-310.pyc deleted file mode 100644 index d2a144dadc43b4d7fa78478a20b8446639e68b6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1515 zcmZux&2HQ_5GE-~tF_mTu4dm2!@E-F@yyg_3FHoO4Luy^4@BkbQNs%-2%{Q#Jwl)aJ-+vs)*eB!@PHqc_ z$uk(u3s90snv;UYl%mbRW--Hg;l-X^^KxGJu}{fwL~`k066q^;7A(DZAcGS!9(;y- z$e5a7nyFkiW6uOdB~{*N1{=mp>I`;=&tIM#W%W$y6#u_17!gYI43r`%1{n3Nxboaa1w7qJR4^3Wtr+l-75KNR+Z{_ zUc6TNeCPB@9o4uHm3Aei=(HEKF^(e`%?MOSt^ga!Rt)a+j!kHfin21hYfDJg`+@wn z*E3;ZfEC`TeEN~-O}OoPI+<04nzSmNmDRzMpC3=&SNcs;C#jlLvZ@XeDXX%XRJAH0 z(1S*$bDgz|2~31mr&-hLg-|ZBtSToC;z=KiO(?1tCOpiO;4q#@2RI3ES_Eh=K3{O?-PHT+W40^c6zD6_*f0yKq2_U^n zOSAnSnD&0S3OG}J1gZ*==1J2CVQZ(64tfvNJs6f8J8YM68q!CUv-5{{qU!=n5wx{n z#5gR+Bp3i3a14M0p4|W!wX6q@{6hYGbm4b?2mk1A0YJ~$D+*tBNJ=ho1+3P>jP^cR zLf^iR?)h?)O`V%1XB~Blpa#;0THh!(MvKW2(6y24+Q?DOA@Bc= dkEOlx7JxS>LPxudpW+kMU`8Xl$42x4`xn^WeBA&5 diff --git a/g2p_registry_encryption/models/__pycache__/reg_ids.cpython-310.pyc b/g2p_registry_encryption/models/__pycache__/reg_ids.cpython-310.pyc deleted file mode 100644 index a43a2797fb47b9cce1717c612c4ec912660222e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1474 zcmZ8h&2HQ_5GE-~t6i@h$8plSKLOf9(FI~{kV8*Kkk(0y9%>ZzsR9Z@5$UxYt)!6J z6l=(*HIP%$SMVP5O1$>eN2pJoA$MKZ1UMR!;{1H`4eQO#0fF)7ulw?8NXTEfxIH*5 zUcfZpfsjPfl1ynzDe4S#mNHyVgEVk^LCL3K8dCBDkz9tCM23o;MT;Qq$>^AjdVhl* zGNLv*DO4%VD6rAAmZ~(G!GR63rhwD_x37*5i{@169RI&PFd`i01qek_DoM&DO#{Wx zLdj$RKEd-JER9s}EPhW;sElOqGG5TMFJsxiB`(<=Fkn*8|k zd@y;|Bw9_9Lgo}5tp@7o`w*rXg6PN<;33(Pft}#UhVQa+rtCfU5mK$JLN;6Lm2gSJ z4mYYi`9Smr*tyQer}b2gTa}+y_5QPOo{oR7^&8V&lGlMpY2pzESy1 z7wvou3jvW9rqy$yd>TbvjXj`aI1+_4Ni(`gE9(I~aYzL4H9v!BNlQDjU{|c8OM1aNau!IsN3J;5W63UpF3?}K zVHYgu1@D;TdqjWP@vF$|OIkq{Q9l3)Xog4E4+@>+b#+oqM3d=ks#>M(24)P2iZ^O* ziSB{#Q4d0#HA?FURyNAD${_4ORqt$nqFR4jW6ZXhxn zHUK<5PRMQ#Rv)yFVH!luLlpyDyEJAyl>Y;ueSQbDJ1sM`u@Du|KnOb!0vJ9kQ6CEN z7NT06#G|K40n~87SWW`#f6SQaI+cWX>@|cG|;Tz~o-h%E1 WKj>ed@pF8I3}!T>yKG1wv3~)q&uSO| From e235a38eb703904cb826c1c9c4c32e21aad57516 Mon Sep 17 00:00:00 2001 From: Lalith Kota Date: Sat, 24 Feb 2024 08:09:25 +0530 Subject: [PATCH 07/13] Added Keymanager encryptor. Reorganized registry encrpytor --- g2p_encryption/models/encryption_provider.py | 29 +- g2p_encryption/views/encryption_provider.xml | 6 +- g2p_encryption_keymanager/README.rst | 54 +++ g2p_encryption_keymanager/__init__.py | 1 + g2p_encryption_keymanager/__manifest__.py | 27 ++ .../data/default_provider.xml | 10 + g2p_encryption_keymanager/models/__init__.py | 1 + .../models/encryption_provider.py | 313 +++++++++++++ .../readme/DESCRIPTION.rst | 1 + .../static/description/icon.png | Bin 0 -> 3985 bytes .../static/description/index.html | 413 ++++++++++++++++++ .../views/encryption_provider.xml | 41 ++ g2p_registry_encryption/README.rst | 15 +- g2p_registry_encryption/__manifest__.py | 6 +- .../controllers/__init__.py | 1 - .../controllers/payments.py | 7 - .../data/registry_encryption_provider.xml | 11 + g2p_registry_encryption/models/__init__.py | 4 +- .../models/encryption_provider.py | 26 ++ g2p_registry_encryption/models/partner.py | 227 ++++------ .../models/payment_file_keymanager.py | 97 ---- .../models/payment_file_qrcode_config.py | 179 -------- .../models/payment_key_set.py | 147 ------- .../models/phone_number.py | 41 -- g2p_registry_encryption/models/reg_ids.py | 41 -- .../models/registry_config.py | 25 -- .../models/res_config_settings.py | 18 + g2p_registry_encryption/security/security.xml | 7 - .../static/description/index.html | 32 +- ...decrypt_file.xml => decrypted_partner.xml} | 3 +- .../views/res_config_view.xml | 49 ++- requirements.txt | 4 + 32 files changed, 1085 insertions(+), 751 deletions(-) create mode 100644 g2p_encryption_keymanager/README.rst create mode 100644 g2p_encryption_keymanager/__init__.py create mode 100644 g2p_encryption_keymanager/__manifest__.py create mode 100644 g2p_encryption_keymanager/data/default_provider.xml create mode 100644 g2p_encryption_keymanager/models/__init__.py create mode 100644 g2p_encryption_keymanager/models/encryption_provider.py create mode 100644 g2p_encryption_keymanager/readme/DESCRIPTION.rst create mode 100644 g2p_encryption_keymanager/static/description/icon.png create mode 100644 g2p_encryption_keymanager/static/description/index.html create mode 100644 g2p_encryption_keymanager/views/encryption_provider.xml delete mode 100644 g2p_registry_encryption/controllers/__init__.py delete mode 100644 g2p_registry_encryption/controllers/payments.py create mode 100644 g2p_registry_encryption/data/registry_encryption_provider.xml create mode 100644 g2p_registry_encryption/models/encryption_provider.py delete mode 100644 g2p_registry_encryption/models/payment_file_keymanager.py delete mode 100644 g2p_registry_encryption/models/payment_file_qrcode_config.py delete mode 100644 g2p_registry_encryption/models/payment_key_set.py delete mode 100644 g2p_registry_encryption/models/phone_number.py delete mode 100644 g2p_registry_encryption/models/reg_ids.py delete mode 100644 g2p_registry_encryption/models/registry_config.py create mode 100644 g2p_registry_encryption/models/res_config_settings.py delete mode 100644 g2p_registry_encryption/security/security.xml rename g2p_registry_encryption/views/{decrypt_file.xml => decrypted_partner.xml} (91%) create mode 100644 requirements.txt diff --git a/g2p_encryption/models/encryption_provider.py b/g2p_encryption/models/encryption_provider.py index 7adb097..7356056 100644 --- a/g2p_encryption/models/encryption_provider.py +++ b/g2p_encryption/models/encryption_provider.py @@ -1,4 +1,4 @@ -from odoo import api, fields, models +from odoo import fields, models class G2PEncryptionProvider(models.Model): @@ -6,22 +6,31 @@ class G2PEncryptionProvider(models.Model): _description = "G2P Encryption Provider" name = fields.Char(required=True) - type = fields.Selection(selection="_selection_provider_type") + type = fields.Selection(selection=[]) - @api.model - def _selection_provider_type(self): - return [] - - def encrypt_data(self, data, **kwargs): + def encrypt_data(self, data: bytes, **kwargs) -> bytes: + """ + Both input and output are NOT base64 encoded + """ raise NotImplementedError() - def decrypt_data(self, data, **kwargs): + def decrypt_data(self, data: bytes, **kwargs) -> bytes: + """ + Both input and output are NOT base64 encoded + """ raise NotImplementedError() - def sign_jwt(self, data, **kwargs): + def jwt_sign( + self, + data: dict, + include_payload=True, + include_certificate=True, + include_cert_hash=True, + **kwargs + ) -> str: raise NotImplementedError() - def verifiy_jwt(self, data, **kwargs): + def jwt_verify(self, data: str, **kwargs) -> dict: raise NotImplementedError() def get_jwks(self, **kwargs): diff --git a/g2p_encryption/views/encryption_provider.xml b/g2p_encryption/views/encryption_provider.xml index 079f9f3..a5824fb 100644 --- a/g2p_encryption/views/encryption_provider.xml +++ b/g2p_encryption/views/encryption_provider.xml @@ -21,8 +21,10 @@ Part of OpenG2P. See LICENSE file for full copyright and licensing details. 1
- - + + + + diff --git a/g2p_encryption_keymanager/README.rst b/g2p_encryption_keymanager/README.rst new file mode 100644 index 0000000..006f844 --- /dev/null +++ b/g2p_encryption_keymanager/README.rst @@ -0,0 +1,54 @@ +========================== +G2P Encryption: Keymanager +========================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/github-OpenG2P%2Fopeng2p--security-lightgray.png?logo=github + :target: https://github.com/OpenG2P/openg2p-security/tree/15.0-develop/g2p_encryption_keymanager + :alt: OpenG2P/openg2p-security + +|badge1| |badge2| + +OpenG2P Encryption With Keymanager + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* OpenG2P + +Maintainers +~~~~~~~~~~~ + +This module is part of the `OpenG2P/openg2p-security `_ project on GitHub. + +You are welcome to contribute. diff --git a/g2p_encryption_keymanager/__init__.py b/g2p_encryption_keymanager/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/g2p_encryption_keymanager/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/g2p_encryption_keymanager/__manifest__.py b/g2p_encryption_keymanager/__manifest__.py new file mode 100644 index 0000000..d004f31 --- /dev/null +++ b/g2p_encryption_keymanager/__manifest__.py @@ -0,0 +1,27 @@ +{ + "name": "G2P Encryption: Keymanager", + "category": "G2P", + "version": "15.0.1.2.0", + "sequence": 1, + "author": "OpenG2P", + "website": "https://openg2p.org", + "license": "Other OSI approved licence", + "development_status": "Alpha", + "depends": [ + "g2p_encryption", + ], + "external_dependencies": {"python": ["cryptography", "jwcrypto", "python-jose"]}, + "data": [ + "views/encryption_provider.xml", + "data/default_provider.xml", + ], + "assets": { + "web.assets_backend": [], + "web.assets_qweb": [], + }, + "demo": [], + "images": [], + "application": False, + "installable": True, + "auto_install": False, +} diff --git a/g2p_encryption_keymanager/data/default_provider.xml b/g2p_encryption_keymanager/data/default_provider.xml new file mode 100644 index 0000000..db04bdb --- /dev/null +++ b/g2p_encryption_keymanager/data/default_provider.xml @@ -0,0 +1,10 @@ + + + + + Default Keymanager Encryption Provider + keymanager + + diff --git a/g2p_encryption_keymanager/models/__init__.py b/g2p_encryption_keymanager/models/__init__.py new file mode 100644 index 0000000..56c044c --- /dev/null +++ b/g2p_encryption_keymanager/models/__init__.py @@ -0,0 +1 @@ +from . import encryption_provider diff --git a/g2p_encryption_keymanager/models/encryption_provider.py b/g2p_encryption_keymanager/models/encryption_provider.py new file mode 100644 index 0000000..048e668 --- /dev/null +++ b/g2p_encryption_keymanager/models/encryption_provider.py @@ -0,0 +1,313 @@ +import base64 +import json +import logging +import os +import secrets +from datetime import datetime + +import requests +from cryptography import x509 +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.serialization import Encoding +from jose import jwt +from jwcrypto import jwk + +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + +KEYMANAGER_API_BASE_URL = os.getenv( + "KEYMANAGER_API_BASE_URL", "http://keymanager.keymanager/v1/keymanager" +) +KEYMANAGER_AUTH_URL = os.getenv( + "KEYMANAGER_AUTH_URL", + "http://keycloak.keycloak/realms/openg2p/protocol/openid-connect/token", +) +KEYMANAGER_AUTH_CLIENT_ID = os.getenv( + "KEYMANAGER_AUTH_CLIENT_ID", "openg2p-admin-client" +) +KEYMANAGER_AUTH_CLIENT_SECRET = os.getenv("KEYMANAGER_AUTH_CLIENT_SECRET", "") +KEYMANAGER_AUTH_GRANT_TYPE = os.getenv( + "KEYMANAGER_AUTH_GRANT_TYPE", "client_credentials" +) + + +class KeymanagerEncryptionProvider(models.Model): + _inherit = "g2p.encryption.provider" + + type = fields.Selection(selection_add=[("keymanager", "Keymanager")]) + + @api.model + def _km_random_secret(self): + return secrets.token_urlsafe() + + @api.model + def km_generate_current_time(self): + return f'{datetime.utcnow().isoformat(timespec = "milliseconds")}Z' + + keymanager_api_base_url = fields.Char(default=KEYMANAGER_API_BASE_URL) + keymanager_auth_url = fields.Char(default=KEYMANAGER_AUTH_URL) + keymanager_auth_client_id = fields.Char(default=KEYMANAGER_AUTH_CLIENT_ID) + keymanager_auth_client_secret = fields.Char(default=KEYMANAGER_AUTH_CLIENT_SECRET) + keymanager_auth_grant_type = fields.Char(default=KEYMANAGER_AUTH_GRANT_TYPE) + + keymanager_access_token = fields.Char() + keymanager_access_token_expiry = fields.Datetime() + + keymanager_encrypt_application_id = fields.Char(default="REGISTRATION") + keymanager_encrypt_reference_id = fields.Char(default="ENCRYPT") + + keymanager_sign_application_id = fields.Char(default="REGISTRATION") + keymanager_sign_reference_id = fields.Char(default="") + + keymanager_encrypt_salt = fields.Char(default=_km_random_secret) + keymanager_encrypt_aad = fields.Char(default=_km_random_secret) + + def encrypt_data(self, data: bytes, **kwargs) -> bytes: + self.ensure_one() + access_token = self.km_get_access_token() + current_time = self.km_generate_current_time() + url = f"{self.keymanager_api_base_url}/encrypt" + headers = {"Cookie": f"Authorization={access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": current_time, + "metadata": {}, + "request": { + "applicationId": self.keymanager_encrypt_application_id or "", + "referenceId": self.keymanager_encrypt_reference_id or "", + "timeStamp": current_time, + "data": base64.urlsafe_b64encode(data).decode(), + "salt": self.keymanager_encrypt_salt, + "aad": self.keymanager_encrypt_aad, + }, + } + response = requests.post(url, json=payload, headers=headers) + _logger.debug("Keymanager Encrypt API response: %s", response.text) + response.raise_for_status() + if response: + response = response.json() + if response: + response = response.get("response") + if response: + return base64.urlsafe_b64decode(response.get("data").encode()) + raise ValueError("Could not encrypt data, invalid keymanager response") + + def decrypt_data(self, data: bytes, **kwargs) -> bytes: + self.ensure_one() + access_token = self.km_get_access_token() + current_time = self.km_generate_current_time() + url = f"{self.keymanager_api_base_url}/decrypt" + headers = {"Cookie": f"Authorization={access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": current_time, + "metadata": {}, + "request": { + "applicationId": self.keymanager_encrypt_application_id or "", + "referenceId": self.keymanager_encrypt_reference_id or "", + "timeStamp": current_time, + "data": base64.urlsafe_b64encode(data).decode(), + "salt": self.keymanager_encrypt_salt, + "aad": self.keymanager_encrypt_aad, + }, + } + response = requests.post(url, json=payload, headers=headers) + _logger.debug("Keymanager Decrypt API response: %s", response.text) + response.raise_for_status() + if response: + response = response.json() + if response: + response = response.get("response") + if response: + return base64.urlsafe_b64decode(response.get("data").encode()) + raise ValueError("Could not decrypt data, invalid keymanager response") + + def jwt_sign( + self, + data: dict, + include_payload=True, + include_certificate=False, + include_cert_hash=False, + **kwargs, + ) -> str: + self.ensure_one() + access_token = self.km_get_access_token() + current_time = self.km_generate_current_time() + url = f"{self.keymanager_api_base_url}/jwtSign" + headers = {"Cookie": f"Authorization={access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": current_time, + "metadata": {}, + "request": { + "dataToSign": base64.urlsafe_b64encode( + json.dumps(data).encode() + ).decode(), + "applicationId": self.keymanager_sign_application_id or "", + "referenceId": self.keymanager_sign_reference_id or "", + "includePayload": include_payload, + "includeCertificate": include_certificate, + "includeCertHash": include_cert_hash, + }, + } + response = requests.post(url, json=payload, headers=headers) + _logger.debug("Keymanager JWT Sign API response: %s", response.text) + response.raise_for_status() + if response: + response = response.json() + if response: + response = response.get("response", {}) + if response: + return response.get("jwtSignedData") + raise ValueError("Could not sign jwt, invalid keymanager response") + + def jwt_verify(self, data: str, **kwargs) -> dict: + self.ensure_one() + access_token = self.km_get_access_token() + current_time = self.km_generate_current_time() + url = f"{self.keymanager_api_base_url}/jwtVerify" + headers = {"Cookie": f"Authorization={access_token}"} + payload = { + "id": "string", + "version": "string", + "requesttime": current_time, + "metadata": {}, + "request": { + "jwtSignatureData": data, + "applicationId": self.keymanager_sign_application_id or "", + "referenceId": self.keymanager_sign_reference_id or "", + "validateTrust": False, + }, + } + response = requests.post(url, json=payload, headers=headers) + _logger.debug("Keymanager JWT Verify API response: %s", response.text) + response.raise_for_status() + if response: + response = response.json() + if response: + response = response.get("response", {}) + if response: + response = response.get("signatureValid", False) + else: + raise ValueError("Could not verify jwt, invalid keymanager response") + if response: + return jwt.decode( + data, + None, + options={ + "verify_signature": False, + "verify_exp": False, + "verify_nbf": False, + "verify_iss": False, + "verify_aud": False, + "verify_at_hash": False, + }, + ) + raise ValueError("invalid jwt signature") + + def get_jwks(self, **kwargs): + # TODO: Cache this JWKS response somehow + self.ensure_one() + access_token = self.km_get_access_token() + jwks = [] + for app_id, ref_id, use in ( + ( + self.keymanager_encrypt_application_id or "", + self.keymanager_encrypt_reference_id or "", + "enc", + ), + ( + self.keymanager_sign_application_id or "", + self.keymanager_sign_reference_id or "", + "sign", + ), + ): + url = f"{self.keymanager_api_base_url}/getAllCertificates" + if self.keymanager_sign_application_id: + url += f"?applicationId={app_id}" + if self.keymanager_sign_reference_id: + url += f"&referenceId={ref_id}" + headers = {"Cookie": f"Authorization={access_token}"} + response = requests.get(url, headers=headers) + _logger.debug("Keymanager get Certificate API response: %s", response.text) + response.raise_for_status() + certs = response.json().get("response", {}).get("allCertificates", []) + for cert in certs: + jwks.append( + self.km_convert_x509_pem_to_jwk( + cert.get("certificateData", "").encode(), + use=use, + kid=cert.get("keyId"), + ) + ) + return {"keys": jwks} + + @api.model + def km_convert_x509_pem_to_jwk(self, cert: bytes, use=None, kid=None): + x509_cert = x509.load_pem_x509_certificate(cert) + public_key = x509_cert.public_key() + new = jwk.JWK() + new.import_from_pyca(public_key) + new.update( + { + "x5c": [ + base64.b64encode(x509_cert.public_bytes(Encoding.DER)).decode() + ], + "x5t": base64.urlsafe_b64encode( + x509_cert.fingerprint(hashes.SHA1()) + ).decode(), + "x5t#S256": base64.urlsafe_b64encode( + x509_cert.fingerprint(hashes.SHA256()) + ).decode(), + } + ) + if kid: + new["kid"] = kid + if use: + new["use"] = use + return dict(new) + + def km_get_access_token(self): + self.ensure_one() + if ( + self.keymanager_access_token + and self.keymanager_access_token_expiry + and self.keymanager_access_token_expiry > datetime.utcnow() + ): + return self.keymanager_access_token + data = { + "client_id": self.keymanager_auth_client_id, + "client_secret": self.keymanager_auth_client_secret, + "grant_type": self.keymanager_auth_grant_type, + } + response = requests.post(self.keymanager_auth_url, data=data) + _logger.debug("Keymanager get Certificates API response: %s", response.text) + response.raise_for_status() + access_token = response.json().get("access_token", None) + token_exp = jwt.decode( + access_token, + None, + options={ + "verify_signature": False, + "verify_exp": False, + "verify_nbf": False, + "verify_iss": False, + "verify_aud": False, + "verify_at_hash": False, + }, + ).get("exp") + self.write( + { + "keymanager_access_token": access_token, + "keymanager_access_token_expiry": datetime.fromtimestamp(token_exp) + if isinstance(token_exp, int) + else datetime.fromisoformat(token_exp) + if isinstance(token_exp, str) + else token_exp, + } + ) + return access_token diff --git a/g2p_encryption_keymanager/readme/DESCRIPTION.rst b/g2p_encryption_keymanager/readme/DESCRIPTION.rst new file mode 100644 index 0000000..7078bb9 --- /dev/null +++ b/g2p_encryption_keymanager/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +OpenG2P Encryption With Keymanager diff --git a/g2p_encryption_keymanager/static/description/icon.png b/g2p_encryption_keymanager/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5ecb429ea9ceb3863d46ea852dc9c9f78d4e901b GIT binary patch literal 3985 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 literal 0 HcmV?d00001 diff --git a/g2p_encryption_keymanager/static/description/index.html b/g2p_encryption_keymanager/static/description/index.html new file mode 100644 index 0000000..eef0aa2 --- /dev/null +++ b/g2p_encryption_keymanager/static/description/index.html @@ -0,0 +1,413 @@ + + + + + + +G2P Encryption: Keymanager + + + +
+

G2P Encryption: Keymanager

+ + +

Alpha OpenG2P/openg2p-security

+

OpenG2P Encryption With Keymanager

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • OpenG2P
  • +
+
+
+

Maintainers

+

This module is part of the OpenG2P/openg2p-security project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/g2p_encryption_keymanager/views/encryption_provider.xml b/g2p_encryption_keymanager/views/encryption_provider.xml new file mode 100644 index 0000000..7f0f78e --- /dev/null +++ b/g2p_encryption_keymanager/views/encryption_provider.xml @@ -0,0 +1,41 @@ + + + + + view_keymanager_encryption_provider_form + g2p.encryption.provider + + 2 + +
+ + + + + + + + + + + + + + + + +
+
+
+
diff --git a/g2p_registry_encryption/README.rst b/g2p_registry_encryption/README.rst index 40a1f9d..d1fc794 100644 --- a/g2p_registry_encryption/README.rst +++ b/g2p_registry_encryption/README.rst @@ -1,14 +1,11 @@ -======================= -G2P:Registry Encryption -======================= +======================== +G2P Registry: Encryption +======================== -.. - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:f327c3d41cb609867269ed2e931991410e42861b8794e665b07ba65be1718803 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png :target: https://odoo-community.org/page/development-status @@ -17,7 +14,7 @@ G2P:Registry Encryption :target: https://github.com/OpenG2P/openg2p-security/tree/15.0-develop/g2p_registry_encryption :alt: OpenG2P/openg2p-security -|badge1| |badge2| +|badge1| |badge2| OpenG2P Registry Encryption @@ -36,7 +33,7 @@ Bug Tracker Bugs are tracked on `GitHub 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 +If you spotted it first, help us smashing it by providing a detailed and welcomed `feedback `_. Do not contact contributors directly about support or help with technical issues. diff --git a/g2p_registry_encryption/__manifest__.py b/g2p_registry_encryption/__manifest__.py index 2c892e6..58cee70 100644 --- a/g2p_registry_encryption/__manifest__.py +++ b/g2p_registry_encryption/__manifest__.py @@ -1,5 +1,5 @@ { - "name": "G2P:Registry Encryption", + "name": "G2P Registry: Encryption", "category": "G2P", "version": "15.0.1.2.0", "sequence": 1, @@ -9,9 +9,9 @@ "development_status": "Alpha", "depends": ["g2p_encryption", "g2p_registry_base", "g2p_registry_individual"], "data": [ - "views/decrypt_file.xml", + "data/registry_encryption_provider.xml", + "views/decrypted_partner.xml", "views/res_config_view.xml", - "security/security.xml", ], "assets": { "web.assets_backend": [], diff --git a/g2p_registry_encryption/controllers/__init__.py b/g2p_registry_encryption/controllers/__init__.py deleted file mode 100644 index 8ac3dc0..0000000 --- a/g2p_registry_encryption/controllers/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import payments diff --git a/g2p_registry_encryption/controllers/payments.py b/g2p_registry_encryption/controllers/payments.py deleted file mode 100644 index f52f3e6..0000000 --- a/g2p_registry_encryption/controllers/payments.py +++ /dev/null @@ -1,7 +0,0 @@ -from odoo.addons.base_rest.controllers import main - - -class RegistryApiController(main.RestController): - _root_path = "/api/v1/payments/" - _collection_name = "base.rest.payment.services" - _default_auth = "user" diff --git a/g2p_registry_encryption/data/registry_encryption_provider.xml b/g2p_registry_encryption/data/registry_encryption_provider.xml new file mode 100644 index 0000000..0d6e7fc --- /dev/null +++ b/g2p_registry_encryption/data/registry_encryption_provider.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/g2p_registry_encryption/models/__init__.py b/g2p_registry_encryption/models/__init__.py index fddb317..f927713 100644 --- a/g2p_registry_encryption/models/__init__.py +++ b/g2p_registry_encryption/models/__init__.py @@ -1 +1,3 @@ -from . import partner, phone_number, reg_ids, registry_config +from . import encryption_provider +from . import partner +from . import res_config_settings diff --git a/g2p_registry_encryption/models/encryption_provider.py b/g2p_registry_encryption/models/encryption_provider.py new file mode 100644 index 0000000..33b9dae --- /dev/null +++ b/g2p_registry_encryption/models/encryption_provider.py @@ -0,0 +1,26 @@ +from odoo import api, models + + +class RegistryEncryptionProvider(models.Model): + _inherit = "g2p.encryption.provider" + + @api.model + def set_registry_provider(self, provider_id, replace=True): + if provider_id and ( + replace + or not self.env["ir.config_parameter"] + .sudo() + .get_param("g2p_registry_encryption.encryption_provider_id", None) + ): + self.env["ir.config_parameter"].sudo().set_param( + "g2p_registry_encryption.encryption_provider_id", str(provider_id) + ) + + @api.model + def get_registry_provider(self): + prov_id = ( + self.env["ir.config_parameter"] + .sudo() + .get_param("g2p_registry_encryption.encryption_provider_id", None) + ) + return self.browse(prov_id) if prov_id else None diff --git a/g2p_registry_encryption/models/partner.py b/g2p_registry_encryption/models/partner.py index 76ea343..350a50c 100644 --- a/g2p_registry_encryption/models/partner.py +++ b/g2p_registry_encryption/models/partner.py @@ -1,165 +1,96 @@ -import base64 import json from odoo import api, fields, models -from odoo.addons.g2p_encryption.models.keymanager_api import EncryptionModule, OdooAuth - class EncryptedPartner(models.Model): _inherit = "res.partner" - is_encrypted = fields.Boolean("Is encrypted?") - encrypted_val = fields.Char("Encrypted value") - # encrypted_val = fields.Binary("Encrypted value") - - @api.model - def create(self, vals): - odoo_token = { - "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", - "auth_client_id": "openg2p-admin-client", - "auth_client_secret": "x75SU2hqKQX7IPob", - "auth_grant_type": "client_credentials", - } - - odoo_auth = OdooAuth(**odoo_token) - base_url = "https://dev.openg2p.net/v1/keymanager" - encryption_module_instance = EncryptionModule(base_url, odoo_auth) - application_id = "REGISTRATION" - reference_id = "string" + encrypted_val = fields.Binary("Encrypted value", attachment=False) + is_encrypted = fields.Boolean(default=False) - def encrypt_field(field_value): - json_data = json.dumps(field_value) - encoded_field_value = base64.b64encode((json_data).encode()).decode() - encrypted_data = encryption_module_instance.encrypt_data( - { - "applicationId": application_id, - "referenceId": reference_id, - "data": encoded_field_value, - } - ) - return encrypted_data + fields_list_to_enc = [ + "name", + "family_name", + "given_name", + "addl_name", + "display_name", + "address", + "birth_place", + ] - vals["is_encrypted"] = bool(vals.get("name")) - vals["encrypted_val"] = encrypt_field(vals) + placeholder_to_encrypted_field = "encrypted" - vals["name"] = "encrypted" - vals["family_name"] = "encrypted" - vals["given_name"] = "encrypted" - vals["addl_name"] = "encrypted" - vals["display_name"] = "encrypted" - vals["address"] = "encrypted" - vals["birth_place"] = "encrypted" - # for field, value in vals.items(): - # if isinstance(value, str): - # vals[field] = "encrypted" - record = super(EncryptedPartner, self).create(vals) - return record - - def write(self, vals): - odoo_token = { - "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", - "auth_client_id": "openg2p-admin-client", - "auth_client_secret": "x75SU2hqKQX7IPob", - "auth_grant_type": "client_credentials", - } - - odoo_auth = OdooAuth(**odoo_token) - base_url = "https://dev.openg2p.net/v1/keymanager" - encryption_module_instance = EncryptionModule(base_url, odoo_auth) - application_id = "REGISTRATION" - reference_id = "string" - - def encrypt_field(field_value): - encoded_field_value = base64.b64encode(field_value.encode()).decode() - encrypted_data = encryption_module_instance.encrypt_data( - { - "applicationId": application_id, - "referenceId": reference_id, - "data": encoded_field_value, - } - ) - return encrypted_data + @api.model + def gather_fields_to_be_enc_from_dict( + self, + fields_dict: dict, + replace=True, + ): + to_be_enc = {} + for each in self.fields_list_to_enc: + if fields_dict.get(each, None): + to_be_enc[each] = fields_dict[each] + if replace: + fields_dict[each] = self.placeholder_to_encrypted_field + return to_be_enc + + def create(self, vals_list): + prov = self.env["g2p.encryption.provider"].get_registry_provider() + is_encrypt_fields = ( + self.env["ir.config_parameter"] + .sudo() + .get_param("g2p_registry_encryption.encrypt_registry", default=False) + ) + for vals in vals_list: + if is_encrypt_fields and (vals.get("is_registrant", False)): + to_be_encrypted = self.gather_fields_to_be_enc_from_dict(vals) + vals["encrypted_val"] = prov.encrypt_data( + json.dumps(to_be_encrypted).encode() + ) + vals["is_encrypted"] = True + + return super().create(vals_list) + + def write(self, vals_list): + prov = self.env["g2p.encryption.provider"].get_registry_provider() + is_encrypt_fields = ( + self.env["ir.config_parameter"] + .sudo() + .get_param("g2p_registry_encryption.encrypt_registry", default=False) + ) + rec_values_list = self.read(self.fields_list_to_enc + "is_registrant") + for rec, vals in zip(rec_values_list, vals_list): + if is_encrypt_fields and ( + rec.get("is_registrant", False) or vals.get("is_registrant", False) + ): + vals = rec.update(vals) + to_be_encrypted = self.gather_fields_to_be_enc_from_dict(vals) - vals["is_encrypted"] = bool(vals.get("name")) - vals["encrypted_val"] = encrypt_field(vals) - if "name" in vals: - vals["name"] = "encrypted" - if "family_name" in vals: - vals["family_name"] = "encrypted" - if "given_name" in vals: - vals["given_name"] = "encrypted" - if "addl_name" in vals: - vals["addl_name"] = "encrypted" - if "display_name" in vals: - vals["display_name"] = "encrypted" - if "address" in vals: - vals["address"] = "encrypted" - if "birth_place" in vals: - vals["birth_place"] = "encrypted" + vals["encrypted_val"] = prov.encrypt_data( + json.dumps(to_be_encrypted).encode() + ) + vals["is_encrypted"] = True - result = super(EncryptedPartner, self).write(vals) - return result + return super().write(vals_list) def _read(self, fields): - odoo_token = { - "auth_url": "https://keycloak.dev.openg2p.net/realms/openg2p/protocol/openid-connect/token", - "auth_client_id": "openg2p-admin-client", - "auth_client_secret": "x75SU2hqKQX7IPob", - "auth_grant_type": "client_credentials", - } - - odoo_auth = OdooAuth(**odoo_token) - base_url = "https://dev.openg2p.net/v1/keymanager" - encryption_module_instance = EncryptionModule(base_url, odoo_auth) - application_id = "REGISTRATION" - reference_id = "" - - def decrypt_field(field_value): - decrypted_data = encryption_module_instance.decrypt_data( - { - "applicationId": application_id, - "referenceId": reference_id, - "data": field_value, - } - ) - while decrypted_data and len(decrypted_data) % 4 != 0: - decrypted_data += "=" - if field_value and not decrypted_data: - return field_value - decoded_value = base64.b64decode(decrypted_data).decode("utf-8") - - return decoded_value - - is_decrypt_fields_enabled = self.env["ir.config_parameter"].get_param( - "g2p_registry.decrypt_fields", default=False + res = super()._read(fields) + prov = self.env["g2p.encryption.provider"].get_registry_provider() + is_decrypt_fields = ( + self.env["ir.config_parameter"] + .sudo() + .get_param("g2p_registry_encryption.decrypt_registry", default=False) ) - super(EncryptedPartner, self)._read(fields) for record in self: - if is_decrypt_fields_enabled and record["is_encrypted"]: - d = decrypt_field(record["encrypted_val"]) - decrytt = json.loads(d) - # print(decrytt["name"]) - - if "name" in record and record["name"]: - self.env.cache.set(record, self._fields["name"], decrytt["name"]) - if "family_name" in record and record["family_name"]: - self.env.cache.set( - record, self._fields["family_name"], decrytt["family_name"] - ) - if "addl_name" in record and record["addl_name"]: - self.env.cache.set( - record, self._fields["addl_name"], decrytt["addl_name"] - ) - if "given_name" in record and record["given_name"]: - self.env.cache.set( - record, self._fields["given_name"], decrytt["given_name"] - ) - if "display_name" in record and record["name"]: - self.env.cache.set( - record, - self._fields["display_name"], - decrytt["name"], - ) - if "email" in record and record["email"]: - self.env.cache.set(record, self._fields["email"], decrytt["email"]) + if is_decrypt_fields and record.is_encrypted and record.encrypted_val: + decrypted_vals = json.loads( + prov.decrypt_data(record.encrypted_val).decode() + ) + + for field_name in self.fields_list_to_enc: + if field_name in record and record[field_name]: + self.env.cache.set( + record, self._fields[field_name], decrypted_vals[field_name] + ) + return res diff --git a/g2p_registry_encryption/models/payment_file_keymanager.py b/g2p_registry_encryption/models/payment_file_keymanager.py deleted file mode 100644 index 790e4cc..0000000 --- a/g2p_registry_encryption/models/payment_file_keymanager.py +++ /dev/null @@ -1,97 +0,0 @@ -# import uuid -# from datetime import datetime, timedelta -# from urllib.parse import urlparse - - -# import requests -# from odoo import api, fields, models - - -# class G2PCryptoKeySet(models.Model): -# _name = "g2p.crypto.key.set" -# _description = "G2P Crypto Key Set" - -# _order = "id desc" - - -# name = fields.Char(string="kid", required=True) - -# type = fields.Selection( -# [ -# ("rsa", "RSA"), -# ], -# default="rsa", -# ) - -# size = fields.Selection( -# [ -# ("2048", "2048"), -# ("3072", "3072"), -# ("4096", "4096"), -# ], -# default="2048", -# ) - -# priv_key = fields.Char(compute="_compute_priv_key", store=True) -# pub_cert = fields.Char(compute="_compute_pub_cert", store=True) - -# jwk = fields.Char(compute="_compute_jwk", store=True) - -# use = fields.Selection( -# [ -# ("sig", "Signature"), -# ("enc", "Encryption"), -# ], -# default="sig", -# ) -# status = fields.Selection( -# [ -# ("active", "Active"), -# ], -# default="active", -# ) - -# file_payment_manager_id = fields.Many2one( -# "g2p.program.payment.manager.file", ondelete="cascade" -# ) - -# _sql_constraints = [ -# ( -# "name_unique", -# "unique (name)", -# "Name/KID of the key set should be unique", -# ), -# ] -# @api.model -# def create(self, values): -# if not values.get("name", None): -# values["name"] = str(uuid.uuid4()) -# return super(G2PCryptoKeySet, self).create(values) - -# @api.depends("type", "size") -# def _compute_priv_key(self): -# for rec in self: -# if rec.type == "rsa": -# priv_key_data = self.get_encryption_public_key() -# rec.priv_key = priv_key_data.get("private_key") - -# @api.depends("priv_key") -# def _compute_pub_cert(self): -# for rec in self: -# if rec.type == "rsa": -# pub_key_data = self.get_signing_public_key() -# rec.pub_cert = pub_key_data.get("public_key") - -# def get_signing_public_key(self): -# url = f"{self.base_url}/tpmsigning/publickey" -# headers = {"Authorization": f"Bearer {self.api_key}"} - -# response = requests.post(url, headers=headers) -# return response.json() - -# def get_encryption_public_key(self): -# url = f"{self.base_url}/tpmencryption/publickey" -# headers = {"Authorization": f"Bearer {self.api_key}"} - -# response = requests.post(url, headers=headers) -# return response.json() diff --git a/g2p_registry_encryption/models/payment_file_qrcode_config.py b/g2p_registry_encryption/models/payment_file_qrcode_config.py deleted file mode 100644 index 7dbcf68..0000000 --- a/g2p_registry_encryption/models/payment_file_qrcode_config.py +++ /dev/null @@ -1,179 +0,0 @@ -# import base64 -# import json -# from io import BytesIO - -# import qrcode -# import qrcode.image.svg -# from barcode import Code128 # pylint: disable=[W7936] -# from jose import jwt # pylint: disable=[W7936] - -# from odoo import _, api, fields, models -# from odoo.exceptions import ValidationError - - -# class G2PPaymentFileQRCodeConfig(models.Model): -# _name = "g2p.payment.file.qrcode.config" -# _description = "Payment File Config" -# _order = "id asc" - -# name = fields.Char(required=True) - -# type = fields.Selection( -# [ -# ("qrcode", "QR code"), -# ("code-128-barcode", "Code 128 Barcode"), -# ] -# ) -# data_type = fields.Selection( -# [ -# ("string", "String"), -# ("json", "JSON"), -# ("jwt", "JWT"), -# # Not implemented -# # ("cwt", "CWT"), -# ] -# ) - -# qrcode_version = fields.Integer(default=None) -# qrcode_error_correct = fields.Selection( -# [ -# ("0", "ERROR_CORRECT_M"), -# ("1", "ERROR_CORRECT_L"), -# ("2", "ERROR_CORRECT_H"), -# ("3", "ERROR_CORRECT_Q"), -# ], -# default="0", -# ) -# qrcode_box_size = fields.Integer(default=10) -# qrcode_border = fields.Integer(default=4) - -# body_string = fields.Char(string="Body") - -# payment_config_id = fields.Many2one("g2p.payment.file.config", ondelete="cascade") - -# @api.constrains("type", "data_type") -# def _constrains_type_and_data_type(self): -# if self.type.endswith("barcode") and self.data_type not in ("string",): -# raise ValidationError( -# _( -# f"Barcode must be of data type String. Cannot be of type {self.data_type}" -# ) -# ) - -# def render_datas_and_store( -# self, -# res_model, -# res_ids, -# crypto_ket_set_id, -# res_id_field_in_qrcode_model=None, -# template_engine="inline_template", -# ): -# datas = self._render_data( -# self.data_type, -# self.body_string, -# res_model, -# res_ids, -# crypto_ket_set_id, -# template_engine=template_engine, -# ) -# create_vals = [] -# for res_id in datas: -# val = { -# "qrcode_config_id": self.id, -# "data": datas[res_id], -# } -# if res_id_field_in_qrcode_model: -# val[res_id_field_in_qrcode_model] = res_id -# create_vals.append(val) -# QrcodeFile = self.env["g2p.payment.file.qrcode"] -# return QrcodeFile.create(create_vals) - -# @api.model -# def _render_data( -# self, -# data_type, -# template_src, -# res_model, -# res_ids, -# key_set, -# template_engine="inline_template", -# ): -# RenderMixin = self.env["mail.render.mixin"] -# datas = RenderMixin._render_template( -# template_src, -# res_model, -# res_ids, -# engine=template_engine, -# ) -# if data_type == "string": -# pass -# elif data_type == "json": -# for res_id in res_ids: -# # the following should throw exception if not json -# json.loads(datas[res_id]) -# elif data_type == "jwt": -# kid = key_set.name -# priv_key = key_set.priv_key.encode() -# for res_id in res_ids: -# payload = json.loads(datas[res_id]) -# datas[res_id] = jwt.encode( -# payload, priv_key, algorithm="RS256", headers={"kid": kid} -# ) -# return datas - - -# class G2PPaymentFileQRCode(models.TransientModel): -# _name = "g2p.payment.file.qrcode" -# _description = "Payment File QR Code" -# _order = "id desc" - -# qrcode_config_id = fields.Many2one("g2p.payment.file.qrcode.config") - -# data = fields.Char() - -# content_base64 = fields.Char(compute="_compute_qrcode_content", store=False) -# content_htmlsafe = fields.Char(compute="_compute_qrcode_content", store=False) - -# payment_batch_id = fields.Many2one("g2p.payment.batch") -# payment_id = fields.Many2one("g2p.payment") - -# def _compute_qrcode_content(self): -# for rec in self: -# config = rec.qrcode_config_id -# if config.type == "code-128-barcode": -# rec._generate_code128_barcode() -# elif config.type == "qrcode": -# rec._generate_qrcode() - -# def _generate_code128_barcode(self): -# self.ensure_one() -# byte_buffer = BytesIO() -# Code128(self.data).write(byte_buffer) -# byte_buffer.seek(0) -# self.content_base64 = base64.b64encode(byte_buffer.read()).decode() -# self.content_htmlsafe = "data:image/svg+xml;base64," + self.content_base64 -# byte_buffer.close() - -# def _generate_qrcode(self): -# self.ensure_one() -# config = self.qrcode_config_id -# img = qrcode.make( -# data=self.data, -# version=config.qrcode_version if config.qrcode_version else None, -# error_correction=int(config.qrcode_error_correct), -# box_size=config.qrcode_box_size, -# border=config.qrcode_border, -# image_factory=qrcode.image.svg.SvgPathImage, -# ) -# byte_buffer = BytesIO() -# img.save(byte_buffer) -# byte_buffer.seek(0) -# self.content_base64 = base64.b64encode(byte_buffer.read()).decode() -# self.content_htmlsafe = "data:image/svg+xml;base64," + self.content_base64 -# byte_buffer.close() - -# def get_by_name(self, name: str): -# for rec in self: -# if rec.qrcode_config_id and rec.qrcode_config_id.name == name: -# return rec -# return None diff --git a/g2p_registry_encryption/models/payment_key_set.py b/g2p_registry_encryption/models/payment_key_set.py deleted file mode 100644 index 315f9be..0000000 --- a/g2p_registry_encryption/models/payment_key_set.py +++ /dev/null @@ -1,147 +0,0 @@ -# import base64 -# import json -# import uuid -# from datetime import datetime, timedelta -# from urllib.parse import urlparse - -# from cryptography import x509 -# from cryptography.hazmat.primitives import hashes, serialization -# from cryptography.hazmat.primitives.asymmetric import rsa -# from cryptography.x509.oid import NameOID -# from jose import constants, jwk # pylint: disable=[W7936] - -# from odoo import api, fields, models - - -# class G2PCryptoKeySet(models.Model): -# _name = "g2p.crypto.key.set" -# _description = "G2P Crypto Key Set" -# _order = "id desc" - -# name = fields.Char(string="kid", required=True) - -# type = fields.Selection( -# [ -# ("rsa", "RSA"), -# ], -# default="rsa", -# ) - -# size = fields.Selection( -# [ -# ("2048", "2048"), -# ("3072", "3072"), -# ("4096", "4096"), -# ], -# default="2048", -# ) - -# priv_key = fields.Char(compute="_compute_priv_key", store=True) -# pub_cert = fields.Char(compute="_compute_pub_cert", store=True) - -# jwk = fields.Char(compute="_compute_jwk", store=True) - -# use = fields.Selection( -# [ -# ("sig", "Signature"), -# ("enc", "Encryption"), -# ], -# default="sig", -# ) -# status = fields.Selection( -# [ -# ("active", "Active"), -# ], -# default="active", -# ) - -# file_payment_manager_id = fields.Many2one( -# "g2p.program.payment.manager.file", ondelete="cascade" -# ) - -# _sql_constraints = [ -# ( -# "name_unique", -# "unique (name)", -# "Name/KID of the key set should be unique", -# ), -# ] - -# @api.model -# def create(self, values): -# if not values.get("name", None): -# values["name"] = str(uuid.uuid4()) -# return super(G2PCryptoKeySet, self).create(values) - -# @api.depends("type", "size") -# def _compute_priv_key(self): -# for rec in self: -# if rec.type == "rsa": -# priv_key = rsa.generate_private_key(65537, int(rec.size)) -# rec.priv_key = priv_key.private_bytes( -# encoding=serialization.Encoding.PEM, -# format=serialization.PrivateFormat.PKCS8, -# # Hardcoding no encryption for now -# encryption_algorithm=serialization.NoEncryption(), -# ).decode() -# else: -# rec.priv_key = None - -# @api.depends("priv_key") -# def _compute_pub_cert(self): -# web_base_url = self.env["ir.config_parameter"].get_param("web.base.url") -# web_base_hostname = urlparse(web_base_url).netloc -# for rec in self: -# if rec.type == "rsa": -# priv_key = serialization.load_pem_private_key( -# data=rec.priv_key.encode(), -# password=None, -# ) -# pub_key = priv_key.public_key() -# sub_name = x509.Name( -# [x509.NameAttribute(NameOID.COMMON_NAME, web_base_hostname)] -# ) -# alt_names = [x509.DNSName(web_base_hostname)] -# san = x509.SubjectAlternativeName(alt_names) - -# utcnow = datetime.utcnow() -# # No signer as of now. -# # TODO: Add a common signer cert for openg2p, -# # which signs every newly created cert. -# # (Probably a oca/vault based implementation) -# cert = ( -# x509.CertificateBuilder() -# .subject_name(sub_name) -# .issuer_name(sub_name) -# .public_key(pub_key) -# .serial_number(1000) -# .not_valid_before(utcnow) -# .not_valid_after(utcnow + timedelta(days=10 * 365)) -# .add_extension(san, False) -# .sign(priv_key, hashes.SHA256()) -# ) -# rec.pub_cert = cert.public_bytes(encoding=serialization.Encoding.PEM) -# else: -# rec.pub_cert = None - -# @api.depends("pub_cert", "use") -# def _compute_jwk(self): -# for key_set in self: -# certificate = x509.load_pem_x509_certificate(key_set.pub_cert.encode()) -# cert_x5c = base64.b64encode( -# certificate.public_bytes(serialization.Encoding.DER) -# ).decode() -# pub_key = certificate.public_key() -# # TODO: For now hardcoding alogrithm -# pub_key_jwk = jwk.RSAKey( -# algorithm=constants.ALGORITHMS.RS256, -# key=pub_key.public_bytes( -# encoding=serialization.Encoding.PEM, -# format=serialization.PublicFormat.SubjectPublicKeyInfo, -# ).decode(), -# ).to_dict() -# pub_key_jwk["kid"] = key_set.name -# pub_key_jwk["use"] = key_set.use -# pub_key_jwk["x5c"] = [cert_x5c] -# key_set.jwk = json.dumps(pub_key_jwk) -# #a certificate contains public key but signed by private key diff --git a/g2p_registry_encryption/models/phone_number.py b/g2p_registry_encryption/models/phone_number.py deleted file mode 100644 index 7348da7..0000000 --- a/g2p_registry_encryption/models/phone_number.py +++ /dev/null @@ -1,41 +0,0 @@ -import logging - -from odoo import api, fields, models - -from odoo.addons.g2p_encryption.models.crypto import AESCipher - -_logger = logging.getLogger(__name__) - - -class EncryptedPhoneNumber(models.Model): - _inherit = "g2p.phone.number" - - phone_no_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("phone_no", "phone_no_decrypted"), - store=False, - ) - - @api.model - def create(self, vals): - record = super(EncryptedPhoneNumber, self).create(vals) - # TODO encryption key should be moved to a secret vault. - encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") - if encryption_key: - crypto = AESCipher(encryption_key) - record["phone_no"] = ( - crypto.encrypt(record["phone_no"]) if record["phone_no"] else None - ) - - return record - - def _decrypt_field(self, actual_field, decrypted_field): - # TODO encryption key should be moved to a secret vault. - encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") - if encryption_key: - crypto = AESCipher(encryption_key) - for rec in self: - if rec[actual_field]: - rec[decrypted_field] = crypto.decrypt(rec[actual_field]) - else: - rec[decrypted_field] = "" - _logger.info("%s , %s", decrypted_field, rec[decrypted_field]) diff --git a/g2p_registry_encryption/models/reg_ids.py b/g2p_registry_encryption/models/reg_ids.py deleted file mode 100644 index 9d1ce06..0000000 --- a/g2p_registry_encryption/models/reg_ids.py +++ /dev/null @@ -1,41 +0,0 @@ -import logging - -from odoo import api, fields, models - -from odoo.addons.g2p_encryption.models.crypto import AESCipher - -_logger = logging.getLogger(__name__) - - -class EncryptedRegID(models.Model): - _inherit = "g2p.reg.id" - - value_decrypted = fields.Char( - compute=lambda self: self._decrypt_field("value", "value_decrypted"), - store=False, - ) - - @api.model - def create(self, vals): - record = super(EncryptedRegID, self).create(vals) - # TODO encryption key should be moved to a secret vault. - encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") - if encryption_key: - crypto = AESCipher(encryption_key) - record["value"] = ( - crypto.encrypt(record["value"]) if record["value"] else None - ) - - return record - - def _decrypt_field(self, actual_field, decrypted_field): - # TODO encryption key should be moved to a secret vault. - encryption_key = self.env["ir.config_parameter"].get_param("g2p_enc_key", "") - if encryption_key: - crypto = AESCipher(encryption_key) - for rec in self: - if rec[actual_field]: - rec[decrypted_field] = crypto.decrypt(rec[actual_field]) - else: - rec[decrypted_field] = "" - _logger.info("%s , %s", decrypted_field, rec[decrypted_field]) diff --git a/g2p_registry_encryption/models/registry_config.py b/g2p_registry_encryption/models/registry_config.py deleted file mode 100644 index 8bdefb6..0000000 --- a/g2p_registry_encryption/models/registry_config.py +++ /dev/null @@ -1,25 +0,0 @@ -from odoo import api, fields, models - - -class RegistryConfigDecrypt(models.TransientModel): - - _inherit = "res.config.settings" - - decrypt_fields = fields.Boolean(default=False, store=True) - - def set_values(self): - res = super(RegistryConfigDecrypt, self).set_values() - params = self.env["ir.config_parameter"].sudo() - params.set_param("g2p_registry.decrypt_fields", self.decrypt_fields) - return res - - @api.model - def get_values(self): - res = super(RegistryConfigDecrypt, self).get_values() - params = self.env["ir.config_parameter"].sudo() - res.update( - decrypt_fields=params.get_param( - "g2p_registry.decrypt_fields", default=False - ), - ) - return res diff --git a/g2p_registry_encryption/models/res_config_settings.py b/g2p_registry_encryption/models/res_config_settings.py new file mode 100644 index 0000000..14df1e7 --- /dev/null +++ b/g2p_registry_encryption/models/res_config_settings.py @@ -0,0 +1,18 @@ +from odoo import fields, models + + +class RegistryEncryptConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + registry_encryption_provider = fields.Many2one( + "g2p.encryption.provider", + config_parameter="g2p_registry_encryption.encryption_provider_id", + ) + encrypt_registry = fields.Boolean( + config_parameter="g2p_registry_encryption.encrypt_registry" + ) + + # TODO: Change this to user context + decrypt_registry = fields.Boolean( + config_parameter="g2p_registry_encryption.decrypt_registry" + ) diff --git a/g2p_registry_encryption/security/security.xml b/g2p_registry_encryption/security/security.xml deleted file mode 100644 index 6a53fb3..0000000 --- a/g2p_registry_encryption/security/security.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - Crypto Admin - - - diff --git a/g2p_registry_encryption/static/description/index.html b/g2p_registry_encryption/static/description/index.html index 75d0a76..b5fcd08 100644 --- a/g2p_registry_encryption/static/description/index.html +++ b/g2p_registry_encryption/static/description/index.html @@ -3,18 +3,18 @@ - -G2P:Registry Encryption + +G2P Registry: Encryption