@gugananuvem/aws-local-simulator 1.0.35 → 1.0.39

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.
Files changed (149) hide show
  1. package/README.md +662 -658
  2. package/package.json +10 -3
  3. package/src/config/default-config.js +71 -0
  4. package/src/config/env-loader.js +4 -2
  5. package/src/middleware/authorization.js +271 -0
  6. package/src/middleware/cloudtrail-logger.js +333 -0
  7. package/src/middleware/error-handler.js +138 -0
  8. package/src/middleware/index.js +79 -0
  9. package/src/middleware/policy-enforcement.js +407 -0
  10. package/src/server.js +74 -4
  11. package/src/services/acm/index.js +66 -0
  12. package/src/services/acm/models/certificate.js +202 -0
  13. package/src/services/acm/server.js +224 -0
  14. package/src/services/acm/simulator.js +293 -0
  15. package/src/services/alb/index.js +104 -0
  16. package/src/services/alb/models/loadBalancer.js +88 -0
  17. package/src/services/alb/models/targetGroup.js +128 -0
  18. package/src/services/alb/server.js +160 -0
  19. package/src/services/alb/simulator.js +262 -0
  20. package/src/services/apigateway/index.js +22 -0
  21. package/src/services/apigateway/server.js +247 -35
  22. package/src/services/apigateway/simulator.js +780 -26
  23. package/src/services/asg/index.js +100 -0
  24. package/src/services/asg/models/autoScalingGroup.js +110 -0
  25. package/src/services/asg/models/launchTemplate.js +41 -0
  26. package/src/services/asg/models/scalingPolicy.js +51 -0
  27. package/src/services/asg/server.js +236 -0
  28. package/src/services/asg/simulator.js +410 -0
  29. package/src/services/aurora/cluster-manager.js +731 -0
  30. package/src/services/aurora/data-api.js +514 -0
  31. package/src/services/aurora/db-engine.js +270 -0
  32. package/src/services/aurora/index.js +159 -0
  33. package/src/services/aurora/rds-api.js +189 -0
  34. package/src/services/aurora/server.js +213 -0
  35. package/src/services/aurora/sql-translator.js +334 -0
  36. package/src/services/cloudformation/index.js +2 -2
  37. package/src/services/cloudformation/server.js +1 -0
  38. package/src/services/cloudfront/cache-engine.js +225 -0
  39. package/src/services/cloudfront/geo-restrictions.js +377 -0
  40. package/src/services/cloudfront/index.js +220 -0
  41. package/src/services/cloudfront/models/behavior.js +158 -0
  42. package/src/services/cloudfront/models/distribution.js +284 -0
  43. package/src/services/cloudfront/models/index.js +99 -0
  44. package/src/services/cloudfront/models/invalidation.js +109 -0
  45. package/src/services/cloudfront/models/origin.js +155 -0
  46. package/src/services/cloudfront/origin-router.js +552 -0
  47. package/src/services/cloudfront/origin-validator.js +398 -0
  48. package/src/services/cloudfront/server.js +512 -0
  49. package/src/services/cloudfront/signed-url-generator.js +377 -0
  50. package/src/services/cloudfront/simulator.js +425 -0
  51. package/src/services/cloudfront/store.js +326 -0
  52. package/src/services/cloudshell/env-builder.js +27 -0
  53. package/src/services/cloudshell/index.js +48 -0
  54. package/src/services/cloudshell/routes.js +60 -0
  55. package/src/services/cloudshell/session-manager.js +226 -0
  56. package/src/services/cloudshell/static/.gitkeep +0 -0
  57. package/src/services/cloudshell/static/index.html +406 -0
  58. package/src/services/cloudshell/websocket-handler.js +107 -0
  59. package/src/services/cloudtrail/index.js +2 -3
  60. package/src/services/cloudtrail/server.js +68 -0
  61. package/src/services/cognito/server.js +4 -1
  62. package/src/services/dynamodb/server.js +4 -1
  63. package/src/services/dynamodb/simulator.js +2 -1
  64. package/src/services/ec2/index.js +101 -0
  65. package/src/services/ec2/instanceServer.js +311 -0
  66. package/src/services/ec2/models/ami.js +39 -0
  67. package/src/services/ec2/models/instance.js +98 -0
  68. package/src/services/ec2/models/networkInterface.js +74 -0
  69. package/src/services/ec2/models/securityGroup.js +71 -0
  70. package/src/services/ec2/server.js +350 -0
  71. package/src/services/ec2/simulator.js +436 -0
  72. package/src/services/eventbridge/server.js +36 -0
  73. package/src/services/eventbridge/simulator.js +230 -45
  74. package/src/services/iam/index.js +65 -0
  75. package/src/services/iam/middleware.js +99 -0
  76. package/src/services/iam/server.js +331 -0
  77. package/src/services/iam/simulator.js +1432 -0
  78. package/src/services/index.js +28 -0
  79. package/src/services/kinesis-analytics/index.js +105 -0
  80. package/src/services/kinesis-analytics/models/application.js +325 -0
  81. package/src/services/kinesis-analytics/models/index.js +12 -0
  82. package/src/services/kinesis-analytics/server.js +250 -0
  83. package/src/services/kinesis-analytics/simulator.js +407 -0
  84. package/src/services/kinesis-analytics/store.js +176 -0
  85. package/src/services/kinesis-data-streams/index.js +106 -0
  86. package/src/services/kinesis-data-streams/models/index.js +12 -0
  87. package/src/services/kinesis-data-streams/models/record.js +70 -0
  88. package/src/services/kinesis-data-streams/models/stream.js +280 -0
  89. package/src/services/kinesis-data-streams/server.js +255 -0
  90. package/src/services/kinesis-data-streams/simulator.js +514 -0
  91. package/src/services/kinesis-data-streams/store.js +163 -0
  92. package/src/services/kinesis-firehose/index.js +106 -0
  93. package/src/services/kinesis-firehose/models/delivery-stream.js +265 -0
  94. package/src/services/kinesis-firehose/models/index.js +10 -0
  95. package/src/services/kinesis-firehose/server.js +215 -0
  96. package/src/services/kinesis-firehose/simulator.js +388 -0
  97. package/src/services/kinesis-firehose/store.js +163 -0
  98. package/src/services/kms/server.js +4 -1
  99. package/src/services/lambda/index.js +26 -0
  100. package/src/services/lambda/server.js +12 -1
  101. package/src/services/lambda/simulator.js +4 -0
  102. package/src/services/opensearch/index.js +105 -0
  103. package/src/services/opensearch/models/document.js +115 -0
  104. package/src/services/opensearch/models/index.js +73 -0
  105. package/src/services/opensearch/server.js +310 -0
  106. package/src/services/opensearch/simulator.js +605 -0
  107. package/src/services/opensearch/store.js +162 -0
  108. package/src/services/organizations/control-tower-simulator.js +321 -0
  109. package/src/services/organizations/control-tower-store.js +182 -0
  110. package/src/services/organizations/iam-integration.js +413 -0
  111. package/src/services/organizations/index.js +172 -0
  112. package/src/services/organizations/models/index.js +13 -0
  113. package/src/services/organizations/models/invitation.js +48 -0
  114. package/src/services/organizations/models/organization.js +566 -0
  115. package/src/services/organizations/models/role.js +244 -0
  116. package/src/services/organizations/models/scp.js +131 -0
  117. package/src/services/organizations/server.js +736 -0
  118. package/src/services/organizations/simulator.js +593 -0
  119. package/src/services/organizations/store.js +235 -0
  120. package/src/services/organizations/vpc-integration.js +453 -0
  121. package/src/services/route53/index.js +67 -0
  122. package/src/services/route53/models/healthCheck.js +101 -0
  123. package/src/services/route53/models/hostedZone.js +37 -0
  124. package/src/services/route53/models/resourceRecord.js +106 -0
  125. package/src/services/route53/server.js +841 -0
  126. package/src/services/route53/simulator.js +350 -0
  127. package/src/services/s3/index.js +62 -0
  128. package/src/services/s3/presigned-url-generator.js +337 -0
  129. package/src/services/s3/server.js +231 -0
  130. package/src/services/s3/simulator.js +551 -4
  131. package/src/services/sns/index.js +31 -0
  132. package/src/services/sns/server.js +9 -0
  133. package/src/services/sqs/index.js +38 -0
  134. package/src/services/sqs/server.js +57 -4
  135. package/src/services/sqs/simulator.js +423 -33
  136. package/src/services/sts/simulator.js +209 -17
  137. package/src/services/vpc/README.md +459 -0
  138. package/src/services/vpc/ec2ResponseFormatter.js +431 -0
  139. package/src/services/vpc/index.js +90 -0
  140. package/src/services/vpc/models/internetGateway.js +71 -0
  141. package/src/services/vpc/models/routeTable.js +160 -0
  142. package/src/services/vpc/models/subnet.js +48 -0
  143. package/src/services/vpc/models/vpc.js +37 -0
  144. package/src/services/vpc/models/vpcEndpoint.js +100 -0
  145. package/src/services/vpc/models/vpcGateway.js +134 -0
  146. package/src/services/vpc/server.js +836 -0
  147. package/src/services/vpc/simulator.js +613 -0
  148. package/src/utils/policy-cache.js +215 -0
  149. package/aws-config +0 -154
@@ -0,0 +1,333 @@
1
+ /**
2
+ * CloudTrail Logger Middleware
3
+ *
4
+ * Loga todos os acessos (permitidos e negados) em CloudTrail
5
+ * para auditoria e compliance
6
+ */
7
+
8
+ const logger = require('../utils/logger');
9
+
10
+ class CloudTrailLoggerMiddleware {
11
+ constructor(cloudtrailService) {
12
+ this.cloudtrailService = cloudtrailService;
13
+ }
14
+
15
+ /**
16
+ * Middleware para logar eventos no CloudTrail
17
+ */
18
+ middleware(serviceName = 'unknown') {
19
+ return async (req, res, next) => {
20
+ try {
21
+ // Interceptar resposta para capturar status
22
+ const originalJson = res.json;
23
+ const originalSend = res.send;
24
+
25
+ let responseData = null;
26
+ let responseStatus = res.statusCode;
27
+
28
+ res.json = function(data) {
29
+ responseData = data;
30
+ responseStatus = res.statusCode;
31
+ return originalJson.call(this, data);
32
+ };
33
+
34
+ res.send = function(data) {
35
+ responseData = data;
36
+ responseStatus = res.statusCode;
37
+ return originalSend.call(this, data);
38
+ };
39
+
40
+ // Logar após resposta ser enviada
41
+ res.on('finish', async () => {
42
+ try {
43
+ await this.logToCloudTrail(
44
+ req,
45
+ responseStatus,
46
+ serviceName,
47
+ responseData
48
+ );
49
+ } catch (error) {
50
+ logger.debug('Error logging to CloudTrail:', error.message);
51
+ }
52
+ });
53
+
54
+ next();
55
+ } catch (error) {
56
+ logger.error('CloudTrail logger error:', error.message);
57
+ next();
58
+ }
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Registrar evento no CloudTrail
64
+ */
65
+ async logToCloudTrail(req, statusCode, serviceName, responseData) {
66
+ try {
67
+ if (!this.cloudtrailService || !this.cloudtrailService.simulador) {
68
+ return;
69
+ }
70
+
71
+ // Extrair informações do request
72
+ const {
73
+ method,
74
+ path,
75
+ headers,
76
+ body,
77
+ principal,
78
+ accountId,
79
+ roleArn,
80
+ policyDecision
81
+ } = req;
82
+
83
+ const eventName = this.mapRequestToEventName(method, path, serviceName);
84
+ const resourceName = this.mapPathToResourceName(path);
85
+ const sourceIPAddress = this.getSourceIP(req);
86
+
87
+ // Determinar sucesso/falha
88
+ const isSuccess = statusCode >= 200 && statusCode < 400;
89
+ const isAccessDenied = statusCode === 403;
90
+
91
+ // Construir evento CloudTrail
92
+ const event = {
93
+ eventTime: new Date(),
94
+ eventName,
95
+ eventSource: `${serviceName}.amazonaws.com`,
96
+ awsRegion: headers['x-amz-target']?.split('.')[0] || 'us-east-1',
97
+ sourceIPAddress,
98
+ userAgent: headers['user-agent'] || 'AWS-CLI',
99
+ userIdentity: {
100
+ type: principal?.type || 'Unknown',
101
+ principalId: principal?.roleArn || principal?.credentials?.accessKeyId || 'Unknown',
102
+ arn: roleArn || 'Unknown',
103
+ accountId: accountId || 'Unknown',
104
+ invokedBy: principal?.sessionName || 'Unknown',
105
+ accessKeyId: principal?.credentials?.accessKeyId || 'Unknown',
106
+ sessionContext: {
107
+ attributes: {
108
+ mfaAuthenticated: !!principal?.credentials?.sessionToken,
109
+ creationDate: principal?.issuedAt
110
+ },
111
+ sessionIssuer: {
112
+ type: 'Role',
113
+ principalId: roleArn || 'Unknown',
114
+ arn: roleArn || 'Unknown',
115
+ accountId: accountId || 'Unknown',
116
+ userName: principal?.sessionName || 'Unknown'
117
+ }
118
+ }
119
+ },
120
+ requestParameters: {
121
+ method,
122
+ path,
123
+ resourceName,
124
+ ...this.extractRequestParams(body)
125
+ },
126
+ responseElements: isAccessDenied ? null : this.extractResponseElements(responseData),
127
+ additionalEventData: {
128
+ x_amzn_requestId: req.requestId,
129
+ principalOrgId: accountId,
130
+ policyDecision: policyDecision || null
131
+ },
132
+ requestId: req.requestId,
133
+ eventId: this.generateEventId(),
134
+ resources: [
135
+ {
136
+ arn: this.constructResourceARN(serviceName, resourceName, accountId),
137
+ accountId,
138
+ type: this.mapServiceToResourceType(serviceName)
139
+ }
140
+ ],
141
+ eventType: 'AwsApiCall',
142
+ recipientAccountId: accountId || 'Unknown',
143
+ sharedEventID: this.generateEventId(),
144
+ vpcEndpointId: null
145
+ };
146
+
147
+ // Logar resultado
148
+ if (isSuccess) {
149
+ event.requestStatus = 'Success';
150
+ logger.debug(`CloudTrail: ${eventName} - SUCCESS`, {
151
+ principal: roleArn,
152
+ resource: resourceName,
153
+ account: accountId
154
+ });
155
+ } else if (isAccessDenied) {
156
+ event.requestStatus = 'AccessDenied';
157
+ event.errorCode = 'AccessDenied';
158
+ event.errorMessage = policyDecision?.message || 'User is not authorized';
159
+ logger.debug(`CloudTrail: ${eventName} - ACCESS DENIED`, {
160
+ principal: roleArn,
161
+ deniedBy: policyDecision?.deniedBy,
162
+ resource: resourceName
163
+ });
164
+ } else {
165
+ event.requestStatus = 'Failure';
166
+ event.errorCode = this.mapStatusToErrorCode(statusCode);
167
+ logger.debug(`CloudTrail: ${eventName} - FAILURE (${statusCode})`, {
168
+ principal: roleArn,
169
+ resource: resourceName
170
+ });
171
+ }
172
+
173
+ // Registrar no CloudTrail
174
+ this.cloudtrailService.simulador.recordEvent(event);
175
+ } catch (error) {
176
+ logger.debug('Error constructing CloudTrail event:', error.message);
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Mapear HTTP method + path → CloudTrail event name
182
+ */
183
+ mapRequestToEventName(method, path, serviceName) {
184
+ const pathParts = path.toLowerCase().split('/').filter(p => p);
185
+ const resource = pathParts[0] || 'unknown';
186
+
187
+ const methodMap = {
188
+ POST: 'Create',
189
+ PUT: 'Put',
190
+ GET: 'Get',
191
+ DELETE: 'Delete',
192
+ PATCH: 'Update',
193
+ HEAD: 'Head'
194
+ };
195
+
196
+ const verb = methodMap[method] || 'Invoke';
197
+ const resourceName = resource.charAt(0).toUpperCase() + resource.slice(1, -1);
198
+
199
+ return `${verb}${resourceName}`;
200
+ }
201
+
202
+ /**
203
+ * Extrair nome do recurso do path
204
+ */
205
+ mapPathToResourceName(path) {
206
+ const parts = path.split('/').filter(p => p && p !== '__admin');
207
+ return parts[0] || 'resource';
208
+ }
209
+
210
+ /**
211
+ * Obter IP de origem
212
+ */
213
+ getSourceIP(req) {
214
+ return (
215
+ req.headers['x-forwarded-for']?.split(',')[0] ||
216
+ req.socket.remoteAddress ||
217
+ 'unknown'
218
+ );
219
+ }
220
+
221
+ /**
222
+ * Extrair parâmetros do request
223
+ */
224
+ extractRequestParams(body) {
225
+ if (!body) return {};
226
+
227
+ if (typeof body === 'string') {
228
+ try {
229
+ return JSON.parse(body);
230
+ } catch (e) {
231
+ return { rawBody: body.substring(0, 100) };
232
+ }
233
+ }
234
+
235
+ if (typeof body === 'object') {
236
+ return body;
237
+ }
238
+
239
+ return {};
240
+ }
241
+
242
+ /**
243
+ * Extrair elementos da resposta (sem dados sensíveis)
244
+ */
245
+ extractResponseElements(data) {
246
+ if (!data) return null;
247
+
248
+ if (typeof data === 'object') {
249
+ return {
250
+ ...data,
251
+ // Remover dados sensíveis
252
+ SecretAccessKey: '***',
253
+ Password: '***',
254
+ PrivateKey: '***'
255
+ };
256
+ }
257
+
258
+ return null;
259
+ }
260
+
261
+ /**
262
+ * Construir ARN do recurso
263
+ */
264
+ constructResourceARN(serviceName, resourceName, accountId) {
265
+ const account = accountId || '*';
266
+ const region = '*';
267
+
268
+ switch (serviceName) {
269
+ case 's3':
270
+ return `arn:aws:s3:::${resourceName}`;
271
+ case 'sqs':
272
+ return `arn:aws:sqs:${region}:${account}:${resourceName}`;
273
+ case 'sns':
274
+ return `arn:aws:sns:${region}:${account}:${resourceName}`;
275
+ case 'dynamodb':
276
+ return `arn:aws:dynamodb:${region}:${account}:table/${resourceName}`;
277
+ case 'lambda':
278
+ return `arn:aws:lambda:${region}:${account}:function:${resourceName}`;
279
+ case 'kms':
280
+ return `arn:aws:kms:${region}:${account}:key/${resourceName}`;
281
+ case 'ec2':
282
+ return `arn:aws:ec2:${region}:${account}:${resourceName}/*`;
283
+ default:
284
+ return `arn:aws:${serviceName}:${region}:${account}:${resourceName}`;
285
+ }
286
+ }
287
+
288
+ /**
289
+ * Mapear service → resource type do CloudTrail
290
+ */
291
+ mapServiceToResourceType(serviceName) {
292
+ const typeMap = {
293
+ s3: 'AWS::S3::Bucket',
294
+ sqs: 'AWS::SQS::Queue',
295
+ sns: 'AWS::SNS::Topic',
296
+ dynamodb: 'AWS::DynamoDB::Table',
297
+ lambda: 'AWS::Lambda::Function',
298
+ kms: 'AWS::KMS::Key',
299
+ ec2: 'AWS::EC2::Instance',
300
+ iam: 'AWS::IAM::Role',
301
+ sts: 'AWS::STS::AssumedRole'
302
+ };
303
+
304
+ return typeMap[serviceName] || 'AWS::Unknown::Resource';
305
+ }
306
+
307
+ /**
308
+ * Mapear HTTP status → CloudTrail error code
309
+ */
310
+ mapStatusToErrorCode(statusCode) {
311
+ const codeMap = {
312
+ 400: 'BadRequest',
313
+ 401: 'Unauthorized',
314
+ 403: 'AccessDenied',
315
+ 404: 'NotFound',
316
+ 409: 'Conflict',
317
+ 429: 'ThrottlingException',
318
+ 500: 'InternalError',
319
+ 503: 'ServiceUnavailable'
320
+ };
321
+
322
+ return codeMap[statusCode] || 'UnknownError';
323
+ }
324
+
325
+ /**
326
+ * Gerar ID único para evento
327
+ */
328
+ generateEventId() {
329
+ return require('crypto').randomUUID();
330
+ }
331
+ }
332
+
333
+ module.exports = CloudTrailLoggerMiddleware;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Error Handler Middleware
3
+ *
4
+ * Formata erros no padrão AWS
5
+ */
6
+
7
+ const crypto = require('crypto');
8
+ const logger = require('../utils/logger');
9
+
10
+ class ErrorHandlerMiddleware {
11
+ /**
12
+ * Middleware Express para tratamento de erros
13
+ */
14
+ static errorHandler() {
15
+ return (err, req, res, next) => {
16
+ const requestId = req.requestId || ErrorHandlerMiddleware.generateRequestId();
17
+
18
+ logger.error('Request error:', {
19
+ requestId,
20
+ message: err.message,
21
+ stack: err.stack,
22
+ path: req.path,
23
+ method: req.method
24
+ });
25
+
26
+ // Se já foi enviada resposta, não fazer nada
27
+ if (res.headersSent) {
28
+ return next(err);
29
+ }
30
+
31
+ // Erro de autorização
32
+ if (err.code === 'AccessDenied' || err.statusCode === 403) {
33
+ return res.status(403).json({
34
+ code: 'AccessDenied',
35
+ message: err.message || 'Access Denied',
36
+ requestId
37
+ });
38
+ }
39
+
40
+ // Erro de validação
41
+ if (err.code === 'ValidationException' || err.statusCode === 400) {
42
+ return res.status(400).json({
43
+ code: 'ValidationException',
44
+ message: err.message || 'Invalid request',
45
+ requestId
46
+ });
47
+ }
48
+
49
+ // Erro de recurso não encontrado
50
+ if (err.code === 'NotFound' || err.statusCode === 404) {
51
+ return res.status(404).json({
52
+ code: 'NotFound',
53
+ message: err.message || 'Resource not found',
54
+ requestId
55
+ });
56
+ }
57
+
58
+ // Erro de conflito
59
+ if (err.code === 'ConflictException' || err.statusCode === 409) {
60
+ return res.status(409).json({
61
+ code: 'ConflictException',
62
+ message: err.message || 'Resource already exists',
63
+ requestId
64
+ });
65
+ }
66
+
67
+ // Erro interno
68
+ if (err.statusCode === 500 || !err.statusCode) {
69
+ return res.status(500).json({
70
+ code: 'InternalError',
71
+ message: 'Internal server error',
72
+ requestId
73
+ });
74
+ }
75
+
76
+ // Erro genérico
77
+ res.status(err.statusCode || 500).json({
78
+ code: err.code || 'UnknownError',
79
+ message: err.message || 'An error occurred',
80
+ requestId
81
+ });
82
+ };
83
+ }
84
+
85
+ /**
86
+ * Middleware para capturar rotas não encontradas
87
+ */
88
+ static notFound() {
89
+ return (req, res) => {
90
+ const requestId = ErrorHandlerMiddleware.generateRequestId();
91
+
92
+ res.status(404).json({
93
+ code: 'NotFound',
94
+ message: `${req.method} ${req.path} not found`,
95
+ requestId
96
+ });
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Gera request ID único
102
+ */
103
+ static generateRequestId() {
104
+ return crypto.randomBytes(8).toString('hex').toUpperCase();
105
+ }
106
+
107
+ /**
108
+ * Middleware para adicionar requestId em cada requisição
109
+ */
110
+ static requestIdMiddleware() {
111
+ return (req, res, next) => {
112
+ req.requestId = ErrorHandlerMiddleware.generateRequestId();
113
+ res.set('X-Amz-Request-Id', req.requestId);
114
+ next();
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Wrapper para async route handlers (catch errors automaticamente)
120
+ */
121
+ static asyncHandler(fn) {
122
+ return (req, res, next) => {
123
+ Promise.resolve(fn(req, res, next)).catch(next);
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Criar erro no formato AWS
129
+ */
130
+ static createError(code, message, statusCode = 400) {
131
+ const error = new Error(message);
132
+ error.code = code;
133
+ error.statusCode = statusCode;
134
+ return error;
135
+ }
136
+ }
137
+
138
+ module.exports = ErrorHandlerMiddleware;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Middleware Index
3
+ *
4
+ * Exporta todos os middlewares para fácil integração nos serviços
5
+ */
6
+
7
+ const AuthorizationMiddleware = require('./authorization');
8
+ const PolicyEnforcementMiddleware = require('./policy-enforcement');
9
+ const ErrorHandlerMiddleware = require('./error-handler');
10
+ const CloudTrailLoggerMiddleware = require('./cloudtrail-logger');
11
+
12
+ /**
13
+ * Factory para criar middlewares configurados
14
+ */
15
+ class MiddlewareFactory {
16
+ static createAuthorizationMiddleware(organizationsService, stsService) {
17
+ const auth = new AuthorizationMiddleware(organizationsService, stsService);
18
+ return auth.middleware();
19
+ }
20
+
21
+ static createPolicyEnforcementMiddleware(organizationsService, service = 'unknown') {
22
+ const enforcement = new PolicyEnforcementMiddleware(organizationsService);
23
+ return enforcement.middleware(service);
24
+ }
25
+
26
+ static createErrorHandler() {
27
+ return ErrorHandlerMiddleware.errorHandler();
28
+ }
29
+
30
+ static createNotFoundHandler() {
31
+ return ErrorHandlerMiddleware.notFound();
32
+ }
33
+
34
+ static createRequestIdMiddleware() {
35
+ return ErrorHandlerMiddleware.requestIdMiddleware();
36
+ }
37
+
38
+ static asyncHandler(fn) {
39
+ return ErrorHandlerMiddleware.asyncHandler(fn);
40
+ }
41
+
42
+ static createError(code, message, statusCode = 400) {
43
+ return ErrorHandlerMiddleware.createError(code, message, statusCode);
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Setup padrão para um serviço
49
+ * Registra middlewares na ordem correta
50
+ */
51
+ function setupServiceMiddleware(app, organizationsService, stsService, serviceName = 'unknown') {
52
+ // 1. RequestId (primeiro, para tracking)
53
+ app.use(ErrorHandlerMiddleware.requestIdMiddleware());
54
+
55
+ // 2. Authorization (extrair principal)
56
+ app.use(MiddlewareFactory.createAuthorizationMiddleware(organizationsService, stsService));
57
+
58
+ // 3. Policy Enforcement (validar SCP + IAM)
59
+ app.use(MiddlewareFactory.createPolicyEnforcementMiddleware(organizationsService, serviceName));
60
+
61
+ // 4. CloudTrail Logging (logar eventos permitidos e negados)
62
+ const cloudtrailService = organizationsService?.organizationsSimulator?.server?.app?.locals?.cloudtrailService;
63
+ if (cloudtrailService) {
64
+ const cloudtrailLogger = new CloudTrailLoggerMiddleware(cloudtrailService);
65
+ app.use(cloudtrailLogger.middleware(serviceName));
66
+ }
67
+
68
+ // 5. Error handler (último)
69
+ app.use(ErrorHandlerMiddleware.errorHandler());
70
+ }
71
+
72
+ module.exports = {
73
+ AuthorizationMiddleware,
74
+ PolicyEnforcementMiddleware,
75
+ ErrorHandlerMiddleware,
76
+ CloudTrailLoggerMiddleware,
77
+ MiddlewareFactory,
78
+ setupServiceMiddleware
79
+ };