@gugananuvem/aws-local-simulator 1.0.34 → 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 (150) hide show
  1. package/README.md +662 -658
  2. package/package.json +11 -4
  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/handler-loader.js +50 -5
  100. package/src/services/lambda/index.js +26 -0
  101. package/src/services/lambda/server.js +18 -12
  102. package/src/services/lambda/simulator.js +73 -17
  103. package/src/services/opensearch/index.js +105 -0
  104. package/src/services/opensearch/models/document.js +115 -0
  105. package/src/services/opensearch/models/index.js +73 -0
  106. package/src/services/opensearch/server.js +310 -0
  107. package/src/services/opensearch/simulator.js +605 -0
  108. package/src/services/opensearch/store.js +162 -0
  109. package/src/services/organizations/control-tower-simulator.js +321 -0
  110. package/src/services/organizations/control-tower-store.js +182 -0
  111. package/src/services/organizations/iam-integration.js +413 -0
  112. package/src/services/organizations/index.js +172 -0
  113. package/src/services/organizations/models/index.js +13 -0
  114. package/src/services/organizations/models/invitation.js +48 -0
  115. package/src/services/organizations/models/organization.js +566 -0
  116. package/src/services/organizations/models/role.js +244 -0
  117. package/src/services/organizations/models/scp.js +131 -0
  118. package/src/services/organizations/server.js +736 -0
  119. package/src/services/organizations/simulator.js +593 -0
  120. package/src/services/organizations/store.js +235 -0
  121. package/src/services/organizations/vpc-integration.js +453 -0
  122. package/src/services/route53/index.js +67 -0
  123. package/src/services/route53/models/healthCheck.js +101 -0
  124. package/src/services/route53/models/hostedZone.js +37 -0
  125. package/src/services/route53/models/resourceRecord.js +106 -0
  126. package/src/services/route53/server.js +841 -0
  127. package/src/services/route53/simulator.js +350 -0
  128. package/src/services/s3/index.js +62 -0
  129. package/src/services/s3/presigned-url-generator.js +337 -0
  130. package/src/services/s3/server.js +231 -0
  131. package/src/services/s3/simulator.js +551 -4
  132. package/src/services/sns/index.js +31 -0
  133. package/src/services/sns/server.js +9 -0
  134. package/src/services/sqs/index.js +38 -0
  135. package/src/services/sqs/server.js +57 -4
  136. package/src/services/sqs/simulator.js +423 -33
  137. package/src/services/sts/simulator.js +209 -17
  138. package/src/services/vpc/README.md +459 -0
  139. package/src/services/vpc/ec2ResponseFormatter.js +431 -0
  140. package/src/services/vpc/index.js +90 -0
  141. package/src/services/vpc/models/internetGateway.js +71 -0
  142. package/src/services/vpc/models/routeTable.js +160 -0
  143. package/src/services/vpc/models/subnet.js +48 -0
  144. package/src/services/vpc/models/vpc.js +37 -0
  145. package/src/services/vpc/models/vpcEndpoint.js +100 -0
  146. package/src/services/vpc/models/vpcGateway.js +134 -0
  147. package/src/services/vpc/server.js +836 -0
  148. package/src/services/vpc/simulator.js +613 -0
  149. package/src/utils/policy-cache.js +215 -0
  150. package/aws-config +0 -154
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gugananuvem/aws-local-simulator",
3
- "version": "1.0.34",
3
+ "version": "1.0.39",
4
4
  "description": "Simulador local completo para serviços AWS",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -10,7 +10,6 @@
10
10
  "start": "node bin/aws-local-simulator.js start"
11
11
  },
12
12
  "dependencies": {
13
- "better-sqlite3": "^11.0.0",
14
13
  "@aws-sdk/client-api-gateway": "^3.0.0",
15
14
  "@aws-sdk/client-cognito-identity-provider": "^3.0.0",
16
15
  "@aws-sdk/client-dynamodb": "^3.0.0",
@@ -19,6 +18,8 @@
19
18
  "@aws-sdk/client-s3": "^3.0.0",
20
19
  "@aws-sdk/client-sqs": "^3.0.0",
21
20
  "@aws-sdk/lib-dynamodb": "^3.0.0",
21
+ "axios": "1.20.0",
22
+ "better-sqlite3": "11.10.0",
22
23
  "child_process": "1.0.2",
23
24
  "cors": "^2.8.5",
24
25
  "crypto": "1.0.1",
@@ -27,13 +28,19 @@
27
28
  "fs": "0.0.1-security",
28
29
  "glob": "10.5.0",
29
30
  "http": "0.0.1-security",
31
+ "http-proxy-middleware": "^2.0.6",
30
32
  "js-yaml": "4.1.1",
31
33
  "jsonwebtoken": "^9.0.2",
34
+ "luxon": "3.7.2",
32
35
  "mkdirp": "^3.0.1",
36
+ "node-pty": "1.1.0",
33
37
  "path": "0.12.7",
34
38
  "url": "0.11.4",
35
39
  "urlpattern-polyfill": "^10.0.0",
36
- "uuid": "14.0.0"
40
+ "uuid": "14.0.0",
41
+ "ws": "8.21.0",
42
+ "xml2js": "0.6.2",
43
+ "xmlbuilder": "15.1.1"
37
44
  },
38
45
  "keywords": [
39
46
  "aws",
@@ -67,6 +74,6 @@
67
74
  "publishConfig": {
68
75
  "directory": "dist"
69
76
  },
70
- "buildDate": "2026-06-23T12:54:20.022Z",
77
+ "buildDate": "2026-10-09T19:19:07.184Z",
71
78
  "published": true
72
79
  }
@@ -19,6 +19,16 @@ module.exports = {
19
19
  "parameter-store": true,
20
20
  kms: true,
21
21
  kinesis: true,
22
+ ec2: true,
23
+ alb: true,
24
+ asg: true,
25
+ opensearch: true,
26
+ "kinesis-data-streams": true,
27
+ "kinesis-firehose": true,
28
+ "kinesis-analytics": true,
29
+ organizations: true,
30
+ route53: true,
31
+ acm: true,
22
32
  },
23
33
 
24
34
  // Portas padrão
@@ -38,6 +48,17 @@ module.exports = {
38
48
  parameterStore: 4002,
39
49
  kms: 4000,
40
50
  kinesis: 4568,
51
+ "kinesis-data-streams": 4568,
52
+ "kinesis-firehose": 4569,
53
+ "kinesis-analytics": 4570,
54
+ ec2: 4020,
55
+ alb: 4021,
56
+ asg: 4022,
57
+ opensearch: 9200,
58
+ organizations: 4581,
59
+ cloudformation: 4582,
60
+ route53: 4024,
61
+ acm: 4025,
41
62
  },
42
63
  apigateway: {
43
64
  defaultCors: {
@@ -76,4 +97,54 @@ module.exports = {
76
97
 
77
98
  // Porta do servidor de administração (Management API)
78
99
  adminPort: 9999,
100
+
101
+ // Organizations Policy Enforcement
102
+ // Aplica SCP + IAM roles em todos os serviços (como na AWS real)
103
+ organizationsPolicyEnforcement: {
104
+ // Ativar/desativar validação de políticas globalmente
105
+ enabled: false,
106
+
107
+ // Exigir contexto de conta (STS AssumeRole)
108
+ // Se true, requisições sem credenciais são negadas
109
+ // Se false, requisições sem credenciais usam comportamento padrão
110
+ requireAccountContext: false,
111
+
112
+ // Configuração de avaliação de SCP
113
+ scpEvaluation: {
114
+ enabled: true,
115
+ // Log tentativas negadas
116
+ logDenials: true,
117
+ // Log tentativas permitidas
118
+ logAllowances: false,
119
+ // TTL do cache de avaliações (em ms)
120
+ cacheTTL: 60000, // 60 segundos
121
+ // Timeout para avaliação (em ms)
122
+ timeout: 5000
123
+ },
124
+
125
+ // Serviços que têm enforcement habilitado
126
+ enforcedServices: [
127
+ 's3',
128
+ 'sqs',
129
+ 'sns',
130
+ 'dynamodb',
131
+ 'cognito',
132
+ 'kms',
133
+ 'lambda',
134
+ 'ec2',
135
+ 'apigateway',
136
+ 'cloudformation',
137
+ 'iam',
138
+ 'sts',
139
+ 'opensearch',
140
+ 'cloudwatch',
141
+ 'cloudtrail'
142
+ ],
143
+
144
+ // Duração padrão de temporary credentials (em segundos)
145
+ credentialDuration: 3600, // 1 hora
146
+
147
+ // Prefixo para SessionToken (para identificar tokens STS)
148
+ sessionTokenPrefix: 'AQOD'
149
+ },
79
150
  };
@@ -16,7 +16,8 @@ class EnvLoader {
16
16
  sns: this.getEnvBool('AWS_LOCAL_SIMULATOR_SNS', false),
17
17
  lambda: this.getEnvBool('AWS_LOCAL_SIMULATOR_LAMBDA', true),
18
18
  apigateway: this.getEnvBool('AWS_LOCAL_SIMULATOR_APIGATEWAY', false),
19
- eventbridge: this.getEnvBool('AWS_LOCAL_SIMULATOR_EVENTBRIDGE', false)
19
+ eventbridge: this.getEnvBool('AWS_LOCAL_SIMULATOR_EVENTBRIDGE', false),
20
+ vpc: this.getEnvBool('AWS_LOCAL_SIMULATOR_VPC', false)
20
21
  };
21
22
 
22
23
  // Carrega portas
@@ -27,7 +28,8 @@ class EnvLoader {
27
28
  lambda: this.getEnvInt('AWS_LOCAL_SIMULATOR_LAMBDA_PORT', 3001),
28
29
  sns: this.getEnvInt('AWS_LOCAL_SIMULATOR_SNS_PORT', 9911),
29
30
  apigateway: this.getEnvInt('AWS_LOCAL_SIMULATOR_APIGATEWAY_PORT', 4567),
30
- eventbridge: this.getEnvInt('AWS_LOCAL_SIMULATOR_EVENTBRIDGE_PORT', 4010)
31
+ eventbridge: this.getEnvInt('AWS_LOCAL_SIMULATOR_EVENTBRIDGE_PORT', 4010),
32
+ vpc: this.getEnvInt('AWS_LOCAL_SIMULATOR_VPC_PORT', 4014)
31
33
  };
32
34
 
33
35
  // Carrega diretório de dados
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Authorization Middleware
3
+ *
4
+ * Extrai e valida o principal (usuário/role/assumed-role) das requisições
5
+ * Suporta:
6
+ * - AWS SigV4 (Authorization header)
7
+ * - SessionToken (X-Amz-Security-Token)
8
+ * - Headers customizados (X-Account-Id, X-Role-Arn)
9
+ */
10
+
11
+ const crypto = require('crypto');
12
+ const logger = require('../utils/logger');
13
+
14
+ class AuthorizationMiddleware {
15
+ constructor(organizationsService, stsService) {
16
+ this.organizationsService = organizationsService;
17
+ this.stsService = stsService;
18
+ this.principalCache = new Map();
19
+ this.cacheTTL = 300000; // 5 minutes
20
+ }
21
+
22
+ /**
23
+ * Middleware Express para extrair principal
24
+ */
25
+ middleware() {
26
+ return async (req, res, next) => {
27
+ try {
28
+ const enforced = req.app.locals.organizationsPolicyEnforcement?.enabled;
29
+
30
+ if (!enforced) {
31
+ // Se enforcement desativado, continua sem validar
32
+ req.principal = null;
33
+ req.credentials = null;
34
+ return next();
35
+ }
36
+
37
+ // Extrair principal de múltiplas fontes
38
+ const principal = await this.extractPrincipal(req);
39
+
40
+ if (!principal) {
41
+ // Se enforcement ativado mas sem credenciais, nega
42
+ return res.status(403).json({
43
+ code: 'InvalidCredentials',
44
+ message: 'Missing or invalid AWS credentials. Set Authorization header or AWS_ACCESS_KEY_ID environment variable.',
45
+ requestId: this.generateRequestId()
46
+ });
47
+ }
48
+
49
+ // Validar se principal ainda existe e não expirou
50
+ const isValid = await this.validatePrincipal(principal);
51
+ if (!isValid) {
52
+ return res.status(403).json({
53
+ code: 'InvalidCredentials',
54
+ message: 'Invalid or expired credentials',
55
+ requestId: this.generateRequestId()
56
+ });
57
+ }
58
+
59
+ req.principal = principal;
60
+ req.credentials = principal.credentials;
61
+ req.accountId = principal.accountId;
62
+ req.roleArn = principal.roleArn;
63
+
64
+ next();
65
+ } catch (error) {
66
+ logger.error('Authorization error:', error.message);
67
+ res.status(500).json({
68
+ code: 'InternalError',
69
+ message: 'Internal error during authorization',
70
+ requestId: this.generateRequestId()
71
+ });
72
+ }
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Extrai principal de:
78
+ * 1. Authorization header (AWS SigV4)
79
+ * 2. X-Amz-Security-Token header (SessionToken de STS)
80
+ * 3. Headers customizados (X-Account-Id, X-Role-Arn)
81
+ */
82
+ async extractPrincipal(req) {
83
+ // Opção 1: SessionToken do STS (SigV4 com assumed role)
84
+ const sessionToken = req.get('X-Amz-Security-Token');
85
+ if (sessionToken) {
86
+ return this.extractFromSessionToken(sessionToken);
87
+ }
88
+
89
+ // Opção 2: Authorization header (AWS SigV4)
90
+ const authHeader = req.get('Authorization');
91
+ if (authHeader && authHeader.startsWith('AWS4-HMAC-SHA256')) {
92
+ return this.extractFromSigV4(authHeader, req);
93
+ }
94
+
95
+ // Opção 3: Headers customizados (para testes/desenvolvimento)
96
+ const accountId = req.get('X-Account-Id');
97
+ const roleArn = req.get('X-Role-Arn');
98
+ if (accountId && roleArn) {
99
+ return {
100
+ accountId,
101
+ roleArn,
102
+ assumedRole: roleArn,
103
+ sessionName: req.get('X-Session-Name') || 'custom-session',
104
+ credentials: {
105
+ accessKeyId: req.get('X-Access-Key-Id'),
106
+ secretAccessKey: req.get('X-Secret-Access-Key'),
107
+ sessionToken: 'custom-token'
108
+ },
109
+ issuedAt: Date.now(),
110
+ expiresAt: Date.now() + 3600000,
111
+ type: 'custom'
112
+ };
113
+ }
114
+
115
+ // Opção 4: Environment variables (AWS CLI default)
116
+ if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
117
+ return {
118
+ accountId: process.env.AWS_ACCOUNT_ID || '123456789012',
119
+ roleArn: process.env.AWS_ROLE_ARN || 'arn:aws:iam::123456789012:root',
120
+ credentials: {
121
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
122
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
123
+ sessionToken: process.env.AWS_SESSION_TOKEN
124
+ },
125
+ issuedAt: Date.now(),
126
+ expiresAt: Date.now() + 3600000,
127
+ type: 'env'
128
+ };
129
+ }
130
+
131
+ return null;
132
+ }
133
+
134
+ /**
135
+ * Extrai do SessionToken (JWT com assumed role info)
136
+ * Formato: header.payload.signature
137
+ */
138
+ extractFromSessionToken(token) {
139
+ try {
140
+ // Parse JWT simples (sem validar assinatura por enquanto)
141
+ const parts = token.split('.');
142
+ if (parts.length !== 3) {
143
+ throw new Error('Invalid token format');
144
+ }
145
+
146
+ // Decode payload (base64url)
147
+ const payload = JSON.parse(
148
+ Buffer.from(parts[1], 'base64url').toString('utf-8')
149
+ );
150
+
151
+ // Validar expiração
152
+ if (payload.expiresAt < Date.now()) {
153
+ return null; // Token expirado
154
+ }
155
+
156
+ return {
157
+ accountId: payload.accountId,
158
+ roleArn: payload.assumedRole || payload.roleArn,
159
+ assumedRole: payload.assumedRole,
160
+ originalPrincipal: payload.principal,
161
+ sessionName: payload.sessionName,
162
+ credentials: {
163
+ accessKeyId: payload.accessKeyId,
164
+ secretAccessKey: payload.secretAccessKey,
165
+ sessionToken: token
166
+ },
167
+ issuedAt: payload.issuedAt,
168
+ expiresAt: payload.expiresAt,
169
+ type: 'sts'
170
+ };
171
+ } catch (error) {
172
+ logger.debug('Failed to extract from SessionToken:', error.message);
173
+ return null;
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Extrai do Authorization header (AWS SigV4)
179
+ * Formato: AWS4-HMAC-SHA256 Credential=AKIA.../20260930/us-east-1/service/aws4_request, ...
180
+ */
181
+ extractFromSigV4(authHeader, req) {
182
+ try {
183
+ const credentialMatch = authHeader.match(/Credential=([^,]+)/);
184
+ if (!credentialMatch) {
185
+ return null;
186
+ }
187
+
188
+ const credential = credentialMatch[1];
189
+ const [accessKeyId, date, region, service, signatureType] = credential.split('/');
190
+
191
+ // Lookup access key no STS para obter informações do principal
192
+ // Por enquanto, extrair do AccessKeyId
193
+ const accountId = accessKeyId.substring(4, 20); // ASIA prefix é para STS
194
+ const isTemporary = accessKeyId.startsWith('ASIA');
195
+
196
+ return {
197
+ accountId,
198
+ credentials: {
199
+ accessKeyId,
200
+ date,
201
+ region,
202
+ service
203
+ },
204
+ isTemporary,
205
+ type: 'sigv4'
206
+ };
207
+ } catch (error) {
208
+ logger.debug('Failed to extract from SigV4:', error.message);
209
+ return null;
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Valida se principal ainda é válido
215
+ */
216
+ async validatePrincipal(principal) {
217
+ // Verificar cache
218
+ const cacheKey = `principal_${principal.credentials?.accessKeyId || principal.roleArn}`;
219
+ const cached = this.principalCache.get(cacheKey);
220
+
221
+ if (cached && cached.expiresAt > Date.now()) {
222
+ return cached.valid;
223
+ }
224
+
225
+ try {
226
+ // Validar se role ainda existe na organização
227
+ if (this.organizationsService && principal.roleArn) {
228
+ const roleExists = this.organizationsService.organizationsSimulator
229
+ ?.roles?.has(principal.roleArn);
230
+
231
+ if (!roleExists) {
232
+ this.principalCache.set(cacheKey, { valid: false, expiresAt: Date.now() + this.cacheTTL });
233
+ return false;
234
+ }
235
+ }
236
+
237
+ // Validar se credentials não expiraram
238
+ if (principal.expiresAt && principal.expiresAt < Date.now()) {
239
+ this.principalCache.set(cacheKey, { valid: false, expiresAt: Date.now() + this.cacheTTL });
240
+ return false;
241
+ }
242
+
243
+ this.principalCache.set(cacheKey, { valid: true, expiresAt: Date.now() + this.cacheTTL });
244
+ return true;
245
+ } catch (error) {
246
+ logger.debug('Principal validation error:', error.message);
247
+ return false;
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Gera request ID único para rastreamento
253
+ */
254
+ generateRequestId() {
255
+ return crypto.randomBytes(8).toString('hex').toUpperCase();
256
+ }
257
+
258
+ /**
259
+ * Limpa cache expirado
260
+ */
261
+ cleanupCache() {
262
+ const now = Date.now();
263
+ for (const [key, value] of this.principalCache.entries()) {
264
+ if (value.expiresAt < now) {
265
+ this.principalCache.delete(key);
266
+ }
267
+ }
268
+ }
269
+ }
270
+
271
+ module.exports = AuthorizationMiddleware;