@gugananuvem/aws-local-simulator 1.0.12 → 1.0.14
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.
- package/README.md +235 -11
- package/package.json +12 -2
- package/src/config/default-config.js +1 -0
- package/src/index.js +18 -2
- package/src/server.js +36 -32
- package/src/services/apigateway/index.js +5 -0
- package/src/services/apigateway/server.js +20 -0
- package/src/services/apigateway/simulator.js +13 -3
- package/src/services/athena/index.js +75 -0
- package/src/services/athena/server.js +101 -0
- package/src/services/athena/simulador.js +998 -0
- package/src/services/athena/simulator.js +346 -0
- package/src/services/cloudformation/index.js +106 -0
- package/src/services/cloudformation/server.js +417 -0
- package/src/services/cloudformation/simulador.js +1045 -0
- package/src/services/cloudtrail/index.js +84 -0
- package/src/services/cloudtrail/server.js +235 -0
- package/src/services/cloudtrail/simulador.js +719 -0
- package/src/services/cloudwatch/index.js +84 -0
- package/src/services/cloudwatch/server.js +366 -0
- package/src/services/cloudwatch/simulador.js +1173 -0
- package/src/services/cognito/index.js +5 -0
- package/src/services/cognito/simulator.js +4 -0
- package/src/services/config/index.js +96 -0
- package/src/services/config/server.js +215 -0
- package/src/services/config/simulador.js +1260 -0
- package/src/services/dynamodb/index.js +7 -3
- package/src/services/dynamodb/server.js +4 -2
- package/src/services/dynamodb/simulator.js +39 -29
- package/src/services/eventbridge/index.js +55 -51
- package/src/services/eventbridge/server.js +209 -0
- package/src/services/eventbridge/simulator.js +684 -0
- package/src/services/index.js +30 -4
- package/src/services/kms/index.js +75 -0
- package/src/services/kms/server.js +67 -0
- package/src/services/kms/simulator.js +324 -0
- package/src/services/lambda/index.js +5 -0
- package/src/services/lambda/simulator.js +48 -38
- package/src/services/parameter-store/index.js +80 -0
- package/src/services/parameter-store/server.js +50 -0
- package/src/services/parameter-store/simulator.js +201 -0
- package/src/services/s3/index.js +7 -3
- package/src/services/s3/server.js +20 -13
- package/src/services/s3/simulator.js +163 -407
- package/src/services/secret-manager/index.js +80 -0
- package/src/services/secret-manager/server.js +50 -0
- package/src/services/secret-manager/simulator.js +171 -0
- package/src/services/sns/index.js +55 -42
- package/src/services/sns/server.js +580 -0
- package/src/services/sns/simulator.js +1482 -0
- package/src/services/sqs/index.js +2 -4
- package/src/services/sqs/server.js +4 -2
- package/src/services/xray/index.js +83 -0
- package/src/services/xray/server.js +308 -0
- package/src/services/xray/simulador.js +994 -0
- package/src/utils/cloudtrail-audit.js +129 -0
- package/src/utils/local-store.js +18 -2
package/README.md
CHANGED
|
@@ -13,13 +13,22 @@ Simulador local completo para serviços AWS. Desenvolva e teste suas aplicaçõe
|
|
|
13
13
|
| DynamoDB | ✅ | 8000 | Banco de dados NoSQL |
|
|
14
14
|
| S3 | ✅ | 4566 | Armazenamento de objetos |
|
|
15
15
|
| SQS | ✅ | 9324 | Filas de mensagens |
|
|
16
|
-
| Lambda | ✅ | 3001 | Funções serverless
|
|
16
|
+
| Lambda | ✅ | 3001 | Funções serverless |
|
|
17
17
|
| Cognito | ✅ | 9229 | Autenticação e autorização |
|
|
18
18
|
| API Gateway | ✅ | 4567 | APIs REST e HTTP |
|
|
19
|
-
| STS | ✅ | 9326 | Credenciais temporárias
|
|
19
|
+
| STS | ✅ | 9326 | Credenciais temporárias |
|
|
20
|
+
| SNS | ✅ | 9911 | Notificações pub/sub |
|
|
21
|
+
| EventBridge | ✅ | 4010 | Barramento de eventos |
|
|
22
|
+
| KMS | ✅ | 4000 | Gerenciamento de chaves |
|
|
23
|
+
| Secrets Manager | ✅ | 4001 | Gerenciamento de segredos |
|
|
24
|
+
| Parameter Store | ✅ | 4002 | Armazenamento de parâmetros |
|
|
25
|
+
| CloudWatch | ✅ | 4011 | Logs, métricas e alarmes |
|
|
26
|
+
| CloudTrail | ✅ | 4012 | Auditoria de API calls |
|
|
27
|
+
| AWS Config | ✅ | 4013 | Conformidade e configuração |
|
|
28
|
+
| CloudFormation | ✅ | 4580 | Infraestrutura como código |
|
|
29
|
+
| Athena | ✅ | 4599 | Consultas SQL em dados no S3 |
|
|
30
|
+
| X-Ray | ✅ | 4015 | Rastreamento distribuído |
|
|
20
31
|
| ECS/Fargate | 🚧 | 8080 | Orquestração de containers (em desenvolvimento) |
|
|
21
|
-
| SNS | 🚧 | 9911 | Notificações (em desenvolvimento) |
|
|
22
|
-
| EventBridge | 🚧 | 4010 | Barramento de eventos (em desenvolvimento) |
|
|
23
32
|
|
|
24
33
|
## 📦 Instalação
|
|
25
34
|
|
|
@@ -40,7 +49,18 @@ npm install --save-dev aws-local-simulator
|
|
|
40
49
|
"lambda": true,
|
|
41
50
|
"cognito": true,
|
|
42
51
|
"apigateway": true,
|
|
43
|
-
"sts": true
|
|
52
|
+
"sts": true,
|
|
53
|
+
"sns": true,
|
|
54
|
+
"eventbridge": true,
|
|
55
|
+
"kms": true,
|
|
56
|
+
"secret-manager": true,
|
|
57
|
+
"parameter-store": true,
|
|
58
|
+
"cloudwatch": true,
|
|
59
|
+
"cloudtrail": true,
|
|
60
|
+
"cloudformation": true,
|
|
61
|
+
"xray": true,
|
|
62
|
+
"config": true,
|
|
63
|
+
"athena": true
|
|
44
64
|
},
|
|
45
65
|
"lambdas": [
|
|
46
66
|
{
|
|
@@ -111,6 +131,17 @@ await dynamoDB.send(new PutCommand({
|
|
|
111
131
|
| AWS_LOCAL_SIMULATOR_COGNITO | Habilita Cognito | false |
|
|
112
132
|
| AWS_LOCAL_SIMULATOR_APIGATEWAY | Habilita API Gateway | false |
|
|
113
133
|
| AWS_LOCAL_SIMULATOR_STS | Habilita STS | true |
|
|
134
|
+
| AWS_LOCAL_SIMULATOR_SNS | Habilita SNS | false |
|
|
135
|
+
| AWS_LOCAL_SIMULATOR_EVENTBRIDGE | Habilita EventBridge | false |
|
|
136
|
+
| AWS_LOCAL_SIMULATOR_KMS | Habilita KMS | false |
|
|
137
|
+
| AWS_LOCAL_SIMULATOR_SECRET_MANAGER | Habilita Secrets Manager | false |
|
|
138
|
+
| AWS_LOCAL_SIMULATOR_PARAMETER_STORE | Habilita Parameter Store | false |
|
|
139
|
+
| AWS_LOCAL_SIMULATOR_CLOUDWATCH | Habilita CloudWatch | false |
|
|
140
|
+
| AWS_LOCAL_SIMULATOR_CLOUDTRAIL | Habilita CloudTrail | false |
|
|
141
|
+
| AWS_LOCAL_SIMULATOR_CLOUDFORMATION | Habilita CloudFormation | false |
|
|
142
|
+
| AWS_LOCAL_SIMULATOR_ATHENA | Habilita Athena | false |
|
|
143
|
+
| AWS_LOCAL_SIMULATOR_XRAY | Habilita X-Ray | false |
|
|
144
|
+
| AWS_LOCAL_SIMULATOR_CONFIG | Habilita AWS Config | false |
|
|
114
145
|
| AWS_LOCAL_SIMULATOR_ECS | Habilita ECS/Fargate | false |
|
|
115
146
|
| AWS_LOCAL_SIMULATOR_DYNAMODB_PORT | Porta DynamoDB | 8000 |
|
|
116
147
|
| AWS_LOCAL_SIMULATOR_S3_PORT | Porta S3 | 4566 |
|
|
@@ -119,6 +150,17 @@ await dynamoDB.send(new PutCommand({
|
|
|
119
150
|
| AWS_LOCAL_SIMULATOR_COGNITO_PORT | Porta Cognito | 9229 |
|
|
120
151
|
| AWS_LOCAL_SIMULATOR_APIGATEWAY_PORT | Porta API Gateway | 4567 |
|
|
121
152
|
| AWS_LOCAL_SIMULATOR_STS_PORT | Porta STS | 9326 |
|
|
153
|
+
| AWS_LOCAL_SIMULATOR_SNS_PORT | Porta SNS | 9911 |
|
|
154
|
+
| AWS_LOCAL_SIMULATOR_EVENTBRIDGE_PORT | Porta EventBridge | 4010 |
|
|
155
|
+
| AWS_LOCAL_SIMULATOR_KMS_PORT | Porta KMS | 4000 |
|
|
156
|
+
| AWS_LOCAL_SIMULATOR_SECRET_MANAGER_PORT | Porta Secrets Manager | 4001 |
|
|
157
|
+
| AWS_LOCAL_SIMULATOR_PARAMETER_STORE_PORT | Porta Parameter Store | 4002 |
|
|
158
|
+
| AWS_LOCAL_SIMULATOR_CLOUDWATCH_PORT | Porta CloudWatch | 4011 |
|
|
159
|
+
| AWS_LOCAL_SIMULATOR_CLOUDTRAIL_PORT | Porta CloudTrail | 4012 |
|
|
160
|
+
| AWS_LOCAL_SIMULATOR_CONFIG_PORT | Porta AWS Config | 4013 |
|
|
161
|
+
| AWS_LOCAL_SIMULATOR_XRAY_PORT | Porta X-Ray | 4015 |
|
|
162
|
+
| AWS_LOCAL_SIMULATOR_CLOUDFORMATION_PORT | Porta CloudFormation | 4580 |
|
|
163
|
+
| AWS_LOCAL_SIMULATOR_ATHENA_PORT | Porta Athena | 4599 |
|
|
122
164
|
| AWS_LOCAL_SIMULATOR_ECS_PORT | Porta ECS | 8080 |
|
|
123
165
|
| AWS_LOCAL_SIMULATOR_DATA | Diretório de dados | ./aws-local-simulator-data |
|
|
124
166
|
| AWS_LOCAL_SIMULATOR_LOG | Nível de log | info |
|
|
@@ -153,6 +195,17 @@ npx aws-local-simulator status
|
|
|
153
195
|
| Cognito | http://localhost:9229 | http://localhost:9229/__admin/userpools |
|
|
154
196
|
| API Gateway | http://localhost:4567 | http://localhost:4567/__admin/apis |
|
|
155
197
|
| STS | http://localhost:9326 | — |
|
|
198
|
+
| SNS | http://localhost:9911 | http://localhost:9911/__admin/health |
|
|
199
|
+
| EventBridge | http://localhost:4010 | — |
|
|
200
|
+
| KMS | http://localhost:4000 | — |
|
|
201
|
+
| Secrets Manager | http://localhost:4001 | — |
|
|
202
|
+
| Parameter Store | http://localhost:4002 | — |
|
|
203
|
+
| CloudWatch | http://localhost:4011 | — |
|
|
204
|
+
| CloudTrail | http://localhost:4012 | — |
|
|
205
|
+
| AWS Config | http://localhost:4013 | — |
|
|
206
|
+
| X-Ray | http://localhost:4015 | — |
|
|
207
|
+
| CloudFormation | http://localhost:4580 | http://localhost:4580/__admin/stacks |
|
|
208
|
+
| Athena | http://localhost:4599 | http://localhost:4599/__admin/health |
|
|
156
209
|
| ECS | http://localhost:8080 | http://localhost:8080/__admin/clusters |
|
|
157
210
|
|
|
158
211
|
## 🧪 Testando com AWS CLI
|
|
@@ -167,7 +220,7 @@ aws s3 ls --endpoint-url http://localhost:4566
|
|
|
167
220
|
# SQS
|
|
168
221
|
aws sqs list-queues --endpoint-url http://localhost:9324
|
|
169
222
|
|
|
170
|
-
# Lambda
|
|
223
|
+
# Lambda
|
|
171
224
|
aws lambda invoke \
|
|
172
225
|
--function-name my-function \
|
|
173
226
|
--payload '{"key":"value"}' \
|
|
@@ -184,8 +237,126 @@ aws sts assume-role \
|
|
|
184
237
|
--role-session-name "my-session" \
|
|
185
238
|
--endpoint-url http://localhost:9326
|
|
186
239
|
|
|
240
|
+
# SNS
|
|
241
|
+
aws sns list-topics --endpoint-url http://localhost:9911
|
|
242
|
+
|
|
243
|
+
# EventBridge
|
|
244
|
+
aws events list-event-buses --endpoint-url http://localhost:4010
|
|
245
|
+
|
|
246
|
+
# KMS
|
|
247
|
+
aws kms list-keys --endpoint-url http://localhost:4000
|
|
248
|
+
|
|
249
|
+
# Secrets Manager
|
|
250
|
+
aws secretsmanager list-secrets --endpoint-url http://localhost:4001
|
|
251
|
+
|
|
252
|
+
# Criar secret
|
|
253
|
+
aws secretsmanager create-secret \
|
|
254
|
+
--name "local/app/db-credentials" \
|
|
255
|
+
--description "Credenciais do banco" \
|
|
256
|
+
--secret-string '{"username":"admin","password":"secret123"}' \
|
|
257
|
+
--endpoint-url http://localhost:4001
|
|
258
|
+
|
|
259
|
+
# Ler secret
|
|
260
|
+
aws secretsmanager get-secret-value \
|
|
261
|
+
--secret-id "local/app/db-credentials" \
|
|
262
|
+
--endpoint-url http://localhost:4001
|
|
263
|
+
|
|
264
|
+
# Parameter Store
|
|
265
|
+
aws ssm describe-parameters --endpoint-url http://localhost:4002
|
|
266
|
+
|
|
267
|
+
# Criar parâmetro String
|
|
268
|
+
aws ssm put-parameter \
|
|
269
|
+
--name "/local/app/config" \
|
|
270
|
+
--value '{"timeout":30,"maxRetries":3}' \
|
|
271
|
+
--type String \
|
|
272
|
+
--endpoint-url http://localhost:4002
|
|
273
|
+
|
|
274
|
+
# Criar parâmetro SecureString
|
|
275
|
+
aws ssm put-parameter \
|
|
276
|
+
--name "/local/app/api-key" \
|
|
277
|
+
--value "my-secret-api-key" \
|
|
278
|
+
--type SecureString \
|
|
279
|
+
--endpoint-url http://localhost:4002
|
|
280
|
+
|
|
281
|
+
# Ler parâmetro
|
|
282
|
+
aws ssm get-parameter \
|
|
283
|
+
--name "/local/app/config" \
|
|
284
|
+
--endpoint-url http://localhost:4002
|
|
285
|
+
|
|
286
|
+
# CloudWatch
|
|
287
|
+
aws cloudwatch list-metrics --endpoint-url http://localhost:4011
|
|
288
|
+
aws logs describe-log-groups --endpoint-url http://localhost:4011
|
|
289
|
+
|
|
290
|
+
# CloudTrail
|
|
291
|
+
aws cloudtrail describe-trails --endpoint-url http://localhost:4012
|
|
292
|
+
|
|
293
|
+
# CloudFormation
|
|
294
|
+
aws cloudformation list-stacks --endpoint-url http://localhost:4580
|
|
295
|
+
|
|
296
|
+
# X-Ray
|
|
297
|
+
aws xray get-trace-summaries \
|
|
298
|
+
--start-time $(date -d '1 hour ago' +%s) \
|
|
299
|
+
--end-time $(date +%s) \
|
|
300
|
+
--endpoint-url http://localhost:4015
|
|
301
|
+
|
|
302
|
+
# AWS Config
|
|
303
|
+
aws configservice describe-configuration-recorders --endpoint-url http://localhost:4013
|
|
304
|
+
|
|
187
305
|
# API Gateway
|
|
188
306
|
aws apigateway get-rest-apis --endpoint-url http://localhost:4567
|
|
307
|
+
|
|
308
|
+
# Cloudformation
|
|
309
|
+
aws cloudformation create-stack \
|
|
310
|
+
--stack-name test-stack \
|
|
311
|
+
--template-body file://templates/test-stack.yaml \
|
|
312
|
+
--parameters \
|
|
313
|
+
ParameterKey=Environment,ParameterValue=local \
|
|
314
|
+
ParameterKey=BucketName,ParameterValue=meu-bucket \
|
|
315
|
+
ParameterKey=QueueName,ParameterValue=minha-fila \
|
|
316
|
+
ParameterKey=TableName,ParameterValue=minha-tabela \
|
|
317
|
+
--endpoint-url http://localhost:4580
|
|
318
|
+
|
|
319
|
+
# Ver Cloudformation resultado
|
|
320
|
+
aws cloudformation describe-stacks \
|
|
321
|
+
--stack-name test-stack \
|
|
322
|
+
--endpoint-url http://localhost:4580
|
|
323
|
+
|
|
324
|
+
# Athena
|
|
325
|
+
# Criar workgroup
|
|
326
|
+
aws athena create-work-group \
|
|
327
|
+
--name my-workgroup \
|
|
328
|
+
--configuration ResultConfiguration={OutputLocation=s3://meu-bucket/athena-results/} \
|
|
329
|
+
--endpoint-url http://localhost:4599
|
|
330
|
+
|
|
331
|
+
# Listar workgroups
|
|
332
|
+
aws athena list-work-groups --endpoint-url http://localhost:4599
|
|
333
|
+
|
|
334
|
+
# Executar query
|
|
335
|
+
aws athena start-query-execution \
|
|
336
|
+
--query-string "SELECT * FROM my_table LIMIT 10" \
|
|
337
|
+
--query-execution-context Database=default \
|
|
338
|
+
--result-configuration OutputLocation=s3://meu-bucket/athena-results/ \
|
|
339
|
+
--endpoint-url http://localhost:4599
|
|
340
|
+
|
|
341
|
+
# Verificar status da query
|
|
342
|
+
aws athena get-query-execution \
|
|
343
|
+
--query-execution-id <id-retornado> \
|
|
344
|
+
--endpoint-url http://localhost:4599
|
|
345
|
+
|
|
346
|
+
# Buscar resultados
|
|
347
|
+
aws athena get-query-results \
|
|
348
|
+
--query-execution-id <id-retornado> \
|
|
349
|
+
--endpoint-url http://localhost:4599
|
|
350
|
+
|
|
351
|
+
# Criar named query
|
|
352
|
+
aws athena create-named-query \
|
|
353
|
+
--name "my-saved-query" \
|
|
354
|
+
--database default \
|
|
355
|
+
--query-string "SELECT id, value FROM my_table WHERE status = 'active'" \
|
|
356
|
+
--endpoint-url http://localhost:4599
|
|
357
|
+
|
|
358
|
+
# Listar named queries
|
|
359
|
+
aws athena list-named-queries --endpoint-url http://localhost:4599
|
|
189
360
|
```
|
|
190
361
|
|
|
191
362
|
## ⚙️ Configuração de Lambdas
|
|
@@ -196,8 +367,8 @@ Lambdas são registradas por **nome** e invocadas via API de invocação (igual
|
|
|
196
367
|
{
|
|
197
368
|
"lambdas": [
|
|
198
369
|
{
|
|
199
|
-
"name": "my-function",
|
|
200
|
-
"handler": "./src/handlers/my-function.js",
|
|
370
|
+
"name": "my-user-function",
|
|
371
|
+
"handler": "./src/handlers/my-user-function.js",
|
|
201
372
|
"env": {
|
|
202
373
|
"TABLE_NAME": "users-table",
|
|
203
374
|
"BUCKET_NAME": "my-bucket"
|
|
@@ -207,6 +378,50 @@ Lambdas são registradas por **nome** e invocadas via API de invocação (igual
|
|
|
207
378
|
}
|
|
208
379
|
```
|
|
209
380
|
|
|
381
|
+
## ⚙️ Configuração API GATEWAY
|
|
382
|
+
|
|
383
|
+
O valor do **lambdaName** deve igual ao nome Lambda que está registrada com o valor **name**. Ex: "my-user-function".
|
|
384
|
+
|
|
385
|
+
```json
|
|
386
|
+
{
|
|
387
|
+
"apigateway": {
|
|
388
|
+
"apis": [
|
|
389
|
+
{
|
|
390
|
+
"name": "Users API",
|
|
391
|
+
"description": "API para gerenciamento de usuários",
|
|
392
|
+
"endpoints": [
|
|
393
|
+
{
|
|
394
|
+
"path": "/user",
|
|
395
|
+
"method": "GET",
|
|
396
|
+
"lambdaName": "my-user-function",
|
|
397
|
+
"integrationType": "lambda"
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
"path": "/user",
|
|
401
|
+
"method": "POST",
|
|
402
|
+
"lambdaName": "my-user-function",
|
|
403
|
+
"integrationType": "lambda"
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"path": "/user/{id}",
|
|
407
|
+
"method": "GET",
|
|
408
|
+
"lambdaName": "my-user-function",
|
|
409
|
+
"integrationType": "lambda"
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"path": "/user/{id}",
|
|
413
|
+
"method": "DELETE",
|
|
414
|
+
"lambdaName": "my-user-function",
|
|
415
|
+
"integrationType": "lambda"
|
|
416
|
+
}
|
|
417
|
+
]
|
|
418
|
+
}
|
|
419
|
+
]
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
210
425
|
O handler deve exportar uma função padrão:
|
|
211
426
|
|
|
212
427
|
```javascript
|
|
@@ -229,13 +444,22 @@ Os dados são persistidos em:
|
|
|
229
444
|
├── sqs/
|
|
230
445
|
├── cognito/
|
|
231
446
|
├── apigateway/
|
|
232
|
-
|
|
447
|
+
├── ecs/
|
|
448
|
+
├── kms/
|
|
449
|
+
├── secret-manager/
|
|
450
|
+
├── parameter-store/
|
|
451
|
+
├── cloudwatch/
|
|
452
|
+
├── cloudtrail/
|
|
453
|
+
├── cloudformation/
|
|
454
|
+
├── athena/
|
|
455
|
+
├── xray/
|
|
456
|
+
└── config/
|
|
233
457
|
```
|
|
234
458
|
|
|
235
459
|
## 🐛 Debug
|
|
236
460
|
|
|
237
461
|
```bash
|
|
238
|
-
AWS_LOCAL_SIMULATOR_LOG=
|
|
462
|
+
AWS_LOCAL_SIMULATOR_LOG=verbose npx aws-local-simulator start
|
|
239
463
|
```
|
|
240
464
|
|
|
241
465
|
## 🤝 Contribuindo
|
|
@@ -252,6 +476,6 @@ MIT © Luiz Gustavo Ribeiro
|
|
|
252
476
|
|
|
253
477
|
## ⚠️ Limitações
|
|
254
478
|
|
|
255
|
-
-
|
|
479
|
+
- ECS/Fargate em desenvolvimento
|
|
256
480
|
- WebSocket APIs em desenvolvimento
|
|
257
481
|
- Para uso em desenvolvimento e testes apenas
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gugananuvem/aws-local-simulator",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Simulador local completo para serviços AWS",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -45,7 +45,17 @@
|
|
|
45
45
|
"lambda",
|
|
46
46
|
"cognito",
|
|
47
47
|
"apigateway",
|
|
48
|
+
"kms",
|
|
49
|
+
"config",
|
|
50
|
+
"parameter-store",
|
|
51
|
+
"secret-manager",
|
|
52
|
+
"cloudformation",
|
|
53
|
+
"eventbridge",
|
|
54
|
+
"sns",
|
|
48
55
|
"ecs",
|
|
56
|
+
"sts",
|
|
57
|
+
"cloudtrail",
|
|
58
|
+
"cloudwatch",
|
|
49
59
|
"development",
|
|
50
60
|
"testing"
|
|
51
61
|
],
|
|
@@ -109,6 +119,6 @@
|
|
|
109
119
|
"optional": true
|
|
110
120
|
}
|
|
111
121
|
},
|
|
112
|
-
"buildDate": "2026-04-
|
|
122
|
+
"buildDate": "2026-04-05T12:32:46.437Z",
|
|
113
123
|
"published": true
|
|
114
124
|
}
|
package/src/index.js
CHANGED
|
@@ -11,8 +11,16 @@ const DynamoDBService = require('./services/dynamodb');
|
|
|
11
11
|
const S3Service = require('./services/s3');
|
|
12
12
|
const SQSService = require('./services/sqs');
|
|
13
13
|
const LambdaService = require('./services/lambda');
|
|
14
|
-
const SNSService = require('./services/sns');
|
|
15
|
-
const EventBridgeService = require('./services/eventbridge');
|
|
14
|
+
const { SNSService } = require('./services/sns');
|
|
15
|
+
const { EventBridgeService } = require('./services/eventbridge');
|
|
16
|
+
const { CloudWatchService } = require('./services/cloudwatch');
|
|
17
|
+
const CloudTrailService = require('./services/cloudtrail');
|
|
18
|
+
const { KMSService } = require('./services/kms');
|
|
19
|
+
const CloudFormationService = require('./services/cloudformation');
|
|
20
|
+
const { XRayService } = require('./services/xray');
|
|
21
|
+
const { SecretManagerService } = require('./services/secret-manager');
|
|
22
|
+
const { ParameterStoreService } = require('./services/parameter-store');
|
|
23
|
+
const { ConfigService } = require('./services/config');
|
|
16
24
|
|
|
17
25
|
// Exporta utilitários
|
|
18
26
|
const LocalStore = require('./utils/local-store');
|
|
@@ -122,6 +130,14 @@ module.exports = {
|
|
|
122
130
|
LambdaService,
|
|
123
131
|
SNSService,
|
|
124
132
|
EventBridgeService,
|
|
133
|
+
CloudWatchService,
|
|
134
|
+
CloudTrailService,
|
|
135
|
+
KMSService,
|
|
136
|
+
CloudFormationService,
|
|
137
|
+
XRayService,
|
|
138
|
+
SecretManagerService,
|
|
139
|
+
ParameterStoreService,
|
|
140
|
+
ConfigService,
|
|
125
141
|
LocalStore,
|
|
126
142
|
HandlerLoader,
|
|
127
143
|
RouteRegistry
|
package/src/server.js
CHANGED
|
@@ -12,12 +12,21 @@ const DynamoDBService = require("./services/dynamodb");
|
|
|
12
12
|
const S3Service = require("./services/s3");
|
|
13
13
|
const SQSService = require("./services/sqs");
|
|
14
14
|
const LambdaService = require("./services/lambda");
|
|
15
|
-
const SNSService = require("./services/sns");
|
|
16
|
-
const EventBridgeService = require("./services/eventbridge");
|
|
15
|
+
const { SNSService } = require("./services/sns");
|
|
16
|
+
const { EventBridgeService } = require("./services/eventbridge");
|
|
17
17
|
const CognitoService = require("./services/cognito");
|
|
18
18
|
const APIGatewayService = require("./services/apigateway");
|
|
19
19
|
const ECSService = require("./services/ecs");
|
|
20
20
|
const STSService = require("./services/sts");
|
|
21
|
+
const { CloudWatchService } = require("./services/cloudwatch");
|
|
22
|
+
const CloudTrailService = require("./services/cloudtrail");
|
|
23
|
+
const { KMSService } = require("./services/kms");
|
|
24
|
+
const CloudFormationService = require("./services/cloudformation");
|
|
25
|
+
const { XRayService } = require("./services/xray");
|
|
26
|
+
const { SecretManagerService } = require("./services/secret-manager");
|
|
27
|
+
const { ParameterStoreService } = require("./services/parameter-store");
|
|
28
|
+
const { ConfigService } = require("./services/config");
|
|
29
|
+
const { AthenaService } = require("./services/athena");
|
|
21
30
|
|
|
22
31
|
class Server {
|
|
23
32
|
constructor(config) {
|
|
@@ -64,24 +73,31 @@ class Server {
|
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
async initializeServices() {
|
|
67
|
-
// Ordem de inicialização importante
|
|
68
76
|
const serviceOrder = [
|
|
69
|
-
{ name: "sts",
|
|
70
|
-
{ name: "lambda",
|
|
71
|
-
{ name: "dynamodb",
|
|
72
|
-
{ name: "s3",
|
|
73
|
-
{ name: "sqs",
|
|
74
|
-
{ name: "sns",
|
|
75
|
-
{ name: "eventbridge",
|
|
76
|
-
{ name: "cognito",
|
|
77
|
-
{ name: "ecs",
|
|
78
|
-
{ name: "apigateway",
|
|
77
|
+
{ name: "sts", class: STSService, depends: [] },
|
|
78
|
+
{ name: "lambda", class: LambdaService, depends: [] },
|
|
79
|
+
{ name: "dynamodb", class: DynamoDBService, depends: [] },
|
|
80
|
+
{ name: "s3", class: S3Service, depends: [] },
|
|
81
|
+
{ name: "sqs", class: SQSService, depends: ["lambda"] },
|
|
82
|
+
{ name: "sns", class: SNSService, depends: [] },
|
|
83
|
+
{ name: "eventbridge", class: EventBridgeService, depends: [] },
|
|
84
|
+
{ name: "cognito", class: CognitoService, depends: [] },
|
|
85
|
+
{ name: "ecs", class: ECSService, depends: [] },
|
|
86
|
+
{ name: "apigateway", class: APIGatewayService, depends: ["lambda"] },
|
|
87
|
+
{ name: "kms", class: KMSService, depends: [] },
|
|
88
|
+
{ name: "cloudwatch", class: CloudWatchService, depends: [] },
|
|
89
|
+
{ name: "cloudtrail", class: CloudTrailService, depends: [] },
|
|
90
|
+
{ name: "cloudformation", class: CloudFormationService, depends: [] },
|
|
91
|
+
{ name: "xray", class: XRayService, depends: [] },
|
|
92
|
+
{ name: "secret-manager", class: SecretManagerService, depends: [] },
|
|
93
|
+
{ name: "parameter-store",class: ParameterStoreService, depends: [] },
|
|
94
|
+
{ name: "config", class: ConfigService, depends: [] },
|
|
95
|
+
{ name: "athena", class: AthenaService, depends: [] },
|
|
79
96
|
];
|
|
80
97
|
|
|
81
98
|
for (const serviceDef of serviceOrder) {
|
|
82
99
|
if (this.config.services[serviceDef.name]) {
|
|
83
100
|
try {
|
|
84
|
-
// Resolve dependências
|
|
85
101
|
const dependencies = {};
|
|
86
102
|
for (const dep of serviceDef.depends) {
|
|
87
103
|
dependencies[dep] = this.servicesMap.get(dep);
|
|
@@ -96,29 +112,17 @@ class Server {
|
|
|
96
112
|
logger.success(`✅ ${serviceDef.name.toUpperCase()} Service inicializado`);
|
|
97
113
|
} catch (error) {
|
|
98
114
|
logger.error(`❌ Erro ao inicializar ${serviceDef.name}:`, error);
|
|
99
|
-
if (serviceDef.name === "lambda")
|
|
100
|
-
throw error; // Lambda é essencial
|
|
101
|
-
}
|
|
115
|
+
if (serviceDef.name === "lambda") throw error;
|
|
102
116
|
}
|
|
103
117
|
}
|
|
104
118
|
}
|
|
105
119
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
this.services.push(cognitoService);
|
|
112
|
-
this.servicesMap.set("cognito", cognitoService);
|
|
113
|
-
logger.success("✅ Cognito Service inicializado");
|
|
120
|
+
// Injeta dependências cross-service nos serviços que suportam
|
|
121
|
+
for (const service of this.services) {
|
|
122
|
+
if (typeof service.injectDependencies === "function") {
|
|
123
|
+
service.injectDependencies(this);
|
|
124
|
+
}
|
|
114
125
|
}
|
|
115
|
-
if (this.config.services.apigateway) {
|
|
116
|
-
const apigatewayService = new APIGatewayService(this.config);
|
|
117
|
-
await apigatewayService.initialize();
|
|
118
|
-
this.services.push(apigatewayService);
|
|
119
|
-
this.servicesMap.set("apigateway", apigatewayService);
|
|
120
|
-
logger.success("✅ API Gateway Service inicializado");
|
|
121
|
-
}*/
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
async startServices() {
|
|
@@ -33,6 +33,11 @@ class APIGatewayService {
|
|
|
33
33
|
logger.debug('API Gateway Service inicializado');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
injectDependencies(server) {
|
|
37
|
+
const ct = server.getService('cloudtrail');
|
|
38
|
+
if (ct?.simulator) this.simulator.audit.setTrail(ct.simulator);
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
async start() {
|
|
37
42
|
if (this.isRunning) return;
|
|
38
43
|
await this.server.start();
|
|
@@ -19,6 +19,26 @@ class APIGatewayServer {
|
|
|
19
19
|
setupMiddlewares() {
|
|
20
20
|
this.app.use(express.json({ limit: '10mb' }));
|
|
21
21
|
this.app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
|
22
|
+
// Parse bodies with AWS content types (e.g. application/x-amz-json-1.1)
|
|
23
|
+
this.app.use((req, res, next) => {
|
|
24
|
+
const ct = req.headers['content-type'] || '';
|
|
25
|
+
if ((req.body && JSON.stringify(req.body) == "{}") && ct.includes('application/x-amz-json')) {
|
|
26
|
+
let data = "";
|
|
27
|
+
req.on("data", (chunk) => {
|
|
28
|
+
data += chunk;
|
|
29
|
+
});
|
|
30
|
+
req.on("end", () => {
|
|
31
|
+
try {
|
|
32
|
+
req.body = JSON.parse(data);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
req.body = {};
|
|
35
|
+
}
|
|
36
|
+
next();
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
next();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
22
42
|
this.app.use(cors());
|
|
23
43
|
|
|
24
44
|
if (logger.currentLogLevel === 'verboso') {
|
|
@@ -9,14 +9,15 @@ const logger = require('../../utils/logger');
|
|
|
9
9
|
const LocalStore = require('../../utils/local-store');
|
|
10
10
|
const path = require('path');
|
|
11
11
|
const { URLPattern } = require('urlpattern-polyfill');
|
|
12
|
+
const { CloudTrailAudit } = require('../../utils/cloudtrail-audit');
|
|
12
13
|
|
|
13
14
|
class APIGatewaySimulator {
|
|
14
15
|
constructor(config) {
|
|
15
16
|
this.config = config;
|
|
16
17
|
this.dataDir = path.join(process.env.AWS_LOCAL_SIMULATOR_DATA_DIR, 'apigateway');
|
|
17
18
|
this.store = new LocalStore(this.dataDir);
|
|
18
|
-
this.apis = new Map();
|
|
19
|
-
this.websocketApis = new Map();
|
|
19
|
+
this.apis = new Map();
|
|
20
|
+
this.websocketApis = new Map();
|
|
20
21
|
this.deployments = new Map();
|
|
21
22
|
this.stages = new Map();
|
|
22
23
|
this.resources = new Map();
|
|
@@ -26,6 +27,7 @@ class APIGatewaySimulator {
|
|
|
26
27
|
this.usagePlans = new Map();
|
|
27
28
|
this.apiKeys = new Map();
|
|
28
29
|
this.domainNames = new Map();
|
|
30
|
+
this.audit = new CloudTrailAudit('execute-api.amazonaws.com');
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
async initialize() {
|
|
@@ -734,7 +736,15 @@ class APIGatewaySimulator {
|
|
|
734
736
|
response.headers = { ...response.headers, ...integrationResponse.responseParameters };
|
|
735
737
|
response.body = this.applyResponseTemplate(integrationResponse, response.body);
|
|
736
738
|
}
|
|
737
|
-
|
|
739
|
+
|
|
740
|
+
this.audit.record({
|
|
741
|
+
eventName: 'Invoke',
|
|
742
|
+
readOnly: method === 'GET' || method === 'HEAD',
|
|
743
|
+
isDataEvent: true,
|
|
744
|
+
resources: [{ ARN: `arn:aws:execute-api:local:000000000000:${apiId}/${stageName}/${method}${path}`, type: 'AWS::APIGateway::Stage' }],
|
|
745
|
+
requestParameters: { apiId, stageName, method, path },
|
|
746
|
+
});
|
|
747
|
+
|
|
738
748
|
return response;
|
|
739
749
|
}
|
|
740
750
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { AthenaSimulator } = require('./simulator');
|
|
6
|
+
const { createAthenaServer } = require('./server');
|
|
7
|
+
const LocalStore = require('../../utils/local-store');
|
|
8
|
+
|
|
9
|
+
class AthenaService {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.logger = require('../../utils/logger');
|
|
13
|
+
this.name = 'athena';
|
|
14
|
+
this.port = config?.ports?.athena || 4599;
|
|
15
|
+
this.store = null;
|
|
16
|
+
this.simulator = null;
|
|
17
|
+
this._server = null;
|
|
18
|
+
this.isRunning = false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async initialize() {
|
|
22
|
+
this.logger.debug(`Inicializando Athena Service na porta ${this.port}...`);
|
|
23
|
+
const dataDir = process.env.AWS_LOCAL_SIMULATOR_DATA_DIR;
|
|
24
|
+
this.store = new LocalStore(path.join(dataDir, 'athena'));
|
|
25
|
+
this.simulator = new AthenaSimulator(this.config, this.store, this.logger);
|
|
26
|
+
await this.simulator.initialize();
|
|
27
|
+
this.app = createAthenaServer(this.simulator, this.logger);
|
|
28
|
+
this.logger.debug('Athena Service inicializado');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
injectDependencies(server) {
|
|
32
|
+
const ct = server.getService('cloudtrail');
|
|
33
|
+
if (ct?.simulator) this.simulator.audit.setTrail(ct.simulator);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async start() {
|
|
37
|
+
if (this.isRunning) return;
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
this._server = http.createServer(this.app);
|
|
40
|
+
this._server.listen(this.port, () => {
|
|
41
|
+
this.isRunning = true;
|
|
42
|
+
this.logger.info(`🔍 Athena rodando em http://localhost:${this.port}`);
|
|
43
|
+
resolve();
|
|
44
|
+
});
|
|
45
|
+
this._server.on('error', reject);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async stop() {
|
|
50
|
+
if (!this.isRunning || !this._server) return;
|
|
51
|
+
return new Promise((resolve) => {
|
|
52
|
+
this._server.close(() => {
|
|
53
|
+
this.isRunning = false;
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async reset() {
|
|
60
|
+
await this.simulator.reset();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getStatus() {
|
|
64
|
+
return {
|
|
65
|
+
running: this.isRunning,
|
|
66
|
+
port: this.port,
|
|
67
|
+
endpoint: `http://localhost:${this.port}`,
|
|
68
|
+
...this.simulator?.getStats(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getSimulator() { return this.simulator; }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { AthenaService };
|