Merge in RR/pyinfra from RED-6273-multi-tenant-storage to master
Squashed commit of the following:
commit 0fead1f8b59c9187330879b4e48d48355885c27c
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Tue Mar 28 15:02:22 2023 +0200
fix typos
commit 892a803726946876f8b8cd7905a0e73c419b2fb1
Author: Matthias Bisping <matthias.bisping@axbit.com>
Date: Tue Mar 28 14:41:49 2023 +0200
Refactoring
Replace custom storage caching logic with LRU decorator
commit eafcd90260731e3360ce960571f07dee8f521327
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Fri Mar 24 12:50:13 2023 +0100
fix bug in storage connection from endpoint
commit d0c9fb5b7d1c55ae2f90e8faa1efec9f7587c26a
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Fri Mar 24 11:49:34 2023 +0100
add logs to PayloadProcessor
- set log messages to determine if x-tenant
storage connection is working
commit 97309fe58037b90469cf7a3de342d4749a0edfde
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Fri Mar 24 10:41:59 2023 +0100
update PayloadProcessor
- introduce storage cache to make every unique
storage connection only once
- add functionality to pass optional processing
kwargs in queue message like the operation key to
the processing function
commit d48e8108fdc0d463c89aaa0d672061ab7dca83a0
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Wed Mar 22 13:34:43 2023 +0100
add multi-tenant storage connection 1st iteration
- forward x-tenant-id from queue message header to
payload processor
- add functions to receive storage infos from an
endpoint or the config. This enables hashing and
caching of connections created from these infos
- add function to initialize storage connections
from storage infos
- streamline and refactor tests to make them more
readable and robust and to make it easier to add
new tests
- update payload processor with first iteration
of multi tenancy storage connection support
with connection caching and backwards compability
commit 52c047c47b98e62d0b834a9b9b6c0e2bb0db41e5
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Tue Mar 21 15:35:57 2023 +0100
add AES/GCM cipher functions
- decrypt x-tenant storage connection strings
50 lines
2.0 KiB
Python
50 lines
2.0 KiB
Python
import base64
|
|
import os
|
|
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
|
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
|
|
|
|
def build_aes_gcm_cipher(public_key, iv=None):
|
|
encoded_key = public_key.encode("utf-8")
|
|
kdf = PBKDF2HMAC(
|
|
algorithm=hashes.SHA1(),
|
|
length=16,
|
|
salt=iv,
|
|
iterations=65536,
|
|
)
|
|
private_key = kdf.derive(encoded_key)
|
|
return AESGCM(private_key)
|
|
|
|
|
|
def encrypt(public_key: str, plaintext: str, iv: int = None) -> str:
|
|
"""Encrypt a text with AES/GCS using a public key.
|
|
|
|
The byte-converted ciphertext consists of an unsigned 32-bit integer big-endian byteorder header i.e. the first 4
|
|
bytes, specifying the length of the following initialization vector (iv). The rest of the text contains the
|
|
encrypted message.
|
|
"""
|
|
iv = iv or os.urandom(12)
|
|
plaintext_bytes = plaintext.encode("utf-8")
|
|
cipher = build_aes_gcm_cipher(public_key, iv)
|
|
header = len(iv).to_bytes(length=4, byteorder="big")
|
|
encrypted = header + iv + cipher.encrypt(nonce=iv, data=plaintext_bytes, associated_data=None)
|
|
return base64.b64encode(encrypted).decode("utf-8")
|
|
|
|
|
|
def decrypt(public_key: str, ciphertext: str) -> str:
|
|
"""Decrypt an AES/GCS encrypted text with a public key.
|
|
|
|
The byte-converted ciphertext consists of an unsigned 32-bit integer big-endian byteorder header i.e. the first 4
|
|
bytes, specifying the length of the following initialization vector (iv). The rest of the text contains the
|
|
encrypted message.
|
|
"""
|
|
ciphertext_bytes = base64.b64decode(ciphertext)
|
|
header, rest = ciphertext_bytes[:4], ciphertext_bytes[4:]
|
|
iv_length = int.from_bytes(header, "big")
|
|
iv, ciphertext_bytes = rest[:iv_length], rest[iv_length:]
|
|
cipher = build_aes_gcm_cipher(public_key, iv)
|
|
decrypted_text = cipher.decrypt(nonce=iv, data=ciphertext_bytes, associated_data=None)
|
|
return decrypted_text.decode("utf-8")
|