From ded9f494889c7fe06a12e1bc26e02f7f48c61cad Mon Sep 17 00:00:00 2001
From: Christian Boettcher <c.boettcher@fz-juelich.de>
Date: Fri, 12 Nov 2021 14:51:45 +0100
Subject: [PATCH] encrypt and decrypt secret values when accessing them

---
 .../EncryptedJsonFileStorageAdapter.py        | 41 +++++++++++++++++++
 apiserver/storage/__init__.py                 |  4 +-
 requirements.txt                              |  1 +
 3 files changed, 45 insertions(+), 1 deletion(-)
 create mode 100644 apiserver/storage/EncryptedJsonFileStorageAdapter.py

diff --git a/apiserver/storage/EncryptedJsonFileStorageAdapter.py b/apiserver/storage/EncryptedJsonFileStorageAdapter.py
new file mode 100644
index 0000000..12cfcc6
--- /dev/null
+++ b/apiserver/storage/EncryptedJsonFileStorageAdapter.py
@@ -0,0 +1,41 @@
+from fastapi.exceptions import HTTPException
+from JsonFileStorageAdapter import JsonFileStorageAdapter, LocationDataType
+from cryptography.fernet import Fernet
+
+from apiserver.config.settings import ApiserverSettings
+
+class EncryptedJsonFileStorageAdapter(JsonFileStorageAdapter):
+
+    def encrypt(self, string: str):
+        f = Fernet(self.encryption_key)
+        return f.encrypt(string.encode())
+
+    def decrypt(self, string: str):
+        f = Fernet(self.encryption_key)
+        return f.decrypt(string.encode())
+    
+    def __init__(self, settings: ApiserverSettings, encryption_key) -> None:
+        self.encryption_key = encryption_key
+        super().__init__(settings)
+    
+    
+    def get_secret_values(self, n_type: LocationDataType, oid:str, usr: str):
+        """ get all available secrets (key + value) for this object"""
+        encrypted_dict = super().get_secret_values(n_type, oid, usr)
+        decrypted_dict = {}
+        for key in encrypted_dict:
+            decrypted_dict[key] = self.decrypt(encrypted_dict[key])
+        return decrypted_dict
+
+    def add_update_secret(self, n_type: LocationDataType, oid:str, key: str, value: str, usr: str):
+        """ add new secrets to an existing object"""
+        super().add_update_secret(n_type, oid, key, self.encrypt(value), usr)
+
+    def get_secret(self, n_type: LocationDataType, oid:str, key: str, usr: str):
+        """ return the value of the requested secret for the given object"""
+        encrypted_secret = super().get_secret(n_type, oid, key, usr)
+        return self.decrypt(encrypted_secret)
+
+    def delete_secret(self, n_type: LocationDataType, oid:str, key: str, usr: str):
+        """ delete and return the value of the requested secret for the given object"""
+        return self.decrypt(super().delete_secret(n_type, oid, key, usr))
\ No newline at end of file
diff --git a/apiserver/storage/__init__.py b/apiserver/storage/__init__.py
index 8c48a89..d14af4f 100644
--- a/apiserver/storage/__init__.py
+++ b/apiserver/storage/__init__.py
@@ -1,3 +1,5 @@
 from .JsonFileStorageAdapter import JsonFileStorageAdapter, verify_oid
 
-from .LocationStorage import LocationDataType, LocationData, AbstractLocationDataStorageAdapter
\ No newline at end of file
+from .LocationStorage import LocationDataType, LocationData, AbstractLocationDataStorageAdapter
+
+from .EncryptedJsonFileStorageAdapter import EncryptedJsonFileStorageAdapter
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 7415b00..cad50df 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,3 +6,4 @@ python-multipart==0.0.5
 python-jose[cryptography]==3.2.0
 passlib[bcrypt]==1.7.4
 jinja2==3.0.1
+cryptography
-- 
GitLab