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.
- microburst-0.1.0/.github/dependabot.yml +10 -0
- microburst-0.1.0/.github/workflows/ci.yml +24 -0
- microburst-0.1.0/.github/workflows/release.yml +22 -0
- microburst-0.1.0/.gitignore +7 -0
- microburst-0.1.0/CONTRIBUTING.md +20 -0
- microburst-0.1.0/EXPLORATION.md +251 -0
- microburst-0.1.0/LICENSE +21 -0
- microburst-0.1.0/PKG-INFO +165 -0
- microburst-0.1.0/README.md +133 -0
- microburst-0.1.0/SECURITY.md +21 -0
- microburst-0.1.0/demo.py +250 -0
- microburst-0.1.0/examples/chaos.yml +29 -0
- microburst-0.1.0/pyproject.toml +56 -0
- microburst-0.1.0/src/microburst/__init__.py +3 -0
- microburst-0.1.0/src/microburst/__main__.py +5 -0
- microburst-0.1.0/src/microburst/cli.py +87 -0
- microburst-0.1.0/src/microburst/detect.py +208 -0
- microburst-0.1.0/src/microburst/errors.py +102 -0
- microburst-0.1.0/src/microburst/models.py +174 -0
- microburst-0.1.0/src/microburst/proxy.py +381 -0
- microburst-0.1.0/src/microburst/rules.py +270 -0
- microburst-0.1.0/tests/conftest.py +132 -0
- microburst-0.1.0/tests/test_detect.py +76 -0
- microburst-0.1.0/tests/test_errors.py +71 -0
- microburst-0.1.0/tests/test_proxy.py +214 -0
|
@@ -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,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.
|
microburst-0.1.0/LICENSE
ADDED
|
@@ -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.
|