raqeb 1.0.0__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.
raqeb-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,274 @@
1
+ Metadata-Version: 2.4
2
+ Name: raqeb
3
+ Version: 1.0.0
4
+ Summary: Python SDK for Raqeb Database PAM and Secrets Management
5
+ Home-page: https://github.com/raqeb/python-sdk
6
+ Author: Raqeb
7
+ Author-email: support@raqeb.cloud
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Requires-Python: >=3.7
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: requests>=2.25.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=6.0; extra == "dev"
23
+ Requires-Dist: pytest-cov>=2.0; extra == "dev"
24
+ Requires-Dist: black>=21.0; extra == "dev"
25
+ Requires-Dist: flake8>=3.9; extra == "dev"
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: classifier
29
+ Dynamic: description
30
+ Dynamic: description-content-type
31
+ Dynamic: home-page
32
+ Dynamic: provides-extra
33
+ Dynamic: requires-dist
34
+ Dynamic: requires-python
35
+ Dynamic: summary
36
+
37
+ # Raqeb Python SDK
38
+
39
+ Official Python SDK for Raqeb Database PAM and Secrets Management.
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ pip install raqeb
45
+ ```
46
+
47
+ ## Quick Start
48
+
49
+ ```python
50
+ from raqeb import RaqebClient
51
+
52
+ # Initialize client with service account API key
53
+ client = RaqebClient(api_key="sa_your_api_key_here")
54
+
55
+ # Get a secret
56
+ secret = client.get_secret("secret-id")
57
+ print(f"Secret value: {secret['value']}")
58
+
59
+ # Get temporary database credentials
60
+ creds = client.get_database_credentials(
61
+ database_id="db-id",
62
+ ttl_hours=4,
63
+ access_level="read-only"
64
+ )
65
+
66
+ print(f"Username: {creds['username']}")
67
+ print(f"Password: {creds['password']}")
68
+ print(f"Expires: {creds['expires_at']}")
69
+
70
+ # Revoke credentials when done
71
+ client.revoke_lease(creds['lease_id'])
72
+ ```
73
+
74
+ ## Usage Examples
75
+
76
+ ### Secrets Management
77
+
78
+ ```python
79
+ from raqeb import RaqebClient
80
+
81
+ client = RaqebClient(api_key="sa_your_key")
82
+
83
+ # Retrieve a secret
84
+ secret = client.get_secret("api-key-prod")
85
+ api_key = secret['value']
86
+
87
+ # Use the secret in your application
88
+ import requests
89
+ response = requests.get(
90
+ "https://api.example.com/data",
91
+ headers={"Authorization": f"Bearer {api_key}"}
92
+ )
93
+ ```
94
+
95
+ ### Database Access
96
+
97
+ ```python
98
+ from raqeb import RaqebClient
99
+ import psycopg2
100
+
101
+ client = RaqebClient(api_key="sa_your_key")
102
+
103
+ # Get temporary database credentials
104
+ creds = client.get_database_credentials(
105
+ database_id="prod-postgres",
106
+ ttl_hours=2,
107
+ access_level="read-only"
108
+ )
109
+
110
+ # Connect to database
111
+ conn = psycopg2.connect(
112
+ host="db.example.com",
113
+ port=5432,
114
+ database="myapp",
115
+ user=creds['username'],
116
+ password=creds['password']
117
+ )
118
+
119
+ try:
120
+ # Use the connection
121
+ cursor = conn.cursor()
122
+ cursor.execute("SELECT * FROM users LIMIT 10")
123
+ results = cursor.fetchall()
124
+
125
+ finally:
126
+ conn.close()
127
+ # Revoke credentials
128
+ client.revoke_lease(creds['lease_id'])
129
+ ```
130
+
131
+ ### Context Manager
132
+
133
+ ```python
134
+ from raqeb import RaqebClient
135
+
136
+ # Use context manager for automatic cleanup
137
+ with RaqebClient(api_key="sa_your_key") as client:
138
+ secret = client.get_secret("secret-id")
139
+ print(secret['value'])
140
+ ```
141
+
142
+ ### API Key Management
143
+
144
+ ```python
145
+ from raqeb import RaqebClient
146
+
147
+ client = RaqebClient(api_key="sa_your_key")
148
+
149
+ # List API keys
150
+ keys = client.list_api_keys()
151
+ for key in keys:
152
+ print(f"{key['name']}: {key['key_prefix']}...")
153
+
154
+ # Create new API key
155
+ new_key = client.create_api_key(
156
+ name="CI/CD Pipeline",
157
+ scopes=["secrets:read", "databases:read"],
158
+ description="Key for automated deployments"
159
+ )
160
+ print(f"New API Key: {new_key['api_key']}") # Save this!
161
+
162
+ # Delete API key
163
+ client.delete_api_key("key-id")
164
+ ```
165
+
166
+ ## Error Handling
167
+
168
+ ```python
169
+ from raqeb import RaqebClient, AuthenticationError, PermissionError, NotFoundError
170
+
171
+ client = RaqebClient(api_key="sa_your_key")
172
+
173
+ try:
174
+ secret = client.get_secret("secret-id")
175
+
176
+ except AuthenticationError:
177
+ print("Invalid or expired API key")
178
+
179
+ except PermissionError:
180
+ print("Insufficient permissions - check API key scopes")
181
+
182
+ except NotFoundError:
183
+ print("Secret not found")
184
+
185
+ except RaqebError as e:
186
+ print(f"API error: {e}")
187
+ ```
188
+
189
+ ## API Reference
190
+
191
+ ### RaqebClient
192
+
193
+ #### `__init__(api_key, base_url="https://app.raqeb.cloud/api/v1")`
194
+ Initialize the client.
195
+
196
+ #### `get_secret(secret_id) -> dict`
197
+ Retrieve a secret value.
198
+
199
+ **Returns:**
200
+ ```python
201
+ {
202
+ 'secret_id': 'secret-123',
203
+ 'name': 'API Key',
204
+ 'value': 'secret-value',
205
+ 'retrieved_at': '2026-02-14T16:09:00Z'
206
+ }
207
+ ```
208
+
209
+ #### `get_database_credentials(database_id, ttl_hours=4, access_level='read-only') -> dict`
210
+ Generate temporary database credentials.
211
+
212
+ **Parameters:**
213
+ - `database_id` (str): Database ID
214
+ - `ttl_hours` (int): Time to live in hours (default: 4)
215
+ - `access_level` (str): 'read-only', 'read-write', or 'admin'
216
+
217
+ **Returns:**
218
+ ```python
219
+ {
220
+ 'lease_id': 'lease-123',
221
+ 'username': 'temp_user_abc',
222
+ 'password': 'temp_pass_xyz',
223
+ 'database_id': 'db-123',
224
+ 'access_level': 'read-only',
225
+ 'issued_at': '2026-02-14T16:09:00Z',
226
+ 'expires_at': '2026-02-14T20:09:00Z',
227
+ 'ttl_seconds': 14400
228
+ }
229
+ ```
230
+
231
+ #### `revoke_lease(lease_id) -> None`
232
+ Revoke a dynamic secret lease.
233
+
234
+ #### `list_api_keys() -> list`
235
+ List user's API keys.
236
+
237
+ #### `create_api_key(name, description=None, scopes=None, expires_at=None) -> dict`
238
+ Create a new API key.
239
+
240
+ #### `delete_api_key(key_id) -> None`
241
+ Delete an API key.
242
+
243
+ ## Environment Variables
244
+
245
+ You can use environment variables for configuration:
246
+
247
+ ```python
248
+ import os
249
+ from raqeb import RaqebClient
250
+
251
+ client = RaqebClient(
252
+ api_key=os.getenv('RAQEB_API_KEY'),
253
+ base_url=os.getenv('RAQEB_BASE_URL', 'https://app.raqeb.cloud/api/v1')
254
+ )
255
+ ```
256
+
257
+ ## Best Practices
258
+
259
+ 1. **Never hardcode API keys** - Use environment variables
260
+ 2. **Use minimal scopes** - Only grant necessary permissions
261
+ 3. **Set appropriate TTLs** - Use shortest time needed
262
+ 4. **Always revoke leases** - Clean up credentials when done
263
+ 5. **Handle errors gracefully** - Catch and handle SDK exceptions
264
+ 6. **Use context managers** - Automatic resource cleanup
265
+
266
+ ## License
267
+
268
+ MIT License - see LICENSE file for details
269
+
270
+ ## Support
271
+
272
+ - Documentation: https://docs.raqeb.cloud
273
+ - Email: support@raqeb.cloud
274
+ - GitHub: https://github.com/raqeb/python-sdk
raqeb-1.0.0/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # Raqeb Python SDK
2
+
3
+ Official Python SDK for Raqeb Database PAM and Secrets Management.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install raqeb
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from raqeb import RaqebClient
15
+
16
+ # Initialize client with service account API key
17
+ client = RaqebClient(api_key="sa_your_api_key_here")
18
+
19
+ # Get a secret
20
+ secret = client.get_secret("secret-id")
21
+ print(f"Secret value: {secret['value']}")
22
+
23
+ # Get temporary database credentials
24
+ creds = client.get_database_credentials(
25
+ database_id="db-id",
26
+ ttl_hours=4,
27
+ access_level="read-only"
28
+ )
29
+
30
+ print(f"Username: {creds['username']}")
31
+ print(f"Password: {creds['password']}")
32
+ print(f"Expires: {creds['expires_at']}")
33
+
34
+ # Revoke credentials when done
35
+ client.revoke_lease(creds['lease_id'])
36
+ ```
37
+
38
+ ## Usage Examples
39
+
40
+ ### Secrets Management
41
+
42
+ ```python
43
+ from raqeb import RaqebClient
44
+
45
+ client = RaqebClient(api_key="sa_your_key")
46
+
47
+ # Retrieve a secret
48
+ secret = client.get_secret("api-key-prod")
49
+ api_key = secret['value']
50
+
51
+ # Use the secret in your application
52
+ import requests
53
+ response = requests.get(
54
+ "https://api.example.com/data",
55
+ headers={"Authorization": f"Bearer {api_key}"}
56
+ )
57
+ ```
58
+
59
+ ### Database Access
60
+
61
+ ```python
62
+ from raqeb import RaqebClient
63
+ import psycopg2
64
+
65
+ client = RaqebClient(api_key="sa_your_key")
66
+
67
+ # Get temporary database credentials
68
+ creds = client.get_database_credentials(
69
+ database_id="prod-postgres",
70
+ ttl_hours=2,
71
+ access_level="read-only"
72
+ )
73
+
74
+ # Connect to database
75
+ conn = psycopg2.connect(
76
+ host="db.example.com",
77
+ port=5432,
78
+ database="myapp",
79
+ user=creds['username'],
80
+ password=creds['password']
81
+ )
82
+
83
+ try:
84
+ # Use the connection
85
+ cursor = conn.cursor()
86
+ cursor.execute("SELECT * FROM users LIMIT 10")
87
+ results = cursor.fetchall()
88
+
89
+ finally:
90
+ conn.close()
91
+ # Revoke credentials
92
+ client.revoke_lease(creds['lease_id'])
93
+ ```
94
+
95
+ ### Context Manager
96
+
97
+ ```python
98
+ from raqeb import RaqebClient
99
+
100
+ # Use context manager for automatic cleanup
101
+ with RaqebClient(api_key="sa_your_key") as client:
102
+ secret = client.get_secret("secret-id")
103
+ print(secret['value'])
104
+ ```
105
+
106
+ ### API Key Management
107
+
108
+ ```python
109
+ from raqeb import RaqebClient
110
+
111
+ client = RaqebClient(api_key="sa_your_key")
112
+
113
+ # List API keys
114
+ keys = client.list_api_keys()
115
+ for key in keys:
116
+ print(f"{key['name']}: {key['key_prefix']}...")
117
+
118
+ # Create new API key
119
+ new_key = client.create_api_key(
120
+ name="CI/CD Pipeline",
121
+ scopes=["secrets:read", "databases:read"],
122
+ description="Key for automated deployments"
123
+ )
124
+ print(f"New API Key: {new_key['api_key']}") # Save this!
125
+
126
+ # Delete API key
127
+ client.delete_api_key("key-id")
128
+ ```
129
+
130
+ ## Error Handling
131
+
132
+ ```python
133
+ from raqeb import RaqebClient, AuthenticationError, PermissionError, NotFoundError
134
+
135
+ client = RaqebClient(api_key="sa_your_key")
136
+
137
+ try:
138
+ secret = client.get_secret("secret-id")
139
+
140
+ except AuthenticationError:
141
+ print("Invalid or expired API key")
142
+
143
+ except PermissionError:
144
+ print("Insufficient permissions - check API key scopes")
145
+
146
+ except NotFoundError:
147
+ print("Secret not found")
148
+
149
+ except RaqebError as e:
150
+ print(f"API error: {e}")
151
+ ```
152
+
153
+ ## API Reference
154
+
155
+ ### RaqebClient
156
+
157
+ #### `__init__(api_key, base_url="https://app.raqeb.cloud/api/v1")`
158
+ Initialize the client.
159
+
160
+ #### `get_secret(secret_id) -> dict`
161
+ Retrieve a secret value.
162
+
163
+ **Returns:**
164
+ ```python
165
+ {
166
+ 'secret_id': 'secret-123',
167
+ 'name': 'API Key',
168
+ 'value': 'secret-value',
169
+ 'retrieved_at': '2026-02-14T16:09:00Z'
170
+ }
171
+ ```
172
+
173
+ #### `get_database_credentials(database_id, ttl_hours=4, access_level='read-only') -> dict`
174
+ Generate temporary database credentials.
175
+
176
+ **Parameters:**
177
+ - `database_id` (str): Database ID
178
+ - `ttl_hours` (int): Time to live in hours (default: 4)
179
+ - `access_level` (str): 'read-only', 'read-write', or 'admin'
180
+
181
+ **Returns:**
182
+ ```python
183
+ {
184
+ 'lease_id': 'lease-123',
185
+ 'username': 'temp_user_abc',
186
+ 'password': 'temp_pass_xyz',
187
+ 'database_id': 'db-123',
188
+ 'access_level': 'read-only',
189
+ 'issued_at': '2026-02-14T16:09:00Z',
190
+ 'expires_at': '2026-02-14T20:09:00Z',
191
+ 'ttl_seconds': 14400
192
+ }
193
+ ```
194
+
195
+ #### `revoke_lease(lease_id) -> None`
196
+ Revoke a dynamic secret lease.
197
+
198
+ #### `list_api_keys() -> list`
199
+ List user's API keys.
200
+
201
+ #### `create_api_key(name, description=None, scopes=None, expires_at=None) -> dict`
202
+ Create a new API key.
203
+
204
+ #### `delete_api_key(key_id) -> None`
205
+ Delete an API key.
206
+
207
+ ## Environment Variables
208
+
209
+ You can use environment variables for configuration:
210
+
211
+ ```python
212
+ import os
213
+ from raqeb import RaqebClient
214
+
215
+ client = RaqebClient(
216
+ api_key=os.getenv('RAQEB_API_KEY'),
217
+ base_url=os.getenv('RAQEB_BASE_URL', 'https://app.raqeb.cloud/api/v1')
218
+ )
219
+ ```
220
+
221
+ ## Best Practices
222
+
223
+ 1. **Never hardcode API keys** - Use environment variables
224
+ 2. **Use minimal scopes** - Only grant necessary permissions
225
+ 3. **Set appropriate TTLs** - Use shortest time needed
226
+ 4. **Always revoke leases** - Clean up credentials when done
227
+ 5. **Handle errors gracefully** - Catch and handle SDK exceptions
228
+ 6. **Use context managers** - Automatic resource cleanup
229
+
230
+ ## License
231
+
232
+ MIT License - see LICENSE file for details
233
+
234
+ ## Support
235
+
236
+ - Documentation: https://docs.raqeb.cloud
237
+ - Email: support@raqeb.cloud
238
+ - GitHub: https://github.com/raqeb/python-sdk
@@ -0,0 +1,25 @@
1
+ """
2
+ Raqeb Python SDK - Database PAM and Secrets Management
3
+
4
+ Usage:
5
+ from raqeb import RaqebClient
6
+
7
+ client = RaqebClient(api_key="sa_your_api_key")
8
+
9
+ # Get secret
10
+ secret = client.get_secret("secret-id")
11
+
12
+ # Get database credentials
13
+ creds = client.get_database_credentials("db-id", ttl_hours=4)
14
+ print(f"Username: {creds['username']}")
15
+ print(f"Password: {creds['password']}")
16
+
17
+ # Revoke when done
18
+ client.revoke_lease(creds['lease_id'])
19
+ """
20
+
21
+ from .client import RaqebClient
22
+ from .exceptions import RaqebError, AuthenticationError, NotFoundError, PermissionError
23
+
24
+ __version__ = "1.0.0"
25
+ __all__ = ["RaqebClient", "RaqebError", "AuthenticationError", "NotFoundError", "PermissionError"]
@@ -0,0 +1,193 @@
1
+ """Raqeb Python SDK Client."""
2
+
3
+ import requests
4
+ from typing import Dict, List, Optional, Any
5
+ from .exceptions import RaqebError, AuthenticationError, NotFoundError, PermissionError
6
+
7
+
8
+ class RaqebClient:
9
+ """Client for interacting with Raqeb API."""
10
+
11
+ def __init__(self, api_key: str, base_url: str = "https://app.raqeb.cloud/api/v1"):
12
+ """
13
+ Initialize Raqeb client.
14
+
15
+ Args:
16
+ api_key: Service account API key (starts with 'sa_')
17
+ base_url: Base URL for Raqeb API
18
+ """
19
+ self.api_key = api_key
20
+ self.base_url = base_url.rstrip('/')
21
+ self.session = requests.Session()
22
+ self.session.headers.update({
23
+ 'Authorization': f'Bearer {api_key}',
24
+ 'Content-Type': 'application/json'
25
+ })
26
+
27
+ def _request(self, method: str, endpoint: str, **kwargs) -> Any:
28
+ """Make HTTP request to API."""
29
+ url = f"{self.base_url}{endpoint}"
30
+
31
+ try:
32
+ response = self.session.request(method, url, **kwargs)
33
+ response.raise_for_status()
34
+ return response.json() if response.content else None
35
+
36
+ except requests.exceptions.HTTPError as e:
37
+ status_code = e.response.status_code
38
+ detail = e.response.json().get('detail', str(e))
39
+
40
+ if status_code == 401:
41
+ raise AuthenticationError(detail)
42
+ elif status_code == 403:
43
+ raise PermissionError(detail)
44
+ elif status_code == 404:
45
+ raise NotFoundError(detail)
46
+ else:
47
+ raise RaqebError(f"HTTP {status_code}: {detail}")
48
+
49
+ except requests.exceptions.RequestException as e:
50
+ raise RaqebError(f"Request failed: {str(e)}")
51
+
52
+ # ============================================================================
53
+ # Secrets Management
54
+ # ============================================================================
55
+
56
+ def get_secret(self, secret_id: str) -> Dict[str, Any]:
57
+ """
58
+ Retrieve a secret value.
59
+
60
+ Args:
61
+ secret_id: ID of the secret to retrieve
62
+
63
+ Returns:
64
+ Dict with keys: secret_id, name, value, retrieved_at
65
+
66
+ Example:
67
+ >>> secret = client.get_secret("secret-123")
68
+ >>> print(secret['value'])
69
+ """
70
+ return self._request('POST', '/service-accounts/secrets/retrieve', params={'secret_id': secret_id})
71
+
72
+ # ============================================================================
73
+ # Database Credentials
74
+ # ============================================================================
75
+
76
+ def get_database_credentials(
77
+ self,
78
+ database_id: str,
79
+ ttl_hours: int = 4,
80
+ access_level: str = 'read-only'
81
+ ) -> Dict[str, Any]:
82
+ """
83
+ Generate temporary database credentials.
84
+
85
+ Args:
86
+ database_id: ID of the database
87
+ ttl_hours: Time to live in hours (default: 4)
88
+ access_level: Access level - 'read-only', 'read-write', or 'admin'
89
+
90
+ Returns:
91
+ Dict with keys: lease_id, username, password, database_id, access_level,
92
+ issued_at, expires_at, ttl_seconds
93
+
94
+ Example:
95
+ >>> creds = client.get_database_credentials("db-123", ttl_hours=2)
96
+ >>> print(f"Username: {creds['username']}")
97
+ >>> print(f"Password: {creds['password']}")
98
+ >>> print(f"Expires: {creds['expires_at']}")
99
+ """
100
+ payload = {
101
+ 'database_id': database_id,
102
+ 'ttl_hours': ttl_hours,
103
+ 'access_level': access_level
104
+ }
105
+ return self._request('POST', '/service-accounts/databases/dynamic-credentials', json=payload)
106
+
107
+ def revoke_lease(self, lease_id: str) -> None:
108
+ """
109
+ Revoke a dynamic secret lease.
110
+
111
+ Args:
112
+ lease_id: ID of the lease to revoke
113
+
114
+ Example:
115
+ >>> client.revoke_lease("lease-123")
116
+ """
117
+ self._request('POST', f'/service-accounts/leases/{lease_id}/revoke')
118
+
119
+ # ============================================================================
120
+ # API Keys Management
121
+ # ============================================================================
122
+
123
+ def list_api_keys(self) -> List[Dict[str, Any]]:
124
+ """
125
+ List user's API keys.
126
+
127
+ Returns:
128
+ List of API key objects
129
+
130
+ Example:
131
+ >>> keys = client.list_api_keys()
132
+ >>> for key in keys:
133
+ ... print(f"{key['name']}: {key['key_prefix']}...")
134
+ """
135
+ return self._request('GET', '/service-accounts/api-keys')
136
+
137
+ def create_api_key(
138
+ self,
139
+ name: str,
140
+ description: Optional[str] = None,
141
+ scopes: Optional[List[str]] = None,
142
+ expires_at: Optional[str] = None
143
+ ) -> Dict[str, Any]:
144
+ """
145
+ Create a new API key.
146
+
147
+ Args:
148
+ name: Name for the API key
149
+ description: Optional description
150
+ scopes: List of scopes (e.g., ['secrets:read', 'databases:read'])
151
+ expires_at: Optional expiration date (ISO format)
152
+
153
+ Returns:
154
+ Dict with keys: id, name, api_key, key_prefix, scopes, created_at
155
+
156
+ Note:
157
+ The api_key is only returned once. Save it securely!
158
+
159
+ Example:
160
+ >>> key = client.create_api_key("My App", scopes=['secrets:read'])
161
+ >>> print(f"API Key: {key['api_key']}") # Save this!
162
+ """
163
+ payload = {
164
+ 'name': name,
165
+ 'description': description,
166
+ 'scopes': scopes or ['secrets:read', 'databases:read'],
167
+ 'expires_at': expires_at
168
+ }
169
+ return self._request('POST', '/service-accounts/api-keys', json=payload)
170
+
171
+ def delete_api_key(self, key_id: str) -> None:
172
+ """
173
+ Delete an API key.
174
+
175
+ Args:
176
+ key_id: ID of the key to delete
177
+
178
+ Example:
179
+ >>> client.delete_api_key("key-123")
180
+ """
181
+ self._request('DELETE', f'/service-accounts/api-keys/{key_id}')
182
+
183
+ # ============================================================================
184
+ # Context Manager Support
185
+ # ============================================================================
186
+
187
+ def __enter__(self):
188
+ """Context manager entry."""
189
+ return self
190
+
191
+ def __exit__(self, exc_type, exc_val, exc_tb):
192
+ """Context manager exit - close session."""
193
+ self.session.close()
@@ -0,0 +1,21 @@
1
+ """Raqeb SDK Exceptions."""
2
+
3
+
4
+ class RaqebError(Exception):
5
+ """Base exception for Raqeb SDK."""
6
+ pass
7
+
8
+
9
+ class AuthenticationError(RaqebError):
10
+ """Authentication failed - invalid or expired API key."""
11
+ pass
12
+
13
+
14
+ class PermissionError(RaqebError):
15
+ """Permission denied - insufficient scopes."""
16
+ pass
17
+
18
+
19
+ class NotFoundError(RaqebError):
20
+ """Resource not found."""
21
+ pass
@@ -0,0 +1,274 @@
1
+ Metadata-Version: 2.4
2
+ Name: raqeb
3
+ Version: 1.0.0
4
+ Summary: Python SDK for Raqeb Database PAM and Secrets Management
5
+ Home-page: https://github.com/raqeb/python-sdk
6
+ Author: Raqeb
7
+ Author-email: support@raqeb.cloud
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Requires-Python: >=3.7
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: requests>=2.25.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=6.0; extra == "dev"
23
+ Requires-Dist: pytest-cov>=2.0; extra == "dev"
24
+ Requires-Dist: black>=21.0; extra == "dev"
25
+ Requires-Dist: flake8>=3.9; extra == "dev"
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: classifier
29
+ Dynamic: description
30
+ Dynamic: description-content-type
31
+ Dynamic: home-page
32
+ Dynamic: provides-extra
33
+ Dynamic: requires-dist
34
+ Dynamic: requires-python
35
+ Dynamic: summary
36
+
37
+ # Raqeb Python SDK
38
+
39
+ Official Python SDK for Raqeb Database PAM and Secrets Management.
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ pip install raqeb
45
+ ```
46
+
47
+ ## Quick Start
48
+
49
+ ```python
50
+ from raqeb import RaqebClient
51
+
52
+ # Initialize client with service account API key
53
+ client = RaqebClient(api_key="sa_your_api_key_here")
54
+
55
+ # Get a secret
56
+ secret = client.get_secret("secret-id")
57
+ print(f"Secret value: {secret['value']}")
58
+
59
+ # Get temporary database credentials
60
+ creds = client.get_database_credentials(
61
+ database_id="db-id",
62
+ ttl_hours=4,
63
+ access_level="read-only"
64
+ )
65
+
66
+ print(f"Username: {creds['username']}")
67
+ print(f"Password: {creds['password']}")
68
+ print(f"Expires: {creds['expires_at']}")
69
+
70
+ # Revoke credentials when done
71
+ client.revoke_lease(creds['lease_id'])
72
+ ```
73
+
74
+ ## Usage Examples
75
+
76
+ ### Secrets Management
77
+
78
+ ```python
79
+ from raqeb import RaqebClient
80
+
81
+ client = RaqebClient(api_key="sa_your_key")
82
+
83
+ # Retrieve a secret
84
+ secret = client.get_secret("api-key-prod")
85
+ api_key = secret['value']
86
+
87
+ # Use the secret in your application
88
+ import requests
89
+ response = requests.get(
90
+ "https://api.example.com/data",
91
+ headers={"Authorization": f"Bearer {api_key}"}
92
+ )
93
+ ```
94
+
95
+ ### Database Access
96
+
97
+ ```python
98
+ from raqeb import RaqebClient
99
+ import psycopg2
100
+
101
+ client = RaqebClient(api_key="sa_your_key")
102
+
103
+ # Get temporary database credentials
104
+ creds = client.get_database_credentials(
105
+ database_id="prod-postgres",
106
+ ttl_hours=2,
107
+ access_level="read-only"
108
+ )
109
+
110
+ # Connect to database
111
+ conn = psycopg2.connect(
112
+ host="db.example.com",
113
+ port=5432,
114
+ database="myapp",
115
+ user=creds['username'],
116
+ password=creds['password']
117
+ )
118
+
119
+ try:
120
+ # Use the connection
121
+ cursor = conn.cursor()
122
+ cursor.execute("SELECT * FROM users LIMIT 10")
123
+ results = cursor.fetchall()
124
+
125
+ finally:
126
+ conn.close()
127
+ # Revoke credentials
128
+ client.revoke_lease(creds['lease_id'])
129
+ ```
130
+
131
+ ### Context Manager
132
+
133
+ ```python
134
+ from raqeb import RaqebClient
135
+
136
+ # Use context manager for automatic cleanup
137
+ with RaqebClient(api_key="sa_your_key") as client:
138
+ secret = client.get_secret("secret-id")
139
+ print(secret['value'])
140
+ ```
141
+
142
+ ### API Key Management
143
+
144
+ ```python
145
+ from raqeb import RaqebClient
146
+
147
+ client = RaqebClient(api_key="sa_your_key")
148
+
149
+ # List API keys
150
+ keys = client.list_api_keys()
151
+ for key in keys:
152
+ print(f"{key['name']}: {key['key_prefix']}...")
153
+
154
+ # Create new API key
155
+ new_key = client.create_api_key(
156
+ name="CI/CD Pipeline",
157
+ scopes=["secrets:read", "databases:read"],
158
+ description="Key for automated deployments"
159
+ )
160
+ print(f"New API Key: {new_key['api_key']}") # Save this!
161
+
162
+ # Delete API key
163
+ client.delete_api_key("key-id")
164
+ ```
165
+
166
+ ## Error Handling
167
+
168
+ ```python
169
+ from raqeb import RaqebClient, AuthenticationError, PermissionError, NotFoundError
170
+
171
+ client = RaqebClient(api_key="sa_your_key")
172
+
173
+ try:
174
+ secret = client.get_secret("secret-id")
175
+
176
+ except AuthenticationError:
177
+ print("Invalid or expired API key")
178
+
179
+ except PermissionError:
180
+ print("Insufficient permissions - check API key scopes")
181
+
182
+ except NotFoundError:
183
+ print("Secret not found")
184
+
185
+ except RaqebError as e:
186
+ print(f"API error: {e}")
187
+ ```
188
+
189
+ ## API Reference
190
+
191
+ ### RaqebClient
192
+
193
+ #### `__init__(api_key, base_url="https://app.raqeb.cloud/api/v1")`
194
+ Initialize the client.
195
+
196
+ #### `get_secret(secret_id) -> dict`
197
+ Retrieve a secret value.
198
+
199
+ **Returns:**
200
+ ```python
201
+ {
202
+ 'secret_id': 'secret-123',
203
+ 'name': 'API Key',
204
+ 'value': 'secret-value',
205
+ 'retrieved_at': '2026-02-14T16:09:00Z'
206
+ }
207
+ ```
208
+
209
+ #### `get_database_credentials(database_id, ttl_hours=4, access_level='read-only') -> dict`
210
+ Generate temporary database credentials.
211
+
212
+ **Parameters:**
213
+ - `database_id` (str): Database ID
214
+ - `ttl_hours` (int): Time to live in hours (default: 4)
215
+ - `access_level` (str): 'read-only', 'read-write', or 'admin'
216
+
217
+ **Returns:**
218
+ ```python
219
+ {
220
+ 'lease_id': 'lease-123',
221
+ 'username': 'temp_user_abc',
222
+ 'password': 'temp_pass_xyz',
223
+ 'database_id': 'db-123',
224
+ 'access_level': 'read-only',
225
+ 'issued_at': '2026-02-14T16:09:00Z',
226
+ 'expires_at': '2026-02-14T20:09:00Z',
227
+ 'ttl_seconds': 14400
228
+ }
229
+ ```
230
+
231
+ #### `revoke_lease(lease_id) -> None`
232
+ Revoke a dynamic secret lease.
233
+
234
+ #### `list_api_keys() -> list`
235
+ List user's API keys.
236
+
237
+ #### `create_api_key(name, description=None, scopes=None, expires_at=None) -> dict`
238
+ Create a new API key.
239
+
240
+ #### `delete_api_key(key_id) -> None`
241
+ Delete an API key.
242
+
243
+ ## Environment Variables
244
+
245
+ You can use environment variables for configuration:
246
+
247
+ ```python
248
+ import os
249
+ from raqeb import RaqebClient
250
+
251
+ client = RaqebClient(
252
+ api_key=os.getenv('RAQEB_API_KEY'),
253
+ base_url=os.getenv('RAQEB_BASE_URL', 'https://app.raqeb.cloud/api/v1')
254
+ )
255
+ ```
256
+
257
+ ## Best Practices
258
+
259
+ 1. **Never hardcode API keys** - Use environment variables
260
+ 2. **Use minimal scopes** - Only grant necessary permissions
261
+ 3. **Set appropriate TTLs** - Use shortest time needed
262
+ 4. **Always revoke leases** - Clean up credentials when done
263
+ 5. **Handle errors gracefully** - Catch and handle SDK exceptions
264
+ 6. **Use context managers** - Automatic resource cleanup
265
+
266
+ ## License
267
+
268
+ MIT License - see LICENSE file for details
269
+
270
+ ## Support
271
+
272
+ - Documentation: https://docs.raqeb.cloud
273
+ - Email: support@raqeb.cloud
274
+ - GitHub: https://github.com/raqeb/python-sdk
@@ -0,0 +1,10 @@
1
+ README.md
2
+ setup.py
3
+ raqeb/__init__.py
4
+ raqeb/client.py
5
+ raqeb/exceptions.py
6
+ raqeb.egg-info/PKG-INFO
7
+ raqeb.egg-info/SOURCES.txt
8
+ raqeb.egg-info/dependency_links.txt
9
+ raqeb.egg-info/requires.txt
10
+ raqeb.egg-info/top_level.txt
@@ -0,0 +1,7 @@
1
+ requests>=2.25.0
2
+
3
+ [dev]
4
+ pytest>=6.0
5
+ pytest-cov>=2.0
6
+ black>=21.0
7
+ flake8>=3.9
@@ -0,0 +1 @@
1
+ raqeb
raqeb-1.0.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
raqeb-1.0.0/setup.py ADDED
@@ -0,0 +1,42 @@
1
+ """Setup script for Raqeb Python SDK."""
2
+
3
+ from setuptools import setup, find_packages
4
+
5
+ with open("README.md", "r", encoding="utf-8") as fh:
6
+ long_description = fh.read()
7
+
8
+ setup(
9
+ name="raqeb",
10
+ version="1.0.0",
11
+ author="Raqeb",
12
+ author_email="support@raqeb.cloud",
13
+ description="Python SDK for Raqeb Database PAM and Secrets Management",
14
+ long_description=long_description,
15
+ long_description_content_type="text/markdown",
16
+ url="https://github.com/raqeb/python-sdk",
17
+ packages=find_packages(),
18
+ classifiers=[
19
+ "Development Status :: 5 - Production/Stable",
20
+ "Intended Audience :: Developers",
21
+ "Topic :: Software Development :: Libraries :: Python Modules",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.7",
25
+ "Programming Language :: Python :: 3.8",
26
+ "Programming Language :: Python :: 3.9",
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ ],
30
+ python_requires=">=3.7",
31
+ install_requires=[
32
+ "requests>=2.25.0",
33
+ ],
34
+ extras_require={
35
+ "dev": [
36
+ "pytest>=6.0",
37
+ "pytest-cov>=2.0",
38
+ "black>=21.0",
39
+ "flake8>=3.9",
40
+ ],
41
+ },
42
+ )