fdc-shared-kernel 0.0.3__tar.gz → 0.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/PKG-INFO +8 -35
  2. fdc_shared_kernel-0.0.5/README_pypi.md +99 -0
  3. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/pyproject.toml +3 -2
  4. fdc_shared_kernel-0.0.3/src/fdc_shared_kernel.egg-info/requires.txt → fdc_shared_kernel-0.0.5/requirements.txt +4 -0
  5. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/fdc_shared_kernel.egg-info/PKG-INFO +8 -35
  6. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/fdc_shared_kernel.egg-info/SOURCES.txt +6 -1
  7. fdc_shared_kernel-0.0.3/requirements.txt → fdc_shared_kernel-0.0.5/src/fdc_shared_kernel.egg-info/requires.txt +5 -1
  8. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/config/__init__.py +4 -4
  9. fdc_shared_kernel-0.0.5/src/shared_kernel/interfaces/__init__.py +2 -0
  10. fdc_shared_kernel-0.0.5/src/shared_kernel/interfaces/keyvault.py +29 -0
  11. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/messaging/nats_databus.py +11 -9
  12. fdc_shared_kernel-0.0.5/src/shared_kernel/security/__init__.py +1 -0
  13. fdc_shared_kernel-0.0.5/src/shared_kernel/security/key_vault/__init__.py +14 -0
  14. fdc_shared_kernel-0.0.5/src/shared_kernel/security/key_vault/aws_secret_manager.py +98 -0
  15. fdc_shared_kernel-0.0.5/src/shared_kernel/security/key_vault/azure_keyvault.py +67 -0
  16. fdc_shared_kernel-0.0.5/src/shared_kernel/tests/config/test_config.py +35 -0
  17. fdc_shared_kernel-0.0.5/src/shared_kernel/tests/logger/test_logger.py +48 -0
  18. fdc_shared_kernel-0.0.5/src/shared_kernel/tests/messaging/test_nats_interface.py +40 -0
  19. fdc_shared_kernel-0.0.3/src/shared_kernel/tests/__init__.py +0 -0
  20. fdc_shared_kernel-0.0.3/src/shared_kernel/tests/config/test_config.py +0 -35
  21. fdc_shared_kernel-0.0.3/src/shared_kernel/tests/logger/test_logger.py +0 -48
  22. fdc_shared_kernel-0.0.3/src/shared_kernel/tests/messaging/test_nats_interface.py +0 -36
  23. fdc_shared_kernel-0.0.3/src/shared_kernel/tests/utils/utils.py +0 -618
  24. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/README.md +0 -0
  25. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/setup.cfg +0 -0
  26. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/fdc_shared_kernel.egg-info/dependency_links.txt +0 -0
  27. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/fdc_shared_kernel.egg-info/top_level.txt +0 -0
  28. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/__init__.py +0 -0
  29. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/database/__init__.py +0 -0
  30. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/exceptions/__init__.py +0 -0
  31. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/exceptions/configuration_exceptions.py +0 -0
  32. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/exceptions/custom_exceptions.py +0 -0
  33. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/exceptions/data_validation_exceptions.py +0 -0
  34. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/exceptions/http_exceptions.py +0 -0
  35. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/exceptions/infrastructure_exceptions.py +0 -0
  36. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/exceptions/operational_exceptions.py +0 -0
  37. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/exceptions/security_exceptions.py +0 -0
  38. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/interfaces/databus.py +0 -0
  39. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/logger/__init__.py +0 -0
  40. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/messaging/__init__.py +0 -0
  41. {fdc_shared_kernel-0.0.3/src/shared_kernel/interfaces → fdc_shared_kernel-0.0.5/src/shared_kernel/models}/__init__.py +0 -0
  42. {fdc_shared_kernel-0.0.3/src/shared_kernel/models → fdc_shared_kernel-0.0.5/src/shared_kernel/tests}/__init__.py +0 -0
  43. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/tests/utils/test_data_validators.py +0 -0
  44. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/tests/utils/test_date_format_utils.py +0 -0
  45. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/tests/utils/test_string_utils.py +0 -0
  46. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/utils/__init__.py +0 -0
  47. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/utils/data_validators_utils.py +0 -0
  48. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/utils/date_format_utils.py +0 -0
  49. {fdc_shared_kernel-0.0.3 → fdc_shared_kernel-0.0.5}/src/shared_kernel/utils/string_utils.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fdc_shared_kernel
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: Shared library for microservice
5
- Author-email: Shikhil S <shikhil.s@dbizsolution.com>
5
+ Author-email: Shikhil S <shikhil.s@dbizsolution.com>, Ahammed Akdham N <ahammedakdham.n@dbizsolution.com>
6
6
  Classifier: Programming Language :: Python :: 3
7
7
  Classifier: License :: OSI Approved :: MIT License
8
8
  Classifier: Operating System :: OS Independent
@@ -26,8 +26,12 @@ Requires-Dist: python-dotenv==1.0.1
26
26
  Requires-Dist: setuptools==71.0.0
27
27
  Requires-Dist: SQLAlchemy==2.0.31
28
28
  Requires-Dist: typing_extensions==4.12.2
29
+ Requires-Dist: boto3==1.34.148
30
+ Requires-Dist: boto3==1.34.148
31
+ Requires-Dist: azure-keyvault-secrets==4.8.0
32
+ Requires-Dist: azure-identity==1.17.1
29
33
 
30
- # Shared Kernel
34
+ # FDC Shared Kernel
31
35
 
32
36
  Shared Kernel is a lightweight, modular Python library designed to facilitate rapid development of microservices. It provides essential utilities for data manipulation, logging, configuration management, and database connectivity, making it an ideal foundation for building scalable and maintainable microservices.
33
37
 
@@ -53,40 +57,9 @@ Shared Kernel is a lightweight, modular Python library designed to facilitate ra
53
57
  To install Shared Kernel, clone the repository and install it using pip:
54
58
 
55
59
  ```sh
56
- git clone https://bitbucket.org/Weavers/shared-kernel.git
57
- cd shared-kernel pip install .
60
+ pip install fdc-shared-kernel
58
61
  ```
59
62
 
60
- ##### Step 1: Set Up Your Environment
61
- First, ensure you have Python installed on your system. Then, set up a virtual environment for your project to manage dependencies cleanly. Open your terminal and navigate to your project directory:
62
-
63
- ```sh
64
- cd path/to/shared-kernel
65
- python -m venv venv
66
- source venv/bin/activate # On Windows, use `venv\Scripts\activate`
67
- ```
68
-
69
- ##### Step 2: Install Python build frontend.
70
- Ensure you python's build frontend. installed in your environment. This is necessary for building the wheel package from **.toml** file. You can install them using pip:
71
- ```sh
72
- pip install --upgrade build
73
- ```
74
-
75
- ##### Step 3: Build the Wheel Package
76
- ```sh
77
- python -m build
78
- ```
79
- This command will build a wheel distribution and also a source distribution. After running this command, you'll find the .whl and a tar file inside the dist/ directory within your project folder.
80
-
81
-
82
- ##### Step 4: Distribute the Wheel
83
- Now that you have a .whl file, you can distribute it to others. Users can install your library using pip by pointing to the .whl file:
84
-
85
- ```sh
86
- pip install dist/shared_kernel-0.1.0-py3-none-any.whl
87
- ```
88
-
89
-
90
63
  ## Usage
91
64
 
92
65
  ### Importing Modules
@@ -0,0 +1,99 @@
1
+ # FDC Shared Kernel
2
+
3
+ Shared Kernel is a lightweight, modular Python library designed to facilitate rapid development of microservices. It provides essential utilities for data manipulation, logging, configuration management, and database connectivity, making it an ideal foundation for building scalable and maintainable microservices.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Getting Started](#getting-started)
8
+ - [Prerequisites](#prerequisites)
9
+ - [Installation](#installation)
10
+ - [Usage](#usage)
11
+ - [Importing Modules](#importing-modules)
12
+ - [Initializing Database Connection](#initializing-database-connection)
13
+
14
+
15
+ ## Getting Started
16
+
17
+ ### Prerequisites
18
+
19
+ - Python 3.6+
20
+ - Pip
21
+
22
+ ### Installation
23
+
24
+ To install Shared Kernel, clone the repository and install it using pip:
25
+
26
+ ```sh
27
+ pip install fdc-shared-kernel
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Importing Modules
33
+
34
+ Import the required modules from Shared Kernel into your project:
35
+
36
+ ```
37
+ from shared_kernel.logger import Logger
38
+ from shared_kernel.config import Config
39
+ from dotenv import find_dotenv
40
+
41
+
42
+ def main():
43
+ logger = Logger(name="my_app")
44
+ logger.configure_logger()
45
+
46
+ # Specify the path to the .env file if it's not in the current directory
47
+ config_manager = Config(env_path=find_dotenv())
48
+
49
+ # Access environment variables
50
+ api_key = config_manager.get("KEY", "default_api_key")
51
+
52
+ # Example usage
53
+ logger.logger.info("This is an info message.")
54
+ logger.logger.error("This is an error message.")
55
+ logger.logger.info(api_key)
56
+
57
+
58
+ if __name__ == "__main__":
59
+ main()
60
+
61
+ ```
62
+
63
+
64
+ ### Initializing Database Connection
65
+
66
+ Use the `DB` class to initialize a database connection:
67
+
68
+ ```
69
+ from shared_kernel.DB import DB
70
+
71
+ db_instance = DB("postgresql://user:password@localhost/dbname")
72
+ engine, SessionLocal = db_instance.init_db_connection()
73
+
74
+ ```
75
+
76
+
77
+
78
+
79
+ ### Initializing NATS Connection
80
+
81
+ Use the `NATSClient` class to initialize a messaging connection:
82
+
83
+ ```
84
+ from shared_kernel.messaging import NATSClient
85
+ import asyncio
86
+
87
+ def run():
88
+ nats_instance = NATSClient("nats://localhost:4222")
89
+ await nc_interface.connect()
90
+
91
+ async def message_callback(data):
92
+ print(f"Received a message: {data}")
93
+
94
+ await nc_interface.subscribe("example_subject", message_callback)
95
+ await nc_interface.publish("example_subject", "Hello NATS!")
96
+
97
+ if __name__ == '__main__':
98
+ asyncio.run(run())
99
+ ```
@@ -4,12 +4,13 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fdc_shared_kernel"
7
- version = "0.0.3"
7
+ version = "0.0.5"
8
8
  requires-python = ">=3.7"
9
- readme = "README.md"
9
+ readme = "README_pypi.md"
10
10
  description = "Shared library for microservice"
11
11
  authors = [
12
12
  {name="Shikhil S", email="shikhil.s@dbizsolution.com"},
13
+ {name="Ahammed Akdham N", email="ahammedakdham.n@dbizsolution.com"},
13
14
  ]
14
15
  classifiers = [
15
16
  "Programming Language :: Python :: 3",
@@ -16,3 +16,7 @@ python-dotenv==1.0.1
16
16
  setuptools==71.0.0
17
17
  SQLAlchemy==2.0.31
18
18
  typing_extensions==4.12.2
19
+ boto3==1.34.148
20
+ boto3==1.34.148
21
+ azure-keyvault-secrets==4.8.0
22
+ azure-identity==1.17.1
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fdc_shared_kernel
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: Shared library for microservice
5
- Author-email: Shikhil S <shikhil.s@dbizsolution.com>
5
+ Author-email: Shikhil S <shikhil.s@dbizsolution.com>, Ahammed Akdham N <ahammedakdham.n@dbizsolution.com>
6
6
  Classifier: Programming Language :: Python :: 3
7
7
  Classifier: License :: OSI Approved :: MIT License
8
8
  Classifier: Operating System :: OS Independent
@@ -26,8 +26,12 @@ Requires-Dist: python-dotenv==1.0.1
26
26
  Requires-Dist: setuptools==71.0.0
27
27
  Requires-Dist: SQLAlchemy==2.0.31
28
28
  Requires-Dist: typing_extensions==4.12.2
29
+ Requires-Dist: boto3==1.34.148
30
+ Requires-Dist: boto3==1.34.148
31
+ Requires-Dist: azure-keyvault-secrets==4.8.0
32
+ Requires-Dist: azure-identity==1.17.1
29
33
 
30
- # Shared Kernel
34
+ # FDC Shared Kernel
31
35
 
32
36
  Shared Kernel is a lightweight, modular Python library designed to facilitate rapid development of microservices. It provides essential utilities for data manipulation, logging, configuration management, and database connectivity, making it an ideal foundation for building scalable and maintainable microservices.
33
37
 
@@ -53,40 +57,9 @@ Shared Kernel is a lightweight, modular Python library designed to facilitate ra
53
57
  To install Shared Kernel, clone the repository and install it using pip:
54
58
 
55
59
  ```sh
56
- git clone https://bitbucket.org/Weavers/shared-kernel.git
57
- cd shared-kernel pip install .
60
+ pip install fdc-shared-kernel
58
61
  ```
59
62
 
60
- ##### Step 1: Set Up Your Environment
61
- First, ensure you have Python installed on your system. Then, set up a virtual environment for your project to manage dependencies cleanly. Open your terminal and navigate to your project directory:
62
-
63
- ```sh
64
- cd path/to/shared-kernel
65
- python -m venv venv
66
- source venv/bin/activate # On Windows, use `venv\Scripts\activate`
67
- ```
68
-
69
- ##### Step 2: Install Python build frontend.
70
- Ensure you python's build frontend. installed in your environment. This is necessary for building the wheel package from **.toml** file. You can install them using pip:
71
- ```sh
72
- pip install --upgrade build
73
- ```
74
-
75
- ##### Step 3: Build the Wheel Package
76
- ```sh
77
- python -m build
78
- ```
79
- This command will build a wheel distribution and also a source distribution. After running this command, you'll find the .whl and a tar file inside the dist/ directory within your project folder.
80
-
81
-
82
- ##### Step 4: Distribute the Wheel
83
- Now that you have a .whl file, you can distribute it to others. Users can install your library using pip by pointing to the .whl file:
84
-
85
- ```sh
86
- pip install dist/shared_kernel-0.1.0-py3-none-any.whl
87
- ```
88
-
89
-
90
63
  ## Usage
91
64
 
92
65
  ### Importing Modules
@@ -1,4 +1,5 @@
1
1
  README.md
2
+ README_pypi.md
2
3
  pyproject.toml
3
4
  requirements.txt
4
5
  src/fdc_shared_kernel.egg-info/PKG-INFO
@@ -19,10 +20,15 @@ src/shared_kernel/exceptions/operational_exceptions.py
19
20
  src/shared_kernel/exceptions/security_exceptions.py
20
21
  src/shared_kernel/interfaces/__init__.py
21
22
  src/shared_kernel/interfaces/databus.py
23
+ src/shared_kernel/interfaces/keyvault.py
22
24
  src/shared_kernel/logger/__init__.py
23
25
  src/shared_kernel/messaging/__init__.py
24
26
  src/shared_kernel/messaging/nats_databus.py
25
27
  src/shared_kernel/models/__init__.py
28
+ src/shared_kernel/security/__init__.py
29
+ src/shared_kernel/security/key_vault/__init__.py
30
+ src/shared_kernel/security/key_vault/aws_secret_manager.py
31
+ src/shared_kernel/security/key_vault/azure_keyvault.py
26
32
  src/shared_kernel/tests/__init__.py
27
33
  src/shared_kernel/tests/config/test_config.py
28
34
  src/shared_kernel/tests/logger/test_logger.py
@@ -30,7 +36,6 @@ src/shared_kernel/tests/messaging/test_nats_interface.py
30
36
  src/shared_kernel/tests/utils/test_data_validators.py
31
37
  src/shared_kernel/tests/utils/test_date_format_utils.py
32
38
  src/shared_kernel/tests/utils/test_string_utils.py
33
- src/shared_kernel/tests/utils/utils.py
34
39
  src/shared_kernel/utils/__init__.py
35
40
  src/shared_kernel/utils/data_validators_utils.py
36
41
  src/shared_kernel/utils/date_format_utils.py
@@ -15,4 +15,8 @@ pytest-asyncio==0.23.8
15
15
  python-dotenv==1.0.1
16
16
  setuptools==71.0.0
17
17
  SQLAlchemy==2.0.31
18
- typing_extensions==4.12.2
18
+ typing_extensions==4.12.2
19
+ boto3==1.34.148
20
+ boto3==1.34.148
21
+ azure-keyvault-secrets==4.8.0
22
+ azure-identity==1.17.1
@@ -2,9 +2,9 @@ import os
2
2
  from typing import Any
3
3
  from dotenv import load_dotenv, find_dotenv
4
4
  from shared_kernel.exceptions import MissingConfiguration, InvalidConfiguration
5
- import logging
5
+ from src.shared_kernel.logger import Logger
6
6
 
7
- logging.basicConfig(level=logging.INFO)
7
+ logger = Logger('SHARED_KERNEL')
8
8
 
9
9
 
10
10
  class Config:
@@ -26,12 +26,12 @@ class Config:
26
26
  if env_path is None:
27
27
  dotenv_path = find_dotenv()
28
28
  if not dotenv_path:
29
- logging.error(".env file not found")
29
+ logger.error(".env file not found")
30
30
  raise InvalidConfiguration(".env file not found")
31
31
  else:
32
32
  dotenv_path = env_path
33
33
 
34
- logging.info(f"Loading environment variables from {dotenv_path}")
34
+ logger.info(f"Loading environment variables from {dotenv_path}")
35
35
  load_dotenv(dotenv_path)
36
36
 
37
37
  @staticmethod
@@ -0,0 +1,2 @@
1
+ from src.shared_kernel.interfaces.databus import *
2
+ from src.shared_kernel.interfaces.keyvault import *
@@ -0,0 +1,29 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class KeyVaultInterface(ABC):
5
+
6
+ @abstractmethod
7
+ def __init__(self, config: dict):
8
+ """Initialize the key vault connection with the given configuration dictionary."""
9
+ pass
10
+
11
+ @abstractmethod
12
+ def store_secret(self, name: str, secret: str) -> None:
13
+ """Store a secret in the key vault."""
14
+ pass
15
+
16
+ @abstractmethod
17
+ def retrieve_secret(self, name: str) -> str:
18
+ """Retrieve a secret from the key vault."""
19
+ pass
20
+
21
+ @abstractmethod
22
+ def delete_secret(self, name: str) -> None:
23
+ """Delete a secret from the key vault."""
24
+ pass
25
+
26
+ @abstractmethod
27
+ def list_secrets(self) -> list:
28
+ """List all secrets in the key vault."""
29
+ pass
@@ -1,11 +1,12 @@
1
1
  import json
2
- import logging
3
2
  from nats.aio.client import Client as NATS
4
3
  from nats.js.api import ConsumerConfig, DeliverPolicy, StreamConfig
5
4
  from typing import Callable, Any, List, Union
5
+ from src.shared_kernel.interfaces import DataBus
6
+ from src.shared_kernel.logger import Logger
6
7
 
7
8
 
8
- class NATSDataBus:
9
+ class NATSDataBus(DataBus):
9
10
  """
10
11
  A NATS Interface class to handle both standard NATS and JetStream operations.
11
12
  """
@@ -31,6 +32,7 @@ class NATSDataBus:
31
32
  self.connected = False
32
33
  self.js = None # JetStream context
33
34
  self.initialized = True
35
+ self.logger = Logger('SHARED_KERNEL')
34
36
 
35
37
  async def make_connection(self):
36
38
  """
@@ -88,12 +90,12 @@ class NATSDataBus:
88
90
  ack = await self.js.publish(
89
91
  topic, json.dumps(event_payload).encode("utf-8")
90
92
  )
91
- logging.info(
93
+ self.logger.info(
92
94
  f"Published event '{event_payload.get('event_name')}' to topic '{topic}', ack: {ack}"
93
95
  )
94
96
  return True
95
97
  except Exception as e:
96
- logging.error(
98
+ self.logger.error(
97
99
  f"Failed to publish event '{event_payload.get('event_name')}': {str(e)}",
98
100
  exc_info=True,
99
101
  )
@@ -119,7 +121,7 @@ class NATSDataBus:
119
121
  )
120
122
  return json.loads(response.data.decode("utf-8"))
121
123
  except Exception as e:
122
- logging.error(f"Failed to request topic '{topic}': {e}", exc_info=True)
124
+ self.logger.error(f"Failed to request topic '{topic}': {e}", exc_info=True)
123
125
  raise e
124
126
 
125
127
  async def subscribe_async_event(
@@ -142,10 +144,10 @@ class NATSDataBus:
142
144
  )
143
145
 
144
146
  await self.js.subscribe(topic, cb=callback, config=consumer_config)
145
- logging.info(f"Subscribed to async event on topic '{topic}'")
147
+ self.logger.info(f"Subscribed to async event on topic '{topic}'")
146
148
 
147
149
  except Exception as e:
148
- logging.error(
150
+ self.logger.error(
149
151
  f"Failed to subscribe to async event on topic '{topic}': {e}",
150
152
  exc_info=True,
151
153
  )
@@ -161,10 +163,10 @@ class NATSDataBus:
161
163
  """
162
164
  try:
163
165
  await self.nc.subscribe(topic, cb=callback)
164
- logging.info(f"Subscribed to sync event on topic '{topic}'")
166
+ self.logger.info(f"Subscribed to sync event on topic '{topic}'")
165
167
 
166
168
  except Exception as e:
167
- logging.error(
169
+ self.logger.error(
168
170
  f"Failed to subscribe to sync event on topic '{topic}': {e}",
169
171
  exc_info=True,
170
172
  )
@@ -0,0 +1 @@
1
+ from src.shared_kernel.security.key_vault import *
@@ -0,0 +1,14 @@
1
+ from src.shared_kernel.interfaces import KeyVaultInterface
2
+ from src.shared_kernel.security.key_vault.aws_secret_manager import AWSSecretsManager
3
+ from src.shared_kernel.security.key_vault.azure_keyvault import AzureKeyVault
4
+
5
+
6
+ class KeyVaultFactory:
7
+ @staticmethod
8
+ def create_key_vault(vault_type: str, config: dict) -> KeyVaultInterface:
9
+ if vault_type == 'AZURE':
10
+ return AzureKeyVault(config)
11
+ elif vault_type == 'AWS':
12
+ return AWSSecretsManager(config)
13
+ else:
14
+ raise ValueError(f"Unknown vault type: {vault_type}")
@@ -0,0 +1,98 @@
1
+ import boto3
2
+ from botocore.exceptions import ClientError
3
+ from src.shared_kernel.interfaces import KeyVaultInterface
4
+ from src.shared_kernel.logger import Logger
5
+
6
+
7
+ class AWSSecretsManager(KeyVaultInterface):
8
+ def __init__(self, config: dict):
9
+ """
10
+ Initialize the AWS Secrets Manager connection with the given configuration.
11
+
12
+ Args:
13
+ config (dict): Configuration dictionary containing region_name, aws_access_key_id, _aws_secret_access_key
14
+ """
15
+ self._region_name = config.get('region_name')
16
+ self._aws_access_key_id = config.get('AWS_SERVER_PUBLIC_KEY')
17
+ self._aws_secret_access_key = config.get('AWS_SERVER_SECRET_KEY')
18
+ self._client = boto3.client('secretsmanager',
19
+ aws_access_key_id=self._aws_access_key_id,
20
+ aws_secret_access_key=self._aws_secret_access_key,
21
+ region_name=self._region_name)
22
+ self.logger = Logger('SHARED_KERNEL')
23
+ self.logger.info(f"Connected to AWS Secrets Manager in region: {self._region_name}")
24
+
25
+ def store_secret(self, name: str, secret: str) -> None:
26
+ """
27
+ Store a secret in AWS Secrets Manager.
28
+
29
+ Args:
30
+ name (str): The name of the secret.
31
+ secret (str): The value of the secret.
32
+
33
+ Raises:
34
+ ClientError: If storing the secret fails.
35
+ """
36
+ try:
37
+ self._client.create_secret(Name=name, SecretString=secret)
38
+ self.logger.info(f"Stored secret '{name}'")
39
+ except ClientError as e:
40
+ if e.response['Error']['Code'] == 'ResourceExistsException':
41
+ self._client.update_secret(SecretId=name, SecretString=secret)
42
+ self.logger.info(f"Updated secret '{name}'")
43
+ else:
44
+ self.logger.error(f"Failed to update secret '{name}' | Error: '{e}'")
45
+ raise e
46
+
47
+ def retrieve_secret(self, name: str) -> str:
48
+ """
49
+ Retrieve a secret from AWS Secrets Manager.
50
+
51
+ Args:
52
+ name (str): The name of the secret.
53
+
54
+ Returns:
55
+ str: The value of the retrieved secret, or None if retrieval fails.
56
+
57
+ Raises:
58
+ ClientError: If retrieving the secret fails.
59
+ """
60
+ try:
61
+ response = self._client.get_secret_value(SecretId=name)
62
+ return response['SecretString']
63
+ except ClientError as e:
64
+ self.logger.error(f"Error retrieving secret '{name}': {e}")
65
+ return None
66
+
67
+ def delete_secret(self, name: str) -> None:
68
+ """
69
+ Delete a secret from AWS Secrets Manager.
70
+
71
+ Args:
72
+ name (str): The name of the secret.
73
+
74
+ Raises:
75
+ ClientError: If deleting the secret fails.
76
+ """
77
+ try:
78
+ self._client.delete_secret(SecretId=name, ForceDeleteWithoutRecovery=True)
79
+ self.logger.info(f"Deleted secret '{name}'")
80
+ except ClientError as e:
81
+ self.logger.error(f"Error deleting secret '{name}': {e}")
82
+
83
+ def list_secrets(self) -> list:
84
+ """
85
+ List all secrets in AWS Secrets Manager.
86
+
87
+ Returns:
88
+ list: A list of secret names.
89
+
90
+ Raises:
91
+ ClientError: If listing the secrets fails.
92
+ """
93
+ try:
94
+ response = self._client.list_secrets()
95
+ return [secret['Name'] for secret in response['SecretList']]
96
+ except ClientError as e:
97
+ self.logger.error(f"Error listing secrets: {e}")
98
+ return []
@@ -0,0 +1,67 @@
1
+ from azure.identity import DefaultAzureCredential, ClientSecretCredential
2
+ from azure.keyvault.secrets import SecretClient
3
+ from src.shared_kernel.interfaces import KeyVaultInterface
4
+ from src.shared_kernel.logger import Logger
5
+
6
+
7
+ class AzureKeyVault(KeyVaultInterface):
8
+ def __init__(self, config: dict):
9
+ """
10
+ Initialize the Azure Key Vault connection with the given configuration.
11
+
12
+ Args:
13
+ config (dict): Configuration dictionary containing 'vault_url'.
14
+ """
15
+ self._vault_url = config.get('vault_url')
16
+ self._credential = ClientSecretCredential(
17
+ tenant_id=config.get('tenant_id'),
18
+ client_id=config.get('client_id'),
19
+ client_secret=config.get('client_secret')
20
+ )
21
+ self._client = SecretClient(vault_url=self._vault_url, credential=self._credential)
22
+ self.logger = Logger('SHARED_KERNEL')
23
+ self.logger.info(f"Connected to Azure Key Vault at: {self._vault_url}")
24
+
25
+ def store_secret(self, name: str, secret: str) -> None:
26
+ """
27
+ Store a secret in Azure Key Vault.
28
+
29
+ Args:
30
+ name (str): The name of the secret.
31
+ secret (str): The value of the secret.
32
+ """
33
+ self._client.set_secret(name, secret)
34
+ self.logger.info(f"Stored secret '{name}'")
35
+
36
+ def retrieve_secret(self, name: str) -> str:
37
+ """
38
+ Retrieve a secret from Azure Key Vault.
39
+
40
+ Args:
41
+ name (str): The name of the secret.
42
+
43
+ Returns:
44
+ str: The value of the retrieved secret.
45
+ """
46
+ retrieved_secret = self._client.get_secret(name)
47
+ return retrieved_secret.value
48
+
49
+ def delete_secret(self, name: str) -> None:
50
+ """
51
+ Delete a secret from Azure Key Vault.
52
+
53
+ Args:
54
+ name (str): The name of the secret.
55
+ """
56
+ self._client.begin_delete_secret(name)
57
+ self.logger.info(f"Deleted secret '{name}'")
58
+
59
+ def list_secrets(self) -> list:
60
+ """
61
+ List all secrets in Azure Key Vault.
62
+
63
+ Returns:
64
+ list: A list of secret names.
65
+ """
66
+ secrets = self._client.list_properties_of_secrets()
67
+ return [secret.name for secret in secrets]
@@ -0,0 +1,35 @@
1
+ import unittest
2
+ import os
3
+ from unittest.mock import patch, mock_open
4
+ from shared_kernel.config import Config
5
+ from shared_kernel.exceptions import InvalidConfiguration, MissingConfiguration
6
+
7
+
8
+ class TestConfig(unittest.TestCase):
9
+
10
+ @patch('shared_kernel.config.find_dotenv', return_value='.env')
11
+ def test_init_with_env_file_found(self, mock_find_dotenv):
12
+ with patch('builtins.open', mock_open(read_data='KEY=value')):
13
+ config=Config()
14
+ self.assertEqual(config.get('KEY'), 'value')
15
+
16
+ @patch('shared_kernel.config.find_dotenv', return_value='')
17
+ def test_init_with_env_file_not_found(self, mock_find_dotenv):
18
+ with self.assertRaises(InvalidConfiguration):
19
+ Config()
20
+
21
+ @patch('shared_kernel.config.find_dotenv', return_value='.env')
22
+ def test_get_existing_variable(self, mock_find_dotenv):
23
+ with patch.dict(os.environ, {'EXISTING_KEY': 'existing_value'}):
24
+ config=Config()
25
+ self.assertEqual(config.get('EXISTING_KEY'), 'existing_value')
26
+
27
+ @patch('shared_kernel.config.find_dotenv', return_value='/mocked/path/to/.env')
28
+ def test_get_non_existing_variable(self, mock_find_dotenv):
29
+ with self.assertRaises(MissingConfiguration):
30
+ config=Config()
31
+ config.get('NON_EXISTING_KEY')
32
+
33
+
34
+ if __name__ == '__main__':
35
+ unittest.main()