miso-client 0.2.0__tar.gz → 0.4.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.
Potentially problematic release.
This version of miso-client might be problematic. Click here for more details.
- {miso_client-0.2.0 → miso_client-0.4.0}/CHANGELOG.md +117 -3
- {miso_client-0.2.0/miso_client.egg-info → miso_client-0.4.0}/PKG-INFO +129 -3
- {miso_client-0.2.0 → miso_client-0.4.0}/README.md +128 -2
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/__init__.py +21 -3
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/errors.py +22 -1
- miso_client-0.4.0/miso_client/models/__init__.py +5 -0
- miso_client-0.4.0/miso_client/models/error_response.py +41 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/services/logger.py +7 -6
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/utils/data_masker.py +77 -5
- miso_client-0.4.0/miso_client/utils/http_client.py +585 -0
- miso_client-0.2.0/miso_client/utils/http_client.py → miso_client-0.4.0/miso_client/utils/internal_http_client.py +103 -19
- miso_client-0.4.0/miso_client/utils/sensitive_fields_loader.py +116 -0
- {miso_client-0.2.0 → miso_client-0.4.0/miso_client.egg-info}/PKG-INFO +129 -3
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client.egg-info/SOURCES.txt +4 -1
- {miso_client-0.2.0 → miso_client-0.4.0}/pyproject.toml +1 -1
- {miso_client-0.2.0 → miso_client-0.4.0}/setup.py +1 -1
- miso_client-0.2.0/miso_client/models/__init__.py +0 -1
- {miso_client-0.2.0 → miso_client-0.4.0}/LICENSE +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/MANIFEST.in +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/models/config.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/py.typed +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/services/__init__.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/services/auth.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/services/cache.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/services/encryption.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/services/permission.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/services/redis.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/services/role.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/utils/__init__.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/utils/config_loader.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client/utils/jwt_tools.py +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client.egg-info/dependency_links.txt +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client.egg-info/not-zip-safe +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client.egg-info/requires.txt +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/miso_client.egg-info/top_level.txt +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/pytest.ini +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/requirements-test.txt +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/requirements.txt +0 -0
- {miso_client-0.2.0 → miso_client-0.4.0}/setup.cfg +0 -0
|
@@ -5,7 +5,121 @@ All notable changes to the MisoClient SDK will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.4.0] - 2025-11-02
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **ISO 27001 Compliant HTTP Client with Automatic Audit and Debug Logging**: New public `HttpClient` class that wraps `InternalHttpClient` with automatic ISO 27001 compliant audit and debug logging
|
|
13
|
+
- Automatic audit logging for all HTTP requests (`http.request.{METHOD}` format)
|
|
14
|
+
- Debug logging when `log_level === 'debug'` with detailed request/response information
|
|
15
|
+
- Automatic data masking using `DataMasker` before logging (ISO 27001 compliant)
|
|
16
|
+
- All request headers are masked (Authorization, x-client-token, Cookie, etc.)
|
|
17
|
+
- All request bodies are recursively masked for sensitive fields (password, token, secret, SSN, etc.)
|
|
18
|
+
- All response bodies are masked (limited to first 1000 characters)
|
|
19
|
+
- Query parameters are automatically masked
|
|
20
|
+
- Error messages are masked if they contain sensitive data
|
|
21
|
+
- Sensitive endpoints (`/api/logs`, `/api/auth/token`) are excluded from audit logging to prevent infinite loops
|
|
22
|
+
- JWT user ID extraction from Authorization headers for audit context
|
|
23
|
+
- Request duration tracking for performance monitoring
|
|
24
|
+
- Request/response size tracking for observability
|
|
25
|
+
|
|
26
|
+
- **JSON Configuration Support for DataMasker**: Enhanced `DataMasker` with JSON configuration file support for sensitive fields
|
|
27
|
+
- New `sensitive_fields_config.json` file with default ISO 27001 compliant sensitive fields
|
|
28
|
+
- Categories: authentication, pii, security
|
|
29
|
+
- Support for custom configuration path via `MISO_SENSITIVE_FIELDS_CONFIG` environment variable
|
|
30
|
+
- `DataMasker.set_config_path()` method for programmatic configuration
|
|
31
|
+
- Automatic merging of JSON fields with hardcoded defaults (fallback if JSON cannot be loaded)
|
|
32
|
+
- Backward compatible - existing hardcoded fields still work as fallback
|
|
33
|
+
|
|
34
|
+
- **New InternalHttpClient Class**: Separated core HTTP functionality into `InternalHttpClient` class
|
|
35
|
+
- Pure HTTP functionality with automatic client token management (no logging)
|
|
36
|
+
- Used internally by public `HttpClient` for actual HTTP requests
|
|
37
|
+
- Used by `LoggerService` for sending logs to prevent circular dependencies
|
|
38
|
+
- Not exported in public API (internal use only)
|
|
39
|
+
|
|
40
|
+
- **New sensitive_fields_loader Module**: Utility module for loading and merging sensitive fields configuration
|
|
41
|
+
- `load_sensitive_fields_config()` function for loading JSON configuration
|
|
42
|
+
- `get_sensitive_fields_array()` function for flattened sensitive fields list
|
|
43
|
+
- `get_field_patterns()` function for pattern matching rules
|
|
44
|
+
- Support for custom configuration paths via environment variables
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- **Breaking Change: HttpClient Constructor**: Public `HttpClient` constructor now requires `logger` parameter
|
|
49
|
+
- Old: `HttpClient(config)`
|
|
50
|
+
- New: `HttpClient(config, logger)`
|
|
51
|
+
- This is handled automatically when using `MisoClient` - no changes needed for typical usage
|
|
52
|
+
- Only affects code that directly instantiates `HttpClient`
|
|
53
|
+
|
|
54
|
+
- **Breaking Change: LoggerService Constructor**: `LoggerService` constructor now uses `InternalHttpClient` instead of `HttpClient`
|
|
55
|
+
- Old: `LoggerService(http_client: HttpClient, redis: RedisService)`
|
|
56
|
+
- New: `LoggerService(internal_http_client: InternalHttpClient, redis: RedisService)`
|
|
57
|
+
- This is handled automatically when using `MisoClient` - no changes needed for typical usage
|
|
58
|
+
- Prevents circular dependency (LoggerService uses InternalHttpClient for log sending)
|
|
59
|
+
|
|
60
|
+
- **MisoClient Architecture**: Updated `MisoClient` constructor to use new HttpClient architecture
|
|
61
|
+
- Creates `InternalHttpClient` first (pure HTTP functionality)
|
|
62
|
+
- Creates `LoggerService` with `InternalHttpClient` (prevents circular dependency)
|
|
63
|
+
- Creates public `HttpClient` wrapping `InternalHttpClient` with logger (adds audit/debug logging)
|
|
64
|
+
- All services now use public `HttpClient` with automatic audit logging
|
|
65
|
+
|
|
66
|
+
- **DataMasker Enhancement**: Updated `DataMasker` to load sensitive fields from JSON configuration
|
|
67
|
+
- Maintains backward compatibility with hardcoded fields as fallback
|
|
68
|
+
- Automatic loading on first use with caching
|
|
69
|
+
- Support for custom configuration paths
|
|
70
|
+
|
|
71
|
+
### ISO 27001 Compliance Features
|
|
72
|
+
|
|
73
|
+
- **Automatic Data Masking**: All sensitive data is automatically masked before logging
|
|
74
|
+
- Request headers: Authorization, x-client-token, Cookie, Set-Cookie, and any header containing sensitive keywords
|
|
75
|
+
- Request bodies: Recursively masks password, token, secret, SSN, creditcard, CVV, PIN, OTP, API keys, etc.
|
|
76
|
+
- Response bodies: Especially important for error responses that might contain sensitive data
|
|
77
|
+
- Query parameters: Automatically extracted and masked
|
|
78
|
+
- Error messages: Masked if containing sensitive data
|
|
79
|
+
|
|
80
|
+
- **Audit Log Structure**: Standardized audit log format for all HTTP requests
|
|
81
|
+
- Action: `http.request.{METHOD}` (e.g., `http.request.GET`, `http.request.POST`)
|
|
82
|
+
- Resource: Request URL path
|
|
83
|
+
- Context: method, url, statusCode, duration, userId, requestSize, responseSize, error (all sensitive data masked)
|
|
84
|
+
|
|
85
|
+
- **Debug Log Structure**: Detailed debug logging when `log_level === 'debug'`
|
|
86
|
+
- All audit context fields plus: requestHeaders, responseHeaders, requestBody, responseBody (all masked)
|
|
87
|
+
- Additional context: baseURL, timeout, queryParams (all sensitive data masked)
|
|
88
|
+
|
|
89
|
+
### Technical Improvements
|
|
90
|
+
|
|
91
|
+
- Improved error handling: Logging errors never break HTTP requests (all errors caught and swallowed)
|
|
92
|
+
- Performance: Async logging that doesn't block request/response flow
|
|
93
|
+
- Safety: Sensitive endpoints excluded from audit logging to prevent infinite loops
|
|
94
|
+
- Flexibility: Configurable sensitive fields via JSON configuration file
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## [0.3.0] - 2025-11-01
|
|
99
|
+
|
|
100
|
+
### Added
|
|
101
|
+
|
|
102
|
+
- **Structured Error Response Interface**: Added generic `ErrorResponse` model following RFC 7807-style format for consistent error handling across applications
|
|
103
|
+
- `ErrorResponse` Pydantic model with fields: `errors`, `type`, `title`, `statusCode`, `instance`
|
|
104
|
+
- Automatic parsing of structured error responses from HTTP responses in `HttpClient`
|
|
105
|
+
- Support for both camelCase (`statusCode`) and snake_case (`status_code`) field names
|
|
106
|
+
- `MisoClientError` now includes optional `error_response` field with structured error information
|
|
107
|
+
- Enhanced error messages automatically generated from structured error responses
|
|
108
|
+
- Instance URI automatically extracted from request URL when not provided in response
|
|
109
|
+
- Backward compatible - falls back to traditional `error_body` dict when structured format is not available
|
|
110
|
+
- Export `ErrorResponse` from main module for reuse in other applications
|
|
111
|
+
- Comprehensive test coverage for error response parsing and fallback behavior
|
|
112
|
+
- Full type safety with Pydantic models
|
|
113
|
+
|
|
114
|
+
### Changed
|
|
115
|
+
|
|
116
|
+
- **Error Handling**: `MisoClientError` now prioritizes structured error information when available
|
|
117
|
+
- Error messages are automatically enhanced from structured error responses
|
|
118
|
+
- Status codes are extracted from structured responses when provided
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## [0.2.0] - 2025-10-31
|
|
9
123
|
|
|
10
124
|
### Added
|
|
11
125
|
|
|
@@ -43,7 +157,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
43
157
|
|
|
44
158
|
---
|
|
45
159
|
|
|
46
|
-
## [
|
|
160
|
+
## [0.1.0] - 2025-10-30
|
|
47
161
|
|
|
48
162
|
### Added
|
|
49
163
|
|
|
@@ -82,7 +196,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
82
196
|
|
|
83
197
|
---
|
|
84
198
|
|
|
85
|
-
## [1.0
|
|
199
|
+
## [0.1.0] - 2025-10-01
|
|
86
200
|
|
|
87
201
|
### Added
|
|
88
202
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: miso-client
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Python client SDK for AI Fabrix authentication, authorization, and logging
|
|
5
5
|
Home-page: https://github.com/aifabrix/miso-client-python
|
|
6
6
|
Author: AI Fabrix Team
|
|
@@ -80,10 +80,13 @@ The **AI Fabrix Miso Client SDK** provides authentication, authorization, and lo
|
|
|
80
80
|
### 📊 Compliance & Audit
|
|
81
81
|
|
|
82
82
|
**ISO 27001 Compliance**
|
|
83
|
-
- Comprehensive audit trails for all user actions
|
|
83
|
+
- Comprehensive audit trails for all user actions and HTTP requests
|
|
84
|
+
- Automatic data masking for all sensitive information in logs
|
|
85
|
+
- HTTP request/response audit logging with masked sensitive data
|
|
84
86
|
- Data access logging and monitoring
|
|
85
87
|
- Security event tracking
|
|
86
88
|
- Accountability and non-repudiation
|
|
89
|
+
- Configurable sensitive fields via JSON configuration
|
|
87
90
|
|
|
88
91
|
**Regulatory Compliance**
|
|
89
92
|
- GDPR-ready data protection
|
|
@@ -134,9 +137,13 @@ The **AI Fabrix Miso Client SDK** provides authentication, authorization, and lo
|
|
|
134
137
|
|
|
135
138
|
**Observability**
|
|
136
139
|
- Centralized logging with correlation IDs
|
|
140
|
+
- Automatic HTTP request/response audit logging (ISO 27001 compliant)
|
|
141
|
+
- Debug logging with detailed request/response information (when `log_level='debug'`)
|
|
137
142
|
- Performance tracking and metrics
|
|
138
143
|
- Error tracking and debugging
|
|
139
144
|
- Health monitoring
|
|
145
|
+
- Automatic data masking for sensitive information in logs
|
|
146
|
+
- Configurable sensitive fields via JSON configuration
|
|
140
147
|
|
|
141
148
|
---
|
|
142
149
|
|
|
@@ -262,7 +269,7 @@ if is_admin:
|
|
|
262
269
|
|
|
263
270
|
### Step 5: Activate Logging
|
|
264
271
|
|
|
265
|
-
**What happens:** Application logs are sent to the Miso Controller with client token authentication.
|
|
272
|
+
**What happens:** Application logs are sent to the Miso Controller with client token authentication. All HTTP requests are automatically audited with ISO 27001 compliant data masking.
|
|
266
273
|
|
|
267
274
|
```python
|
|
268
275
|
from miso_client import MisoClient, load_config
|
|
@@ -278,10 +285,17 @@ user = await client.get_user(token)
|
|
|
278
285
|
await client.log.info('User accessed dashboard', {'userId': user.id if user else None})
|
|
279
286
|
await client.log.error('Operation failed', {'error': str(err)})
|
|
280
287
|
await client.log.warn('Unusual activity', {'details': '...'})
|
|
288
|
+
|
|
289
|
+
# HTTP requests are automatically audited
|
|
290
|
+
# All sensitive data is automatically masked before logging
|
|
291
|
+
result = await client.http_client.get('/api/users')
|
|
292
|
+
# This automatically creates an audit log: http.request.GET with masked sensitive data
|
|
281
293
|
```
|
|
282
294
|
|
|
283
295
|
**What happens to logs?** They're sent to the Miso Controller for centralized monitoring and analysis. Client token is automatically included.
|
|
284
296
|
|
|
297
|
+
**ISO 27001 Compliance:** All HTTP requests are automatically audited with sensitive data masked. Set `log_level='debug'` to enable detailed request/response logging (all sensitive data is still masked).
|
|
298
|
+
|
|
285
299
|
→ [Complete logging example](examples/step-5-logging.py)
|
|
286
300
|
→ [Logging Reference](docs/api-reference.md#logger-service)
|
|
287
301
|
|
|
@@ -414,6 +428,7 @@ config = MisoClientConfig(
|
|
|
414
428
|
port=6379,
|
|
415
429
|
),
|
|
416
430
|
log_level="info", # Optional: 'debug' | 'info' | 'warn' | 'error'
|
|
431
|
+
# Set to 'debug' for detailed HTTP request/response logging
|
|
417
432
|
api_key="your-test-api-key", # Optional: API key for testing (bypasses OAuth2)
|
|
418
433
|
cache={ # Optional: Cache TTL settings
|
|
419
434
|
"role_ttl": 900, # Role cache TTL (default: 900s)
|
|
@@ -424,6 +439,18 @@ config = MisoClientConfig(
|
|
|
424
439
|
|
|
425
440
|
**Recommended:** Use `load_config()` to load from `.env` file automatically.
|
|
426
441
|
|
|
442
|
+
**ISO 27001 Data Masking Configuration:**
|
|
443
|
+
|
|
444
|
+
Sensitive fields are configured via `miso_client/utils/sensitive_fields_config.json`. You can customize this by:
|
|
445
|
+
|
|
446
|
+
1. Setting `MISO_SENSITIVE_FIELDS_CONFIG` environment variable to point to a custom JSON file
|
|
447
|
+
2. Using `DataMasker.set_config_path()` to set a custom path programmatically
|
|
448
|
+
|
|
449
|
+
The default configuration includes ISO 27001 compliant sensitive fields:
|
|
450
|
+
- Authentication: password, token, secret, key, auth, authorization
|
|
451
|
+
- PII: ssn, creditcard, cc, cvv, pin, otp
|
|
452
|
+
- Security: apikey, accesstoken, refreshtoken, privatekey, secretkey, cookie, session
|
|
453
|
+
|
|
427
454
|
→ [Complete Configuration Reference](docs/configuration.md)
|
|
428
455
|
|
|
429
456
|
---
|
|
@@ -448,6 +475,28 @@ The SDK consists of five core services:
|
|
|
448
475
|
- **LoggerService** - Centralized logging with API key authentication
|
|
449
476
|
- **RedisService** - Caching and queue management (optional)
|
|
450
477
|
|
|
478
|
+
### HTTP Client Architecture
|
|
479
|
+
|
|
480
|
+
The SDK uses a two-layer HTTP client architecture for ISO 27001 compliance:
|
|
481
|
+
|
|
482
|
+
- **InternalHttpClient** - Core HTTP functionality with automatic client token management (internal)
|
|
483
|
+
- **HttpClient** - Public wrapper that adds automatic ISO 27001 compliant audit and debug logging
|
|
484
|
+
|
|
485
|
+
**Features:**
|
|
486
|
+
- Automatic audit logging for all HTTP requests (`http.request.{METHOD}`)
|
|
487
|
+
- Debug logging when `log_level === 'debug'` with detailed request/response information
|
|
488
|
+
- Automatic data masking using `DataMasker` before logging (ISO 27001 compliant)
|
|
489
|
+
- Sensitive endpoints (`/api/logs`, `/api/auth/token`) are excluded from audit logging to prevent infinite loops
|
|
490
|
+
- All sensitive data (headers, bodies, query params) is automatically masked before logging
|
|
491
|
+
|
|
492
|
+
**ISO 27001 Compliance:**
|
|
493
|
+
- All request headers are masked (Authorization, x-client-token, Cookie, etc.)
|
|
494
|
+
- All request bodies are recursively masked for sensitive fields (password, token, secret, SSN, etc.)
|
|
495
|
+
- All response bodies are masked (limited to first 1000 characters)
|
|
496
|
+
- Query parameters are automatically masked
|
|
497
|
+
- Error messages are masked if they contain sensitive data
|
|
498
|
+
- Sensitive fields configuration can be customized via `sensitive_fields_config.json`
|
|
499
|
+
|
|
451
500
|
→ [Architecture Details](docs/api-reference.md#architecture)
|
|
452
501
|
|
|
453
502
|
---
|
|
@@ -485,6 +534,83 @@ The SDK consists of five core services:
|
|
|
485
534
|
- [Flask Decorators](docs/examples.md#flask-decorators) - Decorator-based auth
|
|
486
535
|
- [Error Handling](docs/examples.md#error-handling) - Best practices
|
|
487
536
|
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
### Structured Error Responses
|
|
540
|
+
|
|
541
|
+
**What happens:** The SDK automatically parses structured error responses from the API (RFC 7807-style format) and makes them available through the `MisoClientError` exception.
|
|
542
|
+
|
|
543
|
+
```python
|
|
544
|
+
from miso_client import MisoClient, MisoClientError, ErrorResponse, load_config
|
|
545
|
+
|
|
546
|
+
client = MisoClient(load_config())
|
|
547
|
+
await client.initialize()
|
|
548
|
+
|
|
549
|
+
try:
|
|
550
|
+
result = await client.http_client.get("/api/some-endpoint")
|
|
551
|
+
except MisoClientError as e:
|
|
552
|
+
# Check if structured error response is available
|
|
553
|
+
if e.error_response:
|
|
554
|
+
print(f"Error Type: {e.error_response.type}")
|
|
555
|
+
print(f"Error Title: {e.error_response.title}")
|
|
556
|
+
print(f"Status Code: {e.error_response.statusCode}")
|
|
557
|
+
print(f"Errors: {e.error_response.errors}")
|
|
558
|
+
print(f"Instance: {e.error_response.instance}")
|
|
559
|
+
else:
|
|
560
|
+
# Fallback to traditional error handling
|
|
561
|
+
print(f"Error: {e.message}")
|
|
562
|
+
print(f"Status Code: {e.status_code}")
|
|
563
|
+
print(f"Error Body: {e.error_body}")
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**Error Response Structure:**
|
|
567
|
+
|
|
568
|
+
The `ErrorResponse` model follows RFC 7807-style format:
|
|
569
|
+
|
|
570
|
+
```json
|
|
571
|
+
{
|
|
572
|
+
"errors": [
|
|
573
|
+
"The user has provided input that the browser is unable to convert.",
|
|
574
|
+
"There are multiple rows in the database for the same value"
|
|
575
|
+
],
|
|
576
|
+
"type": "/Errors/Bad Input",
|
|
577
|
+
"title": "Bad Request",
|
|
578
|
+
"statusCode": 400,
|
|
579
|
+
"instance": "/OpenApi/rest/Xzy"
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
**Features:**
|
|
584
|
+
|
|
585
|
+
- **Automatic Parsing**: Structured error responses are automatically parsed from HTTP responses
|
|
586
|
+
- **Backward Compatible**: Falls back to traditional error handling when structured format is not available
|
|
587
|
+
- **Type Safety**: Full type hints with Pydantic models for reliable error handling
|
|
588
|
+
- **Generic Interface**: `ErrorResponse` model can be reused across different applications
|
|
589
|
+
- **Instance URI**: Automatically extracted from request URL if not provided in response
|
|
590
|
+
|
|
591
|
+
**Using ErrorResponse directly:**
|
|
592
|
+
|
|
593
|
+
```python
|
|
594
|
+
from miso_client import ErrorResponse
|
|
595
|
+
|
|
596
|
+
# Create ErrorResponse from dict
|
|
597
|
+
error_data = {
|
|
598
|
+
"errors": ["Validation failed"],
|
|
599
|
+
"type": "/Errors/Validation",
|
|
600
|
+
"title": "Validation Error",
|
|
601
|
+
"statusCode": 422,
|
|
602
|
+
"instance": "/api/endpoint"
|
|
603
|
+
}
|
|
604
|
+
error_response = ErrorResponse(**error_data)
|
|
605
|
+
|
|
606
|
+
# Access fields
|
|
607
|
+
print(error_response.errors) # ["Validation failed"]
|
|
608
|
+
print(error_response.type) # "/Errors/Validation"
|
|
609
|
+
print(error_response.title) # "Validation Error"
|
|
610
|
+
print(error_response.statusCode) # 422
|
|
611
|
+
print(error_response.instance) # "/api/endpoint"
|
|
612
|
+
```
|
|
613
|
+
|
|
488
614
|
### Common Tasks
|
|
489
615
|
|
|
490
616
|
**Add authentication middleware (FastAPI):**
|
|
@@ -31,10 +31,13 @@ The **AI Fabrix Miso Client SDK** provides authentication, authorization, and lo
|
|
|
31
31
|
### 📊 Compliance & Audit
|
|
32
32
|
|
|
33
33
|
**ISO 27001 Compliance**
|
|
34
|
-
- Comprehensive audit trails for all user actions
|
|
34
|
+
- Comprehensive audit trails for all user actions and HTTP requests
|
|
35
|
+
- Automatic data masking for all sensitive information in logs
|
|
36
|
+
- HTTP request/response audit logging with masked sensitive data
|
|
35
37
|
- Data access logging and monitoring
|
|
36
38
|
- Security event tracking
|
|
37
39
|
- Accountability and non-repudiation
|
|
40
|
+
- Configurable sensitive fields via JSON configuration
|
|
38
41
|
|
|
39
42
|
**Regulatory Compliance**
|
|
40
43
|
- GDPR-ready data protection
|
|
@@ -85,9 +88,13 @@ The **AI Fabrix Miso Client SDK** provides authentication, authorization, and lo
|
|
|
85
88
|
|
|
86
89
|
**Observability**
|
|
87
90
|
- Centralized logging with correlation IDs
|
|
91
|
+
- Automatic HTTP request/response audit logging (ISO 27001 compliant)
|
|
92
|
+
- Debug logging with detailed request/response information (when `log_level='debug'`)
|
|
88
93
|
- Performance tracking and metrics
|
|
89
94
|
- Error tracking and debugging
|
|
90
95
|
- Health monitoring
|
|
96
|
+
- Automatic data masking for sensitive information in logs
|
|
97
|
+
- Configurable sensitive fields via JSON configuration
|
|
91
98
|
|
|
92
99
|
---
|
|
93
100
|
|
|
@@ -213,7 +220,7 @@ if is_admin:
|
|
|
213
220
|
|
|
214
221
|
### Step 5: Activate Logging
|
|
215
222
|
|
|
216
|
-
**What happens:** Application logs are sent to the Miso Controller with client token authentication.
|
|
223
|
+
**What happens:** Application logs are sent to the Miso Controller with client token authentication. All HTTP requests are automatically audited with ISO 27001 compliant data masking.
|
|
217
224
|
|
|
218
225
|
```python
|
|
219
226
|
from miso_client import MisoClient, load_config
|
|
@@ -229,10 +236,17 @@ user = await client.get_user(token)
|
|
|
229
236
|
await client.log.info('User accessed dashboard', {'userId': user.id if user else None})
|
|
230
237
|
await client.log.error('Operation failed', {'error': str(err)})
|
|
231
238
|
await client.log.warn('Unusual activity', {'details': '...'})
|
|
239
|
+
|
|
240
|
+
# HTTP requests are automatically audited
|
|
241
|
+
# All sensitive data is automatically masked before logging
|
|
242
|
+
result = await client.http_client.get('/api/users')
|
|
243
|
+
# This automatically creates an audit log: http.request.GET with masked sensitive data
|
|
232
244
|
```
|
|
233
245
|
|
|
234
246
|
**What happens to logs?** They're sent to the Miso Controller for centralized monitoring and analysis. Client token is automatically included.
|
|
235
247
|
|
|
248
|
+
**ISO 27001 Compliance:** All HTTP requests are automatically audited with sensitive data masked. Set `log_level='debug'` to enable detailed request/response logging (all sensitive data is still masked).
|
|
249
|
+
|
|
236
250
|
→ [Complete logging example](examples/step-5-logging.py)
|
|
237
251
|
→ [Logging Reference](docs/api-reference.md#logger-service)
|
|
238
252
|
|
|
@@ -365,6 +379,7 @@ config = MisoClientConfig(
|
|
|
365
379
|
port=6379,
|
|
366
380
|
),
|
|
367
381
|
log_level="info", # Optional: 'debug' | 'info' | 'warn' | 'error'
|
|
382
|
+
# Set to 'debug' for detailed HTTP request/response logging
|
|
368
383
|
api_key="your-test-api-key", # Optional: API key for testing (bypasses OAuth2)
|
|
369
384
|
cache={ # Optional: Cache TTL settings
|
|
370
385
|
"role_ttl": 900, # Role cache TTL (default: 900s)
|
|
@@ -375,6 +390,18 @@ config = MisoClientConfig(
|
|
|
375
390
|
|
|
376
391
|
**Recommended:** Use `load_config()` to load from `.env` file automatically.
|
|
377
392
|
|
|
393
|
+
**ISO 27001 Data Masking Configuration:**
|
|
394
|
+
|
|
395
|
+
Sensitive fields are configured via `miso_client/utils/sensitive_fields_config.json`. You can customize this by:
|
|
396
|
+
|
|
397
|
+
1. Setting `MISO_SENSITIVE_FIELDS_CONFIG` environment variable to point to a custom JSON file
|
|
398
|
+
2. Using `DataMasker.set_config_path()` to set a custom path programmatically
|
|
399
|
+
|
|
400
|
+
The default configuration includes ISO 27001 compliant sensitive fields:
|
|
401
|
+
- Authentication: password, token, secret, key, auth, authorization
|
|
402
|
+
- PII: ssn, creditcard, cc, cvv, pin, otp
|
|
403
|
+
- Security: apikey, accesstoken, refreshtoken, privatekey, secretkey, cookie, session
|
|
404
|
+
|
|
378
405
|
→ [Complete Configuration Reference](docs/configuration.md)
|
|
379
406
|
|
|
380
407
|
---
|
|
@@ -399,6 +426,28 @@ The SDK consists of five core services:
|
|
|
399
426
|
- **LoggerService** - Centralized logging with API key authentication
|
|
400
427
|
- **RedisService** - Caching and queue management (optional)
|
|
401
428
|
|
|
429
|
+
### HTTP Client Architecture
|
|
430
|
+
|
|
431
|
+
The SDK uses a two-layer HTTP client architecture for ISO 27001 compliance:
|
|
432
|
+
|
|
433
|
+
- **InternalHttpClient** - Core HTTP functionality with automatic client token management (internal)
|
|
434
|
+
- **HttpClient** - Public wrapper that adds automatic ISO 27001 compliant audit and debug logging
|
|
435
|
+
|
|
436
|
+
**Features:**
|
|
437
|
+
- Automatic audit logging for all HTTP requests (`http.request.{METHOD}`)
|
|
438
|
+
- Debug logging when `log_level === 'debug'` with detailed request/response information
|
|
439
|
+
- Automatic data masking using `DataMasker` before logging (ISO 27001 compliant)
|
|
440
|
+
- Sensitive endpoints (`/api/logs`, `/api/auth/token`) are excluded from audit logging to prevent infinite loops
|
|
441
|
+
- All sensitive data (headers, bodies, query params) is automatically masked before logging
|
|
442
|
+
|
|
443
|
+
**ISO 27001 Compliance:**
|
|
444
|
+
- All request headers are masked (Authorization, x-client-token, Cookie, etc.)
|
|
445
|
+
- All request bodies are recursively masked for sensitive fields (password, token, secret, SSN, etc.)
|
|
446
|
+
- All response bodies are masked (limited to first 1000 characters)
|
|
447
|
+
- Query parameters are automatically masked
|
|
448
|
+
- Error messages are masked if they contain sensitive data
|
|
449
|
+
- Sensitive fields configuration can be customized via `sensitive_fields_config.json`
|
|
450
|
+
|
|
402
451
|
→ [Architecture Details](docs/api-reference.md#architecture)
|
|
403
452
|
|
|
404
453
|
---
|
|
@@ -436,6 +485,83 @@ The SDK consists of five core services:
|
|
|
436
485
|
- [Flask Decorators](docs/examples.md#flask-decorators) - Decorator-based auth
|
|
437
486
|
- [Error Handling](docs/examples.md#error-handling) - Best practices
|
|
438
487
|
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
### Structured Error Responses
|
|
491
|
+
|
|
492
|
+
**What happens:** The SDK automatically parses structured error responses from the API (RFC 7807-style format) and makes them available through the `MisoClientError` exception.
|
|
493
|
+
|
|
494
|
+
```python
|
|
495
|
+
from miso_client import MisoClient, MisoClientError, ErrorResponse, load_config
|
|
496
|
+
|
|
497
|
+
client = MisoClient(load_config())
|
|
498
|
+
await client.initialize()
|
|
499
|
+
|
|
500
|
+
try:
|
|
501
|
+
result = await client.http_client.get("/api/some-endpoint")
|
|
502
|
+
except MisoClientError as e:
|
|
503
|
+
# Check if structured error response is available
|
|
504
|
+
if e.error_response:
|
|
505
|
+
print(f"Error Type: {e.error_response.type}")
|
|
506
|
+
print(f"Error Title: {e.error_response.title}")
|
|
507
|
+
print(f"Status Code: {e.error_response.statusCode}")
|
|
508
|
+
print(f"Errors: {e.error_response.errors}")
|
|
509
|
+
print(f"Instance: {e.error_response.instance}")
|
|
510
|
+
else:
|
|
511
|
+
# Fallback to traditional error handling
|
|
512
|
+
print(f"Error: {e.message}")
|
|
513
|
+
print(f"Status Code: {e.status_code}")
|
|
514
|
+
print(f"Error Body: {e.error_body}")
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
**Error Response Structure:**
|
|
518
|
+
|
|
519
|
+
The `ErrorResponse` model follows RFC 7807-style format:
|
|
520
|
+
|
|
521
|
+
```json
|
|
522
|
+
{
|
|
523
|
+
"errors": [
|
|
524
|
+
"The user has provided input that the browser is unable to convert.",
|
|
525
|
+
"There are multiple rows in the database for the same value"
|
|
526
|
+
],
|
|
527
|
+
"type": "/Errors/Bad Input",
|
|
528
|
+
"title": "Bad Request",
|
|
529
|
+
"statusCode": 400,
|
|
530
|
+
"instance": "/OpenApi/rest/Xzy"
|
|
531
|
+
}
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
**Features:**
|
|
535
|
+
|
|
536
|
+
- **Automatic Parsing**: Structured error responses are automatically parsed from HTTP responses
|
|
537
|
+
- **Backward Compatible**: Falls back to traditional error handling when structured format is not available
|
|
538
|
+
- **Type Safety**: Full type hints with Pydantic models for reliable error handling
|
|
539
|
+
- **Generic Interface**: `ErrorResponse` model can be reused across different applications
|
|
540
|
+
- **Instance URI**: Automatically extracted from request URL if not provided in response
|
|
541
|
+
|
|
542
|
+
**Using ErrorResponse directly:**
|
|
543
|
+
|
|
544
|
+
```python
|
|
545
|
+
from miso_client import ErrorResponse
|
|
546
|
+
|
|
547
|
+
# Create ErrorResponse from dict
|
|
548
|
+
error_data = {
|
|
549
|
+
"errors": ["Validation failed"],
|
|
550
|
+
"type": "/Errors/Validation",
|
|
551
|
+
"title": "Validation Error",
|
|
552
|
+
"statusCode": 422,
|
|
553
|
+
"instance": "/api/endpoint"
|
|
554
|
+
}
|
|
555
|
+
error_response = ErrorResponse(**error_data)
|
|
556
|
+
|
|
557
|
+
# Access fields
|
|
558
|
+
print(error_response.errors) # ["Validation failed"]
|
|
559
|
+
print(error_response.type) # "/Errors/Validation"
|
|
560
|
+
print(error_response.title) # "Validation Error"
|
|
561
|
+
print(error_response.statusCode) # 422
|
|
562
|
+
print(error_response.instance) # "/api/endpoint"
|
|
563
|
+
```
|
|
564
|
+
|
|
439
565
|
### Common Tasks
|
|
440
566
|
|
|
441
567
|
**Add authentication middleware (FastAPI):**
|
|
@@ -26,6 +26,7 @@ from .models.config import (
|
|
|
26
26
|
RoleResult,
|
|
27
27
|
UserInfo,
|
|
28
28
|
)
|
|
29
|
+
from .models.error_response import ErrorResponse
|
|
29
30
|
from .services.auth import AuthService
|
|
30
31
|
from .services.cache import CacheService
|
|
31
32
|
from .services.encryption import EncryptionService
|
|
@@ -35,8 +36,9 @@ from .services.redis import RedisService
|
|
|
35
36
|
from .services.role import RoleService
|
|
36
37
|
from .utils.config_loader import load_config
|
|
37
38
|
from .utils.http_client import HttpClient
|
|
39
|
+
from .utils.internal_http_client import InternalHttpClient
|
|
38
40
|
|
|
39
|
-
__version__ = "0.
|
|
41
|
+
__version__ = "0.4.0"
|
|
40
42
|
__author__ = "AI Fabrix Team"
|
|
41
43
|
__license__ = "MIT"
|
|
42
44
|
|
|
@@ -60,14 +62,29 @@ class MisoClient:
|
|
|
60
62
|
config: MisoClient configuration including controller URL, client credentials, etc.
|
|
61
63
|
"""
|
|
62
64
|
self.config = config
|
|
63
|
-
|
|
65
|
+
|
|
66
|
+
# Create InternalHttpClient first (pure HTTP functionality, no logging)
|
|
67
|
+
self._internal_http_client = InternalHttpClient(config)
|
|
68
|
+
|
|
69
|
+
# Create Redis service
|
|
64
70
|
self.redis = RedisService(config.redis)
|
|
71
|
+
|
|
72
|
+
# Create LoggerService with InternalHttpClient (to avoid circular dependency)
|
|
73
|
+
# LoggerService uses InternalHttpClient for sending logs to prevent audit loops
|
|
74
|
+
self.logger = LoggerService(self._internal_http_client, self.redis)
|
|
75
|
+
|
|
76
|
+
# Create public HttpClient wrapping InternalHttpClient with logger
|
|
77
|
+
# This HttpClient adds automatic ISO 27001 compliant audit and debug logging
|
|
78
|
+
self.http_client = HttpClient(config, self.logger)
|
|
79
|
+
|
|
65
80
|
# Cache service (uses Redis if available, falls back to in-memory)
|
|
66
81
|
self.cache = CacheService(self.redis)
|
|
82
|
+
|
|
83
|
+
# Services use public HttpClient (with audit logging)
|
|
67
84
|
self.auth = AuthService(self.http_client, self.redis)
|
|
68
85
|
self.roles = RoleService(self.http_client, self.cache)
|
|
69
86
|
self.permissions = PermissionService(self.http_client, self.cache)
|
|
70
|
-
|
|
87
|
+
|
|
71
88
|
# Encryption service (reads ENCRYPTION_KEY from environment by default)
|
|
72
89
|
self.encryption = EncryptionService()
|
|
73
90
|
self.initialized = False
|
|
@@ -473,6 +490,7 @@ __all__ = [
|
|
|
473
490
|
"ClientTokenResponse",
|
|
474
491
|
"PerformanceMetrics",
|
|
475
492
|
"ClientLoggingOptions",
|
|
493
|
+
"ErrorResponse",
|
|
476
494
|
"AuthService",
|
|
477
495
|
"RoleService",
|
|
478
496
|
"PermissionService",
|
|
@@ -4,12 +4,21 @@ SDK exceptions and error handling.
|
|
|
4
4
|
This module defines custom exceptions for the MisoClient SDK.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from ..models.error_response import ErrorResponse
|
|
11
|
+
|
|
7
12
|
|
|
8
13
|
class MisoClientError(Exception):
|
|
9
14
|
"""Base exception for MisoClient SDK errors."""
|
|
10
15
|
|
|
11
16
|
def __init__(
|
|
12
|
-
self,
|
|
17
|
+
self,
|
|
18
|
+
message: str,
|
|
19
|
+
status_code: int | None = None,
|
|
20
|
+
error_body: dict | None = None,
|
|
21
|
+
error_response: "ErrorResponse | None" = None,
|
|
13
22
|
):
|
|
14
23
|
"""
|
|
15
24
|
Initialize MisoClient error.
|
|
@@ -18,11 +27,23 @@ class MisoClientError(Exception):
|
|
|
18
27
|
message: Error message
|
|
19
28
|
status_code: HTTP status code if applicable
|
|
20
29
|
error_body: Sanitized error response body (secrets masked)
|
|
30
|
+
error_response: Structured error response object (RFC 7807-style)
|
|
21
31
|
"""
|
|
22
32
|
super().__init__(message)
|
|
23
33
|
self.message = message
|
|
24
34
|
self.status_code = status_code
|
|
25
35
|
self.error_body = error_body if error_body is not None else None
|
|
36
|
+
self.error_response = error_response
|
|
37
|
+
|
|
38
|
+
# Enhance message with structured error information if available
|
|
39
|
+
if error_response and error_response.errors:
|
|
40
|
+
if len(error_response.errors) == 1:
|
|
41
|
+
self.message = error_response.errors[0]
|
|
42
|
+
else:
|
|
43
|
+
self.message = f"{error_response.title}: {'; '.join(error_response.errors)}"
|
|
44
|
+
# Override status_code from structured response if available
|
|
45
|
+
if error_response.statusCode:
|
|
46
|
+
self.status_code = error_response.statusCode
|
|
26
47
|
|
|
27
48
|
|
|
28
49
|
class AuthenticationError(MisoClientError):
|