opensecureconf-client 1.0.1__tar.gz → 1.0.2__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.
- {opensecureconf_client-1.0.1/opensecureconf_client.egg-info → opensecureconf_client-1.0.2}/PKG-INFO +1 -1
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2/opensecureconf_client.egg-info}/PKG-INFO +1 -1
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/opensecureconf_client.py +39 -41
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/pyproject.toml +1 -1
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/setup.py +1 -0
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/LICENSE +0 -0
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/MANIFEST.in +0 -0
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/README.md +0 -0
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/opensecureconf_client.egg-info/SOURCES.txt +0 -0
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/opensecureconf_client.egg-info/dependency_links.txt +0 -0
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/opensecureconf_client.egg-info/requires.txt +0 -0
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/opensecureconf_client.egg-info/top_level.txt +0 -0
- {opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2}/setup.cfg +0 -0
{opensecureconf_client-1.0.1/opensecureconf_client.egg-info → opensecureconf_client-1.0.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensecureconf-client
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: Python client library for OpenSecureConf encrypted configuration management API
|
|
5
5
|
Author-email: Alessandro Pioli <alessandro.pioli+apioli-pypi@gmail.com>
|
|
6
6
|
Maintainer-email: Alessandro Pioli <alessandro.pioli+apioli-pypi@gmail.com>
|
{opensecureconf_client-1.0.1 → opensecureconf_client-1.0.2/opensecureconf_client.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensecureconf-client
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: Python client library for OpenSecureConf encrypted configuration management API
|
|
5
5
|
Author-email: Alessandro Pioli <alessandro.pioli+apioli-pypi@gmail.com>
|
|
6
6
|
Maintainer-email: Alessandro Pioli <alessandro.pioli+apioli-pypi@gmail.com>
|
|
@@ -5,29 +5,26 @@ A Python client library for interacting with the OpenSecureConf API,
|
|
|
5
5
|
which provides encrypted configuration management with multithreading support.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from typing import Any, Dict, List, Optional
|
|
9
|
+
|
|
8
10
|
import requests
|
|
9
|
-
from
|
|
10
|
-
from requests.exceptions import RequestException, HTTPError, ConnectionError, Timeout
|
|
11
|
+
from requests.exceptions import Timeout
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class OpenSecureConfError(Exception):
|
|
14
15
|
"""Base exception for OpenSecureConf client errors."""
|
|
15
|
-
pass
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class AuthenticationError(OpenSecureConfError):
|
|
19
19
|
"""Raised when authentication fails (invalid or missing user key)."""
|
|
20
|
-
pass
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
class ConfigurationNotFoundError(OpenSecureConfError):
|
|
24
23
|
"""Raised when a requested configuration key does not exist."""
|
|
25
|
-
pass
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
class ConfigurationExistsError(OpenSecureConfError):
|
|
29
27
|
"""Raised when attempting to create a configuration that already exists."""
|
|
30
|
-
pass
|
|
31
28
|
|
|
32
29
|
|
|
33
30
|
class OpenSecureConfClient:
|
|
@@ -40,12 +37,14 @@ class OpenSecureConfClient:
|
|
|
40
37
|
Attributes:
|
|
41
38
|
base_url (str): The base URL of the OpenSecureConf API server.
|
|
42
39
|
user_key (str): The encryption key used for authentication and encryption/decryption.
|
|
40
|
+
api_key (Optional[str]): Optional API key for additional authentication.
|
|
43
41
|
timeout (int): Request timeout in seconds.
|
|
44
42
|
|
|
45
43
|
Example:
|
|
46
44
|
>>> client = OpenSecureConfClient(
|
|
47
45
|
... base_url="http://localhost:9000",
|
|
48
|
-
... user_key="my-secret-key-123"
|
|
46
|
+
... user_key="my-secret-key-123",
|
|
47
|
+
... api_key="optional-api-key"
|
|
49
48
|
... )
|
|
50
49
|
>>> config = client.create("database", {"host": "localhost", "port": 5432})
|
|
51
50
|
>>> print(config["value"])
|
|
@@ -56,6 +55,7 @@ class OpenSecureConfClient:
|
|
|
56
55
|
self,
|
|
57
56
|
base_url: str,
|
|
58
57
|
user_key: str,
|
|
58
|
+
api_key: Optional[str] = None,
|
|
59
59
|
timeout: int = 30,
|
|
60
60
|
verify_ssl: bool = True
|
|
61
61
|
):
|
|
@@ -65,6 +65,7 @@ class OpenSecureConfClient:
|
|
|
65
65
|
Args:
|
|
66
66
|
base_url: The base URL of the OpenSecureConf API (e.g., "http://localhost:9000")
|
|
67
67
|
user_key: User encryption key for authentication (minimum 8 characters)
|
|
68
|
+
api_key: Optional API key for additional authentication
|
|
68
69
|
timeout: Request timeout in seconds (default: 30)
|
|
69
70
|
verify_ssl: Whether to verify SSL certificates (default: True)
|
|
70
71
|
|
|
@@ -76,20 +77,24 @@ class OpenSecureConfClient:
|
|
|
76
77
|
|
|
77
78
|
self.base_url = base_url.rstrip("/")
|
|
78
79
|
self.user_key = user_key
|
|
80
|
+
self.api_key = api_key
|
|
79
81
|
self.timeout = timeout
|
|
80
82
|
self.verify_ssl = verify_ssl
|
|
81
83
|
self._session = requests.Session()
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
|
|
85
|
+
# Setup headers
|
|
86
|
+
headers = {
|
|
87
|
+
"x-user-key": self.user_key,
|
|
84
88
|
"Content-Type": "application/json"
|
|
85
|
-
}
|
|
89
|
+
}
|
|
86
90
|
|
|
87
|
-
|
|
88
|
-
self
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
# Add X-API-Key header if api_key is provided
|
|
92
|
+
if self.api_key:
|
|
93
|
+
headers["X-API-Key"] = self.api_key
|
|
94
|
+
|
|
95
|
+
self._session.headers.update(headers)
|
|
96
|
+
|
|
97
|
+
def _make_request(self, method: str, endpoint: str, **kwargs) -> Any:
|
|
93
98
|
"""
|
|
94
99
|
Make an HTTP request to the API with error handling.
|
|
95
100
|
|
|
@@ -116,17 +121,21 @@ class OpenSecureConfClient:
|
|
|
116
121
|
response = self._session.request(method, url, **kwargs)
|
|
117
122
|
|
|
118
123
|
if response.status_code == 401:
|
|
119
|
-
raise AuthenticationError(
|
|
120
|
-
|
|
124
|
+
raise AuthenticationError(
|
|
125
|
+
"Authentication failed: invalid or missing user key"
|
|
126
|
+
)
|
|
127
|
+
if response.status_code == 404:
|
|
121
128
|
raise ConfigurationNotFoundError("Configuration not found")
|
|
122
|
-
|
|
129
|
+
if response.status_code == 400:
|
|
123
130
|
error_detail = response.json().get("detail", "Bad request")
|
|
124
131
|
if "already exists" in error_detail.lower():
|
|
125
132
|
raise ConfigurationExistsError(error_detail)
|
|
126
133
|
raise OpenSecureConfError(f"Bad request: {error_detail}")
|
|
127
|
-
|
|
134
|
+
if response.status_code >= 400:
|
|
128
135
|
error_detail = response.json().get("detail", "Unknown error")
|
|
129
|
-
raise OpenSecureConfError(
|
|
136
|
+
raise OpenSecureConfError(
|
|
137
|
+
f"API error ({response.status_code}): {error_detail}"
|
|
138
|
+
)
|
|
130
139
|
|
|
131
140
|
if response.status_code == 204 or not response.content:
|
|
132
141
|
return None
|
|
@@ -134,9 +143,11 @@ class OpenSecureConfClient:
|
|
|
134
143
|
return response.json()
|
|
135
144
|
|
|
136
145
|
except (ConnectionError, Timeout) as e:
|
|
137
|
-
raise ConnectionError(
|
|
146
|
+
raise ConnectionError(
|
|
147
|
+
f"Failed to connect to {self.base_url}: {str(e)}"
|
|
148
|
+
) from e
|
|
138
149
|
except ValueError as e:
|
|
139
|
-
raise OpenSecureConfError(f"Invalid JSON response: {str(e)}")
|
|
150
|
+
raise OpenSecureConfError(f"Invalid JSON response: {str(e)}") from e
|
|
140
151
|
|
|
141
152
|
def get_service_info(self) -> Dict[str, Any]:
|
|
142
153
|
"""
|
|
@@ -153,10 +164,7 @@ class OpenSecureConfClient:
|
|
|
153
164
|
return self._make_request("GET", "/")
|
|
154
165
|
|
|
155
166
|
def create(
|
|
156
|
-
self,
|
|
157
|
-
key: str,
|
|
158
|
-
value: Dict[str, Any],
|
|
159
|
-
category: Optional[str] = None
|
|
167
|
+
self, key: str, value: Dict[str, Any], category: Optional[str] = None
|
|
160
168
|
) -> Dict[str, Any]:
|
|
161
169
|
"""
|
|
162
170
|
Create a new encrypted configuration entry.
|
|
@@ -187,11 +195,7 @@ class OpenSecureConfClient:
|
|
|
187
195
|
if not key or len(key) > 255:
|
|
188
196
|
raise ValueError("Key must be between 1 and 255 characters")
|
|
189
197
|
|
|
190
|
-
payload = {
|
|
191
|
-
"key": key,
|
|
192
|
-
"value": value,
|
|
193
|
-
"category": category
|
|
194
|
-
}
|
|
198
|
+
payload = {"key": key, "value": value, "category": category}
|
|
195
199
|
|
|
196
200
|
return self._make_request("POST", "/configs", json=payload)
|
|
197
201
|
|
|
@@ -216,10 +220,7 @@ class OpenSecureConfClient:
|
|
|
216
220
|
return self._make_request("GET", f"/configs/{key}")
|
|
217
221
|
|
|
218
222
|
def update(
|
|
219
|
-
self,
|
|
220
|
-
key: str,
|
|
221
|
-
value: Dict[str, Any],
|
|
222
|
-
category: Optional[str] = None
|
|
223
|
+
self, key: str, value: Dict[str, Any], category: Optional[str] = None
|
|
223
224
|
) -> Dict[str, Any]:
|
|
224
225
|
"""
|
|
225
226
|
Update an existing configuration entry with new encrypted value.
|
|
@@ -241,10 +242,7 @@ class OpenSecureConfClient:
|
|
|
241
242
|
... value={"host": "db.example.com", "port": 5432}
|
|
242
243
|
... )
|
|
243
244
|
"""
|
|
244
|
-
payload = {
|
|
245
|
-
"value": value,
|
|
246
|
-
"category": category
|
|
247
|
-
}
|
|
245
|
+
payload = {"value": value, "category": category}
|
|
248
246
|
|
|
249
247
|
return self._make_request("PUT", f"/configs/{key}", json=payload)
|
|
250
248
|
|
|
@@ -312,5 +310,5 @@ __all__ = [
|
|
|
312
310
|
"OpenSecureConfError",
|
|
313
311
|
"AuthenticationError",
|
|
314
312
|
"ConfigurationNotFoundError",
|
|
315
|
-
"ConfigurationExistsError"
|
|
313
|
+
"ConfigurationExistsError",
|
|
316
314
|
]
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "opensecureconf-client"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.2"
|
|
8
8
|
description = "Python client library for OpenSecureConf encrypted configuration management API"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|