microburst 0.1.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.
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ - package-ecosystem: github-actions
8
+ directory: /
9
+ schedule:
10
+ interval: weekly
@@ -0,0 +1,24 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python: ["3.10", "3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v5
17
+ - name: Install Python
18
+ run: uv python install ${{ matrix.python }}
19
+ - name: Install
20
+ run: uv pip install --python ${{ matrix.python }} --system -e ".[test]"
21
+ - name: Lint
22
+ run: uvx ruff check src/ tests/
23
+ - name: Test
24
+ run: uv run --python ${{ matrix.python }} --no-project --with-editable . --with pytest --with boto3 python -m pytest tests/ -q
@@ -0,0 +1,22 @@
1
+ name: release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ id-token: write # PyPI trusted publishing (OIDC) — no stored token
9
+
10
+ jobs:
11
+ publish:
12
+ runs-on: ubuntu-latest
13
+ environment:
14
+ name: pypi
15
+ url: https://pypi.org/p/microburst
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: astral-sh/setup-uv@v5
19
+ - name: Build
20
+ run: uv build
21
+ - name: Publish to PyPI
22
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,7 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .pytest_cache/
7
+ .ruff_cache/
@@ -0,0 +1,20 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ uv venv && uv pip install -e ".[test]"
7
+ pytest
8
+ ruff check src/ tests/
9
+ ```
10
+
11
+ ## Conventions
12
+
13
+ - Error shapes, operation metadata and protocols come from **botocore service
14
+ models** — don't hand-maintain parallel tables if the model can answer.
15
+ - Wire formats must match what AWS SDKs parse. When changing error
16
+ serialization, verify against a real `boto3` client (see `tests/`).
17
+ - Keep matchers deterministic and observable: every decision should show up
18
+ in `/_microburst/fired` or not happen at all.
19
+ - The control API is intentionally unauthenticated (local dev tool). Don't
20
+ add features that make it safe to expose — document instead.
@@ -0,0 +1,251 @@
1
+ # aws-chaos-proxy — Exploración profunda
2
+
3
+ **Fecha:** 2026-10-07
4
+ **Estado:** MVP implementado como `microburst` (este directorio). 26 tests verdes,
5
+ smoke test end-to-end contra MiniStack verificado (pass-through + throttle
6
+ con retry del SDK + fired log).
7
+ **TL;DR:** no existe ningún proxy standalone protocol-aware para inyectar fallas
8
+ en llamadas a la API de AWS. Todos los que lo hacen lo tienen *embebido en su
9
+ propio emulador* (y el más conocido, LocalStack, lo vende en tier Enterprise).
10
+ El hueco es real, técnico, y defendible.
11
+
12
+ ---
13
+
14
+ ## 1. El problema
15
+
16
+ Todo equipo que escribe código sobre AWS necesita responder: "¿qué pasa cuando
17
+ DynamoDB throttlea? ¿cuando SQS tiene 3s de latencia? ¿cuando Lambda devuelve
18
+ 503?" Las opciones actuales son todas malas:
19
+
20
+ - **AWS FIS** — real AWS only, procedural (crear experiment template, correr,
21
+ esperar minutos), nivel infraestructura, cuesta plata, no sirve para el loop
22
+ dev ni para CI.
23
+ - **Toxiproxy / fault / saboteur / chaosproxy** — proxies TCP/HTTP genéricos.
24
+ Pueden cortar conexiones y agregar latencia, pero **no pueden devolver un
25
+ `ProvisionedThroughputExceededException` con la forma correcta** para que el
26
+ SDK lo clasifique como throttling retriable.
27
+ - **DIY SDK middleware** — la respuesta oficial de AWS. En
28
+ awslabs/aws-sdk-rust discussion #542, ante "¿cómo inyecto fallas para chaos
29
+ testing?", la respuesta del equipo del SDK es literalmente "escribí tu propio
30
+ connector o armate un proxy". Cada equipo reinventa esto.
31
+
32
+ ## 2. Panorama competitivo (verificado 2026-10)
33
+
34
+ ### Fault injection *embebido en emuladores* — todos
35
+
36
+ | Proyecto | Fault injection | Licencia/acceso | Problema |
37
+ |---|---|---|---|
38
+ | **LocalStack Chaos API** | `/_localstack/chaos/faults`: reglas por region/service/operation + probabilidad + error custom + latency via `/chaos/effects` | **Tier Enterprise** (verificado en docs) | Solo si pagás LocalStack Enterprise |
39
+ | **CloudMock** | `InjectFault(service, action, type)` — throttle, latency, timeout, blackhole, error + % | Source-available (NOASSERTION), no OSS | Embebido en su emulador; licencia no-OSI |
40
+ | **awsim** (QaidVoid) | Chaos engine con presets (`flaky-s3`, `ddb-throttle`, `kms-outage`...) | OSS | Embebido en su emulador |
41
+ | **local-web-services** | `lws chaos enable/set` — error-rate, latency, timeout, conn-reset; errores service-aware (JSON vs XML) | OSS | Embebido en su emulador |
42
+ | **MiniStack** | **No tiene** (verificado: 0 hits de chaos/fault-inject en el código) | MIT | Oportunidad de feature o proyecto hermano |
43
+
44
+ ### Proxies genéricos — ninguno AWS-aware
45
+
46
+ | Proyecto | Nivel | Limitación |
47
+ |---|---|---|
48
+ | Toxiproxy (Shopify) | TCP | Sin noción de servicio/operación; errores no con forma AWS |
49
+ | `fault` (fault-project) | TCP/UDP/DNS | Idem; buen engine pero ciego al protocolo |
50
+ | saboteur | HTTP | Reglas por URL/method/headers; bodies genéricos |
51
+ | chaosproxy (josephwoodward) | HTTP | Match por regex de host/path; status codes genéricos |
52
+ | rodriguez | HTTP + mocks S3/SQS | Harness de test, no proxy protocol-aware |
53
+
54
+ ### Por qué "error con forma correcta" es EL diferenciador
55
+
56
+ botocore (y todos los SDKs, que comparten la spec de retry) clasifican errores
57
+ **parseando el código de error del body**, no solo el status HTTP:
58
+
59
+ - Modo `standard` reintenta: códigos `Throttling`, `ThrottlingException`,
60
+ `ProvisionedThroughputExceededException`, `SlowDown`, `RequestLimitExceeded`,
61
+ `TransactionInProgressException`, ... + status 500/502/503/504 + errores de
62
+ conexión.
63
+ - `ModeledRetryableChecker`: cada servicio puede marcar sus propias excepciones
64
+ como retriables **en el service model** — o sea, el set correcto de errores
65
+ retriables está definido por Smithy/botocore models.
66
+ - `x-amz-retry-after` (milisegundos) se incorpora al backoff; `Retry-After`
67
+ estándar **se ignora** (boto3 lo descarta explícitamente).
68
+ - Un 429 genérico con body vacío **no** se clasifica como throttling — cae en
69
+ el bucket genérico de status code. La diferencia cambia el backoff base
70
+ (1s para throttling vs 50ms para transient) y el comportamiento de adaptive
71
+ mode (client-side rate limiting solo reacciona a respuestas clasificadas
72
+ como throttling).
73
+
74
+ Conclusión técnica: un proxy protocol-aware puede emitir fallos que el SDK trata
75
+ **exactamente como fallos reales de AWS**, ejercitando retry/backoff/circuit
76
+ breaker/adaptive rate limiting de verdad. Un proxy genérico no.
77
+
78
+ ## 3. Cómo se detecta servicio + operación (evidencia: MiniStack router)
79
+
80
+ El mismo razonamiento que usa MiniStack's `core/router.py` aplica al proxy:
81
+
82
+ 1. **Credential scope** del header `Authorization: AWS4-HMAC-SHA256
83
+ Credential=AKIA.../20261007/us-east-1/dynamodb/aws4_request` → servicio +
84
+ región firmados. Infalible para SDKs.
85
+ 2. **`X-Amz-Target: DynamoDB_20120810.PutItem`** → servicio + operación exacta
86
+ para todos los servicios JSON protocol (DynamoDB, Kinesis, SSM,
87
+ SecretsManager, Logs, Step Functions, KMS, Cognito...).
88
+ 3. **Query protocol** (SQS, SNS, IAM, STS, EC2, RDS...): `Action=` +
89
+ `Version=` en body form-encoded o query string.
90
+ 4. **REST-JSON / REST-XML** (API Gateway, Lambda control plane, S3): método +
91
+ path pattern contra las rutas del service model.
92
+ 5. **Host header** como fallback.
93
+
94
+ Los edge cases existen pero son conocidos y acotados (MiniStack ya los
95
+ catalogó: `streams.dynamodb` vs `dynamodb`, iot-jobs-data vs iot-data,
96
+ bedrock-runtime vs bedrock, etc.). El service→protocol mapping sale directo
97
+ de los service models de botocore (`metadata.protocol`: `json`, `query`,
98
+ `rest-xml`, `rest-json`, `ec2`).
99
+
100
+ ## 4. Formatos de error por protocolo
101
+
102
+ | Protocol | Servicios ejemplo | Forma del error |
103
+ |---|---|---|
104
+ | `json` (1.0/1.1) | DynamoDB, Kinesis, SSM, Logs, States, KMS | `{"__type": "ProvisionedThroughputExceededException", "message": "..."}` + a veces `x-amzn-ErrorType` header |
105
+ | `query` | SQS, SNS, IAM, STS, EC2, RDS, CloudWatch | XML `<ErrorResponse><Error><Code>Throttling</Code><Message>...` |
106
+ | `rest-xml` | S3, CloudFront, Route53 | XML `<Error><Code>SlowDown</Code><Message>...` + `x-amz-request-id` + `x-amz-id-2` |
107
+ | `rest-json` | API Gateway v2, Lambda control, EKS | `{"message": "..."}` + `x-amzn-errortype: TooManyRequestsException` header |
108
+ | `ec2` | EC2 legacy | Variante query XML |
109
+
110
+ Detalles que importan para el realismo: `x-amzn-RequestId` /
111
+ `x-amz-request-id` con formato plausible, `x-amz-id-2` para S3,
112
+ `Content-Type` correcto (`application/x-amz-json-1.0`, `text/xml`), y para
113
+ JSON protocol el `__type` a veces lleva prefijo del shape
114
+ (`com.amazonaws.dynamodb.v20120810#ProvisionedThroughputExceededException`).
115
+
116
+ ## 5. SigV4 y el problema del proxy
117
+
118
+ El SDK firma la request incluyendo el `host` en los SignedHeaders. Tres modos:
119
+
120
+ - **Modo emulator (primario):** `AWS_ENDPOINT_URL=http://localhost:9999` →
121
+ proxy → upstream (MiniStack/moto/LocalStack). Los emuladores no validan
122
+ la firma estrictamente (MiniStack solo parsea el credential scope). El
123
+ proxy puede forwardear la firma intacta. **Cero fricción.**
124
+ - **Modo real AWS (re-signing):** el proxy termina la request y la re-firma
125
+ con credenciales configuradas (las del usuario — es su propia cuenta para
126
+ game days en staging). Es ~100 líneas (MiniStack `core/sigv4.py` ya tiene
127
+ todos los primitivos: canonical request, derive key, calculate). La TLS la
128
+ habla el proxy hacia arriba; el cliente habla HTTP plano al proxy. No hace
129
+ falta MITM ni CA custom.
130
+ - **Modo passthrough MITM (opcional, v2+):** HTTPS_PROXY con CA instalada.
131
+ Solo si se quiere inyectar sin cambiar endpoint config. No para MVP.
132
+
133
+ ## 6. Catálogo de efectos (realistas de AWS)
134
+
135
+ Ordenados por valor/esfuerzo:
136
+
137
+ | Efecto | Qué simula | Notas |
138
+ |---|---|---|
139
+ | `error` con error code AWS real | ProvisionedThroughputExceeded, SlowDown, KMSInternalException... | Killer feature: lookup en service model de excepciones declaradas por operación |
140
+ | `throttle` | 429/400 throttling con forma correcta | Sub-caso de error; preset común |
141
+ | `latency` | ms fijos o rango uniforme con jitter | Simular región degradada |
142
+ | `timeout` | hold → 504 o colgar conexión | Ejercita timeouts del SDK |
143
+ | `connection-reset` | RST / half-close | Transient error del cliente HTTP |
144
+ | `partial-body` | Truncar body mid-stream / corromper | S3 GetObject truncado, checksum mismatch — detalles que rompen apps de formas raras |
145
+ | `slow-drip` | Response body a N bytes/seg | Simula throughput bajo |
146
+ | `stale-read` | Eventual consistency (put → get 404) | Difícil: requiere entender semántica del servicio. **Post-MVP.** |
147
+
148
+ Matchers por regla: service, operation, region, resource (table name, bucket,
149
+ queue URL — extraíble del body/path), probability, y **rate** (token bucket:
150
+ "throttlea todo lo que exceda 10 req/s" — más realista que probabilidad para
151
+ modelar límites de AWS).
152
+
153
+ Presets estilo awsim (buena idea copiar el patrón): `ddb-throttle`,
154
+ `flaky-s3`, `slow-lambda`, `kms-outage`, `regional-failover`, `sqs-backlog`.
155
+
156
+ ## 7. Arquitectura propuesta
157
+
158
+ ```
159
+ app (SDK cualquiera)
160
+ │ AWS_ENDPOINT_URL=http://localhost:9999
161
+ ▼
162
+ chaos-proxy :9999
163
+ ├── protocol detector (credential scope → X-Amz-Target → Action= → host/path)
164
+ ├── rule engine (first-match o all-match, probability, rate limit)
165
+ ├── effect executor
166
+ └── forwarder → upstream (ministack:4566 / moto:5000 / AWS real)
167
+
168
+ control plane:
169
+ POST /_chaos/rules (append)
170
+ GET /_chaos/rules
171
+ DELETE /_chaos/rules
172
+ GET /_chaos/fired (qué reglas dispararon — clave para debug)
173
+ POST /_chaos/presets/{name}
174
+ config YAML al arranque + hot-reload
175
+ ```
176
+
177
+ Decisión de lenguaje — trade-off real:
178
+
179
+ - **Python + botocore:** los service models (incl. error shapes por operación)
180
+ vienen gratis; toda la expertise de MiniStack es reutilizable; `uvx
181
+ aws-chaos-proxy`. Contra: "single binary" requiere PyInstaller o uv.
182
+ - **Go:** binario real, mejor performance como proxy; pero hay que portar los
183
+ service models o embeber un subset JSON de los de botocore.
184
+
185
+ Recomendación: **Python primero** (velocidad de iteración, modelos gratis,
186
+ ecosistema MiniStack). Reescribir en Go solo si la performance/distro lo
187
+ exige.
188
+
189
+ ## 8. MVP (scope propuesto)
190
+
191
+ 1. Proxy HTTP/1.1 con upstream configurable (`--upstream`).
192
+ 2. Detector para ~10 servicios: dynamodb, sqs, s3, sns, lambda, kinesis,
193
+ ssm, secretsmanager, sts, iam.
194
+ 3. Efectos: `error` (protocol-correct, desde service model), `latency`,
195
+ `timeout`, `connection-reset`.
196
+ 4. Reglas vía REST + YAML; presets.
197
+ 5. `/_chaos/fired` — log de qué regla matcheó cada request. *Esto es lo que
198
+ convierte el proxy de "caos ciego" en herramienta de debugging.*
199
+ 6. Demo: app Python contra MiniStack, inyectar 30% throttle en DynamoDB,
200
+ mostrar retries del SDK.
201
+
202
+ Tests de validación (lo que prueba que funciona de verdad):
203
+ - boto3 clasifica el error inyectado igual que el real (throttling → backoff
204
+ largo, retriable).
205
+ - Cross-SDK: aws-sdk-go-v2 y aws-sdk-js-v3 responden igual.
206
+ - Adaptive mode activa client-side rate limiting bajo throttling sostenido.
207
+
208
+ ## 9. Riesgos
209
+
210
+ - **Servicios streaming/eventos:** Kinesis SubscribeToShard, S3 Select, SQS
211
+ long-polling — payloads chunked/event-stream. MVP: passthrough sin
212
+ inyección. Mediano plazo: inyectar a nivel frame.
213
+ - **S3 presigned URLs:** la firma va en query params; detección distinta.
214
+ Acotable.
215
+ - **HTTP/2:** SDKs usan mayormente HTTP/1.1 para estos servicios; h2 en
216
+ streaming APIs. MVP: HTTP/1.1.
217
+ - **Descubribilidad:** "chaos engineering" en búsquedas está saturado de
218
+ herramientas de infra. Posicionar como *"test your AWS SDK error
219
+ handling"* / *"failure injection for AWS API calls"*, no como chaos
220
+ platform.
221
+ - **Absorción por emuladores:** MiniStack/LocalStack podrían copiarlo. Es
222
+ riesgo aceptable — y si MiniStack lo integra, mejor para MiniStack (somos
223
+ nosotros).
224
+ - **Espacio se mueve rápido:** CloudMock y awsim aparecieron hace meses. La
225
+ ventana de "primero en standalone" existe pero no es eterna.
226
+
227
+ ## 10. Diferenciación resumida
228
+
229
+ > Toxiproxy para AWS, pero que entiende el protocolo: matchea por
230
+ > servicio/operación/recurso, devuelve errores con la forma exacta que el SDK
231
+ > espera (desde los service models), y funciona contra cualquier backend —
232
+ > MiniStack, moto, LocalStack, o AWS real. LocalStack vende esto en
233
+ > Enterprise; CloudMock/atrición lo atan a su emulador. Este es el primero
234
+ > standalone y open source.
235
+
236
+ ## 11. Nombres candidatos
237
+
238
+ `aws-chaos-proxy` (descriptivo), `faultline`, `stormfront`, `throttle-shop`,
239
+ `bad-weather`, `blip` (AWS tiene hiccups). Recomendación: nombre corto +
240
+ subtítulo descriptivo, ej. **`microburst`** — "AWS failure injection proxy".
241
+ Microburst = ráfaga de tormenta. Corto, disponible probablemente, on-theme.
242
+
243
+ ## 12. Relación con MiniStack
244
+
245
+ Dos caminos no excluyentes:
246
+ 1. Proyecto standalone primero — mayor alcance (funciona con todo el
247
+ ecosistema), marca propia.
248
+ 2. Después: MiniStack puede importarlo como middleware o re-implementar el
249
+ faults endpoint compatible (`/_ministack/chaos/faults`) usando la misma
250
+ rule engine. LocalStack cobra Enterprise por esto; MiniStack lo tendría
251
+ gratis — argumento de marketing directo.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 pingedbrain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.5
2
+ Name: microburst
3
+ Version: 0.1.0
4
+ Summary: AWS failure injection proxy — protocol-aware faults for any AWS endpoint (emulators or real AWS)
5
+ Project-URL: Homepage, https://github.com/pingedbrain/microburst
6
+ Project-URL: Repository, https://github.com/pingedbrain/microburst
7
+ Project-URL: Issues, https://github.com/pingedbrain/microburst/issues
8
+ Author-email: pingedbrain <licha.pintos@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: aws,chaos,fault-injection,proxy,resilience,testing
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Testing
22
+ Classifier: Topic :: System :: Distributed Computing
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: aiohttp<4,>=3.9
25
+ Requires-Dist: botocore>=1.34
26
+ Requires-Dist: pyyaml>=6.0
27
+ Provides-Extra: test
28
+ Requires-Dist: boto3>=1.34; extra == 'test'
29
+ Requires-Dist: pytest>=8.0; extra == 'test'
30
+ Requires-Dist: ruff>=0.6; extra == 'test'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # microburst
34
+
35
+ **AWS failure injection proxy.** Point your SDK at microburst instead of your AWS
36
+ endpoint and inject realistic faults — throttling, latency, timeouts,
37
+ connection resets — that the SDK treats exactly like real AWS failures.
38
+
39
+ Works against **any** upstream: MiniStack, moto, LocalStack, or real AWS.
40
+
41
+ ## Why
42
+
43
+ Generic proxies (Toxiproxy et al.) are protocol-blind: they can cut a
44
+ connection or add delay, but they can't return a
45
+ `ProvisionedThroughputExceededException` in the shape the SDK parses — so your
46
+ retry/backoff/circuit-breaker code never gets exercised for real.
47
+
48
+ Microburst is **AWS-protocol-aware**:
49
+
50
+ - detects service, operation, region and resource per request (SigV4
51
+ credential scope, `X-Amz-Target`, `Action=`, REST path patterns from the
52
+ service model)
53
+ - serializes errors in the wire format of the right protocol
54
+ (`json` / `query` / `rest-xml` / `rest-json`)
55
+ - picks HTTP statuses from the modeled error shape, and can *sample* a
56
+ plausible modeled exception for an operation
57
+ - works as a plain HTTP hop — no MITM, no cert install; for real AWS it can
58
+ re-sign requests with your credentials
59
+
60
+ ## Quickstart
61
+
62
+ ```bash
63
+ pip install -e . # or: uvx microburst (once published)
64
+ microburst --upstream http://localhost:4566 --port 9999
65
+ ```
66
+
67
+ ```bash
68
+ export AWS_ENDPOINT_URL=http://localhost:9999
69
+ python your_app.py # all AWS calls now flow through microburst
70
+ ```
71
+
72
+ Inject a fault at runtime:
73
+
74
+ ```bash
75
+ curl -X PATCH localhost:9999/_microburst/rules -d '[
76
+ {"service": "dynamodb", "probability": 0.3,
77
+ "error": {"code": "ProvisionedThroughputExceededException"}}
78
+ ]'
79
+ ```
80
+
81
+ Or use a preset:
82
+
83
+ ```bash
84
+ curl -X POST localhost:9999/_microburst/presets/ddb-throttle
85
+ curl -X POST localhost:9999/_microburst/presets/network-jitter
86
+ ```
87
+
88
+ See what fired (the part that turns blind chaos into a debugging tool):
89
+
90
+ ```bash
91
+ curl localhost:9999/_microburst/fired
92
+ ```
93
+
94
+ ## Rules
95
+
96
+ ```yaml
97
+ - service: dynamodb # sigV4 credential scope name, "*" for all
98
+ operation: PutItem # optional; resolved per protocol
99
+ region: us-east-1 # optional
100
+ resource: orders # substring of table/bucket/queue/etc.
101
+ probability: 0.5 # default 1.0
102
+ times: 3 # fire at most N times total (great for
103
+ # "fail once, then retry succeeds")
104
+ error:
105
+ code: SlowDown # any AWS error code; omit → sample from the
106
+ status: 503 # operation's modeled exceptions
107
+ message: "slow down"
108
+ latency: {min: 500, max: 2000} # ms; or a bare number
109
+ timeout_ms: 30000 # hold the connection, then 504
110
+ reset: true # abort the TCP connection
111
+ ```
112
+
113
+ A rule with only `latency` delays the request and still forwards it. The
114
+ first matching rule wins.
115
+
116
+ ### Presets
117
+
118
+ `ddb-throttle` · `flaky-s3` · `slow-lambda` · `kms-outage` · `sqs-backlog` ·
119
+ `regional-failover` · `network-jitter` · `gateway-storm`
120
+
121
+ ## Control API
122
+
123
+ | Method | Path | Effect |
124
+ |---|---|---|
125
+ | GET | `/_microburst/health` | upstream, rule count, requests seen |
126
+ | GET | `/_microburst/rules` | list active rules |
127
+ | POST | `/_microburst/rules` | replace all rules |
128
+ | PATCH | `/_microburst/rules` | append rules |
129
+ | DELETE | `/_microburst/rules` | body `[]` clears all; or list of field matchers |
130
+ | GET | `/_microburst/fired?limit=N` | fault events (rule, service, op, action) |
131
+ | DELETE | `/_microburst/fired` | clear the log |
132
+ | GET | `/_microburst/presets` | list presets |
133
+ | POST | `/_microburst/presets/{name}` | activate a preset |
134
+
135
+ ## Config file
136
+
137
+ ```bash
138
+ microburst --config examples/chaos.yml
139
+ ```
140
+
141
+ See `examples/chaos.yml`.
142
+
143
+ ## Real AWS upstreams
144
+
145
+ ```bash
146
+ export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=...
147
+ microburst --upstream https://dynamodb.us-east-1.amazonaws.com
148
+ ```
149
+
150
+ Re-signing is enabled automatically for `amazonaws.com` upstreams (use
151
+ `--no-resign` to disable). Useful for game days against staging accounts —
152
+ inject faults into real API traffic without touching app code.
153
+
154
+ ## Caveats
155
+
156
+ - HTTP/1.1 data plane; streaming/event-stream APIs
157
+ (Kinesis `SubscribeToShard`, S3 Select, Lambda response streaming) pass
158
+ through but fault injection on frames is not implemented yet.
159
+ - Bodies > 4 MiB are streamed uninspected (resource-level matchers won't see
160
+ them; service/operation matchers still work for REST services).
161
+ - S3 presigned URLs are not specially detected yet.
162
+
163
+ ## License
164
+
165
+ MIT
@@ -0,0 +1,133 @@
1
+ # microburst
2
+
3
+ **AWS failure injection proxy.** Point your SDK at microburst instead of your AWS
4
+ endpoint and inject realistic faults — throttling, latency, timeouts,
5
+ connection resets — that the SDK treats exactly like real AWS failures.
6
+
7
+ Works against **any** upstream: MiniStack, moto, LocalStack, or real AWS.
8
+
9
+ ## Why
10
+
11
+ Generic proxies (Toxiproxy et al.) are protocol-blind: they can cut a
12
+ connection or add delay, but they can't return a
13
+ `ProvisionedThroughputExceededException` in the shape the SDK parses — so your
14
+ retry/backoff/circuit-breaker code never gets exercised for real.
15
+
16
+ Microburst is **AWS-protocol-aware**:
17
+
18
+ - detects service, operation, region and resource per request (SigV4
19
+ credential scope, `X-Amz-Target`, `Action=`, REST path patterns from the
20
+ service model)
21
+ - serializes errors in the wire format of the right protocol
22
+ (`json` / `query` / `rest-xml` / `rest-json`)
23
+ - picks HTTP statuses from the modeled error shape, and can *sample* a
24
+ plausible modeled exception for an operation
25
+ - works as a plain HTTP hop — no MITM, no cert install; for real AWS it can
26
+ re-sign requests with your credentials
27
+
28
+ ## Quickstart
29
+
30
+ ```bash
31
+ pip install -e . # or: uvx microburst (once published)
32
+ microburst --upstream http://localhost:4566 --port 9999
33
+ ```
34
+
35
+ ```bash
36
+ export AWS_ENDPOINT_URL=http://localhost:9999
37
+ python your_app.py # all AWS calls now flow through microburst
38
+ ```
39
+
40
+ Inject a fault at runtime:
41
+
42
+ ```bash
43
+ curl -X PATCH localhost:9999/_microburst/rules -d '[
44
+ {"service": "dynamodb", "probability": 0.3,
45
+ "error": {"code": "ProvisionedThroughputExceededException"}}
46
+ ]'
47
+ ```
48
+
49
+ Or use a preset:
50
+
51
+ ```bash
52
+ curl -X POST localhost:9999/_microburst/presets/ddb-throttle
53
+ curl -X POST localhost:9999/_microburst/presets/network-jitter
54
+ ```
55
+
56
+ See what fired (the part that turns blind chaos into a debugging tool):
57
+
58
+ ```bash
59
+ curl localhost:9999/_microburst/fired
60
+ ```
61
+
62
+ ## Rules
63
+
64
+ ```yaml
65
+ - service: dynamodb # sigV4 credential scope name, "*" for all
66
+ operation: PutItem # optional; resolved per protocol
67
+ region: us-east-1 # optional
68
+ resource: orders # substring of table/bucket/queue/etc.
69
+ probability: 0.5 # default 1.0
70
+ times: 3 # fire at most N times total (great for
71
+ # "fail once, then retry succeeds")
72
+ error:
73
+ code: SlowDown # any AWS error code; omit → sample from the
74
+ status: 503 # operation's modeled exceptions
75
+ message: "slow down"
76
+ latency: {min: 500, max: 2000} # ms; or a bare number
77
+ timeout_ms: 30000 # hold the connection, then 504
78
+ reset: true # abort the TCP connection
79
+ ```
80
+
81
+ A rule with only `latency` delays the request and still forwards it. The
82
+ first matching rule wins.
83
+
84
+ ### Presets
85
+
86
+ `ddb-throttle` · `flaky-s3` · `slow-lambda` · `kms-outage` · `sqs-backlog` ·
87
+ `regional-failover` · `network-jitter` · `gateway-storm`
88
+
89
+ ## Control API
90
+
91
+ | Method | Path | Effect |
92
+ |---|---|---|
93
+ | GET | `/_microburst/health` | upstream, rule count, requests seen |
94
+ | GET | `/_microburst/rules` | list active rules |
95
+ | POST | `/_microburst/rules` | replace all rules |
96
+ | PATCH | `/_microburst/rules` | append rules |
97
+ | DELETE | `/_microburst/rules` | body `[]` clears all; or list of field matchers |
98
+ | GET | `/_microburst/fired?limit=N` | fault events (rule, service, op, action) |
99
+ | DELETE | `/_microburst/fired` | clear the log |
100
+ | GET | `/_microburst/presets` | list presets |
101
+ | POST | `/_microburst/presets/{name}` | activate a preset |
102
+
103
+ ## Config file
104
+
105
+ ```bash
106
+ microburst --config examples/chaos.yml
107
+ ```
108
+
109
+ See `examples/chaos.yml`.
110
+
111
+ ## Real AWS upstreams
112
+
113
+ ```bash
114
+ export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=...
115
+ microburst --upstream https://dynamodb.us-east-1.amazonaws.com
116
+ ```
117
+
118
+ Re-signing is enabled automatically for `amazonaws.com` upstreams (use
119
+ `--no-resign` to disable). Useful for game days against staging accounts —
120
+ inject faults into real API traffic without touching app code.
121
+
122
+ ## Caveats
123
+
124
+ - HTTP/1.1 data plane; streaming/event-stream APIs
125
+ (Kinesis `SubscribeToShard`, S3 Select, Lambda response streaming) pass
126
+ through but fault injection on frames is not implemented yet.
127
+ - Bodies > 4 MiB are streamed uninspected (resource-level matchers won't see
128
+ them; service/operation matchers still work for REST services).
129
+ - S3 presigned URLs are not specially detected yet.
130
+
131
+ ## License
132
+
133
+ MIT
@@ -0,0 +1,21 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ | Version | Supported |
6
+ |---------|-----------|
7
+ | 0.1.x | ✅ |
8
+
9
+ ## Reporting a vulnerability
10
+
11
+ Please **do not** open a public issue for security reports. Use GitHub's
12
+ [private vulnerability reporting](../../security/advisories/new) instead.
13
+
14
+ ## Scope notes
15
+
16
+ - The `/_microburst/*` control API is **unauthenticated by design** — it is a
17
+ local development tool. Never expose it beyond localhost. Treat anything
18
+ that can reach the proxy port as able to inject faults into your traffic.
19
+ - `--resign` mode handles real AWS credentials. Signatures are computed in
20
+ memory and never logged or forwarded to third parties; still, only run it
21
+ against upstreams you trust.