@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
@@ -0,0 +1,101 @@
1
+ /**
2
+ * EC2 Service - Ponto de entrada
3
+ */
4
+
5
+ const EC2Server = require('./server');
6
+ const EC2Simulator = require('./simulator');
7
+
8
+ class EC2Service {
9
+ constructor(config) {
10
+ this.config = config;
11
+ this.name = 'ec2';
12
+ this.port = config.ports.ec2 || 4020;
13
+ this.server = null;
14
+ this.simulator = null;
15
+ this.isRunning = false;
16
+ }
17
+
18
+ async initialize() {
19
+ const logger = require('../../utils/logger');
20
+ logger.debug(`Inicializando EC2 Service na porta ${this.port}...`);
21
+
22
+ this.simulator = new EC2Simulator(this.config.ec2 || {});
23
+ await this.simulator.initialize();
24
+
25
+ this.server = new EC2Server(this.port, this.config);
26
+ this.server.simulator = this.simulator;
27
+
28
+ await this.server.initialize();
29
+
30
+ logger.debug('EC2 Service inicializado');
31
+ }
32
+
33
+ injectDependencies(server) {
34
+ // Aqui você pode injetar dependências de outros serviços se necessário
35
+ // Por exemplo, integração com VPC
36
+ }
37
+
38
+ async start() {
39
+ const logger = require('../../utils/logger');
40
+
41
+ if (this.isRunning) {
42
+ logger.warn('EC2 Service já está em execução');
43
+ return;
44
+ }
45
+
46
+ try {
47
+ await this.server.start();
48
+ this.isRunning = true;
49
+ logger.info('EC2 Service iniciado com sucesso');
50
+ } catch (error) {
51
+ logger.error(`Erro ao iniciar EC2 Service: ${error.message}`);
52
+ throw error;
53
+ }
54
+ }
55
+
56
+ async stop() {
57
+ const logger = require('../../utils/logger');
58
+
59
+ if (!this.isRunning) {
60
+ logger.warn('EC2 Service não está em execução');
61
+ return;
62
+ }
63
+
64
+ try {
65
+ // Parar todos os servidores web das instâncias
66
+ for (const [instanceId, server] of this.simulator.instanceServers) {
67
+ await server.stop();
68
+ }
69
+
70
+ await this.server.stop();
71
+ this.isRunning = false;
72
+ logger.info('EC2 Service parado com sucesso');
73
+ } catch (error) {
74
+ logger.error(`Erro ao parar EC2 Service: ${error.message}`);
75
+ throw error;
76
+ }
77
+ }
78
+
79
+ getSimulator() {
80
+ return this.simulator;
81
+ }
82
+
83
+ getStatus() {
84
+ const instances = this.simulator.getAllResources();
85
+ return {
86
+ name: this.name,
87
+ running: this.isRunning,
88
+ port: this.port,
89
+ endpoint: `http://localhost:${this.port}`,
90
+ resources: {
91
+ instancesCount: instances.instances.length,
92
+ runningCount: instances.instances.filter(i => i.isRunning()).length,
93
+ amisCount: instances.amis.length,
94
+ securityGroupsCount: instances.securityGroups.length,
95
+ networkInterfacesCount: instances.networkInterfaces.length
96
+ }
97
+ };
98
+ }
99
+ }
100
+
101
+ module.exports = EC2Service;
@@ -0,0 +1,311 @@
1
+ /**
2
+ * Instance Server - Mini HTTP Server para cada EC2 Instance
3
+ * Serve um site HTML/Angular, página padrão, ou atua como proxy para URL externa
4
+ */
5
+
6
+ const express = require('express');
7
+ const path = require('path');
8
+ const fs = require('fs');
9
+ const axios = require('axios');
10
+ const { createProxyMiddleware } = require('http-proxy-middleware');
11
+ const logger = require('../../utils/logger');
12
+
13
+ class InstanceServer {
14
+ constructor(instance, websiteDir = null) {
15
+ this.instance = instance;
16
+ this.websiteDir = websiteDir;
17
+ this.app = express();
18
+ this.server = null;
19
+ this.setupApp();
20
+ }
21
+
22
+ setupApp() {
23
+ this.app.use(express.json());
24
+
25
+ // Middleware de log
26
+ this.app.use((req, res, next) => {
27
+ logger.debug(`[EC2:${this.instance.InstanceId}] ${req.method} ${req.path}`);
28
+ next();
29
+ });
30
+
31
+ // Health check
32
+ this.app.get('/__health', (req, res) => {
33
+ res.json({
34
+ status: 'ok',
35
+ instanceId: this.instance.InstanceId,
36
+ state: this.instance.State,
37
+ isProxy: !!this.instance.ProxyUrl
38
+ });
39
+ });
40
+
41
+ // Metadata (similar ao AWS metadata service)
42
+ this.app.get('/__metadata', (req, res) => {
43
+ res.json({
44
+ instanceId: this.instance.InstanceId,
45
+ instanceType: this.instance.InstanceType,
46
+ privateIp: this.instance.PrivateIpAddress,
47
+ publicIp: this.instance.PublicIpAddress,
48
+ vpcId: this.instance.VpcId,
49
+ subnetId: this.instance.SubnetId,
50
+ launchTime: this.instance.LaunchTime,
51
+ imageId: this.instance.ImageId,
52
+ proxyUrl: this.instance.ProxyUrl || null
53
+ });
54
+ });
55
+
56
+ // Se ProxyUrl configurada, usar http-proxy-middleware
57
+ if (this.instance.ProxyUrl) {
58
+ logger.info(`[EC2:${this.instance.InstanceId}] 🔗 Proxy configurado para: ${this.instance.ProxyUrl}`);
59
+
60
+ this.app.use('/', createProxyMiddleware({
61
+ target: this.instance.ProxyUrl,
62
+ changeOrigin: true,
63
+ pathRewrite: {},
64
+ ws: true, // WebSocket suport
65
+ logLevel: 'warn',
66
+ onError: (err, req, res) => {
67
+ logger.error(`[EC2:${this.instance.InstanceId}] Proxy error: ${err.message}`);
68
+ res.status(503).json({
69
+ error: 'Proxy service unavailable',
70
+ target: this.instance.ProxyUrl,
71
+ message: err.message
72
+ });
73
+ }
74
+ }));
75
+ } else if (this.websiteDir && fs.existsSync(this.websiteDir)) {
76
+ // Se website dir configurado, servir arquivos estáticos
77
+ logger.info(`[EC2:${this.instance.InstanceId}] Servindo website de: ${this.websiteDir}`);
78
+ this.app.use(express.static(this.websiteDir));
79
+
80
+ // SPA fallback (para Angular, React, Vue)
81
+ this.app.get(/^(?!__).+/, (req, res, next) => {
82
+ const indexPath = path.join(this.websiteDir, 'index.html');
83
+ if (fs.existsSync(indexPath)) {
84
+ res.sendFile(indexPath);
85
+ } else {
86
+ next();
87
+ }
88
+ });
89
+ }
90
+
91
+ // Página padrão (se não houver website nem proxy)
92
+ if (!this.instance.ProxyUrl) {
93
+ this.app.get('/', (req, res) => {
94
+ const html = this.getDefaultPage();
95
+ res.set('Content-Type', 'text/html; charset=utf-8').send(html);
96
+ });
97
+ }
98
+
99
+ // 404
100
+ this.app.use((req, res) => {
101
+ res.status(404).json({
102
+ error: 'Not Found',
103
+ instanceId: this.instance.InstanceId,
104
+ path: req.path
105
+ });
106
+ });
107
+ }
108
+
109
+ getDefaultPage() {
110
+ const proxyInfo = this.instance.ProxyUrl ? `
111
+ <div class="info-item proxy-item">
112
+ <div class="info-label">🔗 Proxy URL</div>
113
+ <div class="info-value">${this.instance.ProxyUrl}</div>
114
+ </div>
115
+ ` : '';
116
+
117
+ return `
118
+ <!DOCTYPE html>
119
+ <html lang="pt-BR">
120
+ <head>
121
+ <meta charset="UTF-8">
122
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
123
+ <title>EC2 Instance - ${this.instance.InstanceId}</title>
124
+ <style>
125
+ * {
126
+ margin: 0;
127
+ padding: 0;
128
+ box-sizing: border-box;
129
+ }
130
+ body {
131
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
132
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
133
+ min-height: 100vh;
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ padding: 20px;
138
+ }
139
+ .container {
140
+ background: white;
141
+ border-radius: 10px;
142
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
143
+ padding: 40px;
144
+ max-width: 600px;
145
+ width: 100%;
146
+ }
147
+ .header {
148
+ text-align: center;
149
+ margin-bottom: 30px;
150
+ border-bottom: 3px solid #667eea;
151
+ padding-bottom: 20px;
152
+ }
153
+ .header h1 {
154
+ color: #333;
155
+ font-size: 28px;
156
+ margin-bottom: 10px;
157
+ }
158
+ .status {
159
+ display: inline-block;
160
+ padding: 8px 16px;
161
+ border-radius: 20px;
162
+ font-weight: bold;
163
+ font-size: 14px;
164
+ ${this.instance.isRunning() ? 'background: #4caf50; color: white;' : 'background: #ff9800; color: white;'}
165
+ }
166
+ .info-grid {
167
+ display: grid;
168
+ grid-template-columns: 1fr 1fr;
169
+ gap: 20px;
170
+ margin-bottom: 20px;
171
+ }
172
+ .info-item {
173
+ background: #f5f5f5;
174
+ padding: 15px;
175
+ border-radius: 8px;
176
+ border-left: 4px solid #667eea;
177
+ }
178
+ .info-item.proxy-item {
179
+ grid-column: 1 / -1;
180
+ border-left-color: #2196f3;
181
+ background: #e3f2fd;
182
+ }
183
+ .info-label {
184
+ color: #666;
185
+ font-size: 12px;
186
+ font-weight: bold;
187
+ text-transform: uppercase;
188
+ margin-bottom: 5px;
189
+ }
190
+ .info-value {
191
+ color: #333;
192
+ font-size: 16px;
193
+ font-weight: 500;
194
+ word-break: break-all;
195
+ }
196
+ .metadata-link {
197
+ text-align: center;
198
+ margin-top: 20px;
199
+ padding-top: 20px;
200
+ border-top: 1px solid #eee;
201
+ }
202
+ .metadata-link a {
203
+ color: #667eea;
204
+ text-decoration: none;
205
+ font-size: 14px;
206
+ }
207
+ .metadata-link a:hover {
208
+ text-decoration: underline;
209
+ }
210
+ .footer {
211
+ text-align: center;
212
+ margin-top: 20px;
213
+ color: #999;
214
+ font-size: 12px;
215
+ }
216
+ </style>
217
+ </head>
218
+ <body>
219
+ <div class="container">
220
+ <div class="header">
221
+ <h1>🖥️ AWS EC2 Instance</h1>
222
+ <div class="status">${this.instance.State.toUpperCase()}</div>
223
+ </div>
224
+
225
+ <div class="info-grid">
226
+ <div class="info-item">
227
+ <div class="info-label">Instance ID</div>
228
+ <div class="info-value">${this.instance.InstanceId}</div>
229
+ </div>
230
+
231
+ <div class="info-item">
232
+ <div class="info-label">Instance Type</div>
233
+ <div class="info-value">${this.instance.InstanceType}</div>
234
+ </div>
235
+
236
+ <div class="info-item">
237
+ <div class="info-label">Public IP</div>
238
+ <div class="info-value">${this.instance.PublicIpAddress}</div>
239
+ </div>
240
+
241
+ <div class="info-item">
242
+ <div class="info-label">Private IP</div>
243
+ <div class="info-value">${this.instance.PrivateIpAddress}</div>
244
+ </div>
245
+
246
+ <div class="info-item">
247
+ <div class="info-label">VPC ID</div>
248
+ <div class="info-value">${this.instance.VpcId || 'N/A'}</div>
249
+ </div>
250
+
251
+ <div class="info-item">
252
+ <div class="info-label">Subnet ID</div>
253
+ <div class="info-value">${this.instance.SubnetId || 'N/A'}</div>
254
+ </div>
255
+
256
+ <div class="info-item">
257
+ <div class="info-label">Image ID</div>
258
+ <div class="info-value">${this.instance.ImageId}</div>
259
+ </div>
260
+
261
+ <div class="info-item">
262
+ <div class="info-label">Launch Time</div>
263
+ <div class="info-value">${new Date(this.instance.LaunchTime).toLocaleString('pt-BR')}</div>
264
+ </div>
265
+
266
+ ${proxyInfo}
267
+ </div>
268
+
269
+ <div class="metadata-link">
270
+ <p><a href="/__metadata">📊 Ver Metadados Completos</a></p>
271
+ </div>
272
+
273
+ <div class="footer">
274
+ <p>Simulador AWS Local | EC2 Instance</p>
275
+ </div>
276
+ </div>
277
+ </body>
278
+ </html>
279
+ `;
280
+ }
281
+
282
+ async start() {
283
+ return new Promise((resolve, reject) => {
284
+ try {
285
+ this.server = this.app.listen(this.instance.WebServerPort, 'localhost', () => {
286
+ logger.info(
287
+ `[EC2:${this.instance.InstanceId}] Servidor rodando em http://localhost:${this.instance.WebServerPort}`
288
+ );
289
+ resolve();
290
+ });
291
+
292
+ this.server.on('error', reject);
293
+ } catch (error) {
294
+ reject(error);
295
+ }
296
+ });
297
+ }
298
+
299
+ async stop() {
300
+ if (this.server) {
301
+ return new Promise((resolve) => {
302
+ this.server.close(() => {
303
+ logger.info(`[EC2:${this.instance.InstanceId}] Servidor parado`);
304
+ resolve();
305
+ });
306
+ });
307
+ }
308
+ }
309
+ }
310
+
311
+ module.exports = InstanceServer;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * AMI (Amazon Machine Image) Model
3
+ */
4
+
5
+ class AMI {
6
+ constructor(name, description = '', config = {}) {
7
+ this.ImageId = `ami-${Math.random().toString(36).substring(7)}`;
8
+ this.Name = name;
9
+ this.Description = description;
10
+ this.Architecture = config.Architecture || 'x86_64';
11
+ this.RootDeviceType = config.RootDeviceType || 'ebs';
12
+ this.VirtualizationType = config.VirtualizationType || 'hvm';
13
+ this.State = 'available';
14
+ this.CreatedAt = new Date().toISOString();
15
+ this.Public = config.Public !== false;
16
+ this.Owner = config.Owner || '123456789012';
17
+ this.SriovNetSupport = config.SriovNetSupport || false;
18
+ this.EnaSupport = config.EnaSupport || true;
19
+ }
20
+
21
+ toJSON() {
22
+ return {
23
+ ImageId: this.ImageId,
24
+ Name: this.Name,
25
+ Description: this.Description,
26
+ Architecture: this.Architecture,
27
+ RootDeviceType: this.RootDeviceType,
28
+ VirtualizationType: this.VirtualizationType,
29
+ State: this.State,
30
+ CreatedAt: this.CreatedAt,
31
+ Public: this.Public,
32
+ Owner: this.Owner,
33
+ SriovNetSupport: this.SriovNetSupport,
34
+ EnaSupport: this.EnaSupport
35
+ };
36
+ }
37
+ }
38
+
39
+ module.exports = AMI;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * EC2 Instance Model
3
+ */
4
+
5
+ const { v4: uuidv4 } = require('uuid');
6
+
7
+ class Instance {
8
+ constructor(imageId, instanceType = 't2.micro', config = {}) {
9
+ this.InstanceId = `i-${uuidv4().substring(0, 8)}`;
10
+ this.ImageId = imageId;
11
+ this.InstanceType = instanceType;
12
+ this.State = 'running'; // pending, running, stopping, stopped, shutting-down, terminated
13
+ this.StateTransitionReason = 'User initiated';
14
+ this.LaunchTime = new Date().toISOString();
15
+ this.PrivateIpAddress = config.PrivateIpAddress || this.generatePrivateIp();
16
+ this.PublicIpAddress = config.PublicIpAddress || this.generatePublicIp();
17
+ this.SubnetId = config.SubnetId || null;
18
+ this.VpcId = config.VpcId || null;
19
+ this.SecurityGroupIds = config.SecurityGroupIds || ['sg-default'];
20
+ this.KeyName = config.KeyName || null;
21
+ this.Tags = config.Tags || [];
22
+ this.Monitoring = config.Monitoring || { State: 'disabled' };
23
+ this.IamInstanceProfile = config.IamInstanceProfile || null;
24
+ this.EbsOptimized = config.EbsOptimized || false;
25
+ this.RootDeviceType = 'ebs';
26
+ this.Architecture = 'x86_64';
27
+ this.VirtualizationType = 'hvm';
28
+ this.Hypervisor = 'xen';
29
+ this.WebServerPort = config.WebServerPort || this.assignWebServerPort();
30
+ this.WebServerDir = config.WebServerDir || null;
31
+ this.ProxyUrl = config.ProxyUrl || null; // URL externa para proxy (ex: http://localhost:3000)
32
+ this.WebServer = null; // Será preenchido com a instância do servidor
33
+ this.CpuUtilization = 0;
34
+ this.MemoryUtilization = 0;
35
+ }
36
+
37
+ generatePrivateIp() {
38
+ return `10.0.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`;
39
+ }
40
+
41
+ generatePublicIp() {
42
+ return `54.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`;
43
+ }
44
+
45
+ assignWebServerPort() {
46
+ // Porta entre 8001 e 8999
47
+ return 8000 + Math.floor(Math.random() * 1000);
48
+ }
49
+
50
+ setState(state, reason = '') {
51
+ this.State = state;
52
+ this.StateTransitionReason = reason || this.StateTransitionReason;
53
+ }
54
+
55
+ isRunning() {
56
+ return this.State === 'running';
57
+ }
58
+
59
+ isStopped() {
60
+ return this.State === 'stopped';
61
+ }
62
+
63
+ isTerminated() {
64
+ return this.State === 'terminated';
65
+ }
66
+
67
+ toJSON() {
68
+ return {
69
+ InstanceId: this.InstanceId,
70
+ ImageId: this.ImageId,
71
+ InstanceType: this.InstanceType,
72
+ State: this.State,
73
+ StateTransitionReason: this.StateTransitionReason,
74
+ LaunchTime: this.LaunchTime,
75
+ PrivateIpAddress: this.PrivateIpAddress,
76
+ PublicIpAddress: this.PublicIpAddress,
77
+ SubnetId: this.SubnetId,
78
+ VpcId: this.VpcId,
79
+ SecurityGroupIds: this.SecurityGroupIds,
80
+ KeyName: this.KeyName,
81
+ Tags: this.Tags,
82
+ Monitoring: this.Monitoring,
83
+ IamInstanceProfile: this.IamInstanceProfile,
84
+ EbsOptimized: this.EbsOptimized,
85
+ RootDeviceType: this.RootDeviceType,
86
+ Architecture: this.Architecture,
87
+ VirtualizationType: this.VirtualizationType,
88
+ Hypervisor: this.Hypervisor,
89
+ WebServerPort: this.WebServerPort,
90
+ WebServerDir: this.WebServerDir,
91
+ ProxyUrl: this.ProxyUrl,
92
+ CpuUtilization: this.CpuUtilization,
93
+ MemoryUtilization: this.MemoryUtilization
94
+ };
95
+ }
96
+ }
97
+
98
+ module.exports = Instance;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Network Interface Model
3
+ */
4
+
5
+ const { v4: uuidv4 } = require('uuid');
6
+
7
+ class NetworkInterface {
8
+ constructor(subnetId, vpcId, config = {}) {
9
+ this.NetworkInterfaceId = `eni-${uuidv4().substring(0, 8)}`;
10
+ this.SubnetId = subnetId;
11
+ this.VpcId = vpcId;
12
+ this.Description = config.Description || '';
13
+ this.PrivateIpAddresses = config.PrivateIpAddresses || [
14
+ {
15
+ PrivateIpAddress: `10.0.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`,
16
+ Primary: true
17
+ }
18
+ ];
19
+ this.Groups = config.Groups || [];
20
+ this.MacAddress = this.generateMacAddress();
21
+ this.Status = 'available'; // available, associated, detaching, detached
22
+ this.Attachment = config.Attachment || null;
23
+ this.SourceDestCheck = true;
24
+ this.Tags = config.Tags || [];
25
+ this.CreatedAt = new Date().toISOString();
26
+ }
27
+
28
+ generateMacAddress() {
29
+ return '02:' + Array(5)
30
+ .fill(0)
31
+ .map(() => Math.floor(Math.random() * 255).toString(16).padStart(2, '0'))
32
+ .join(':');
33
+ }
34
+
35
+ attachToInstance(instanceId, deviceIndex = 0) {
36
+ this.Attachment = {
37
+ AttachmentId: `eni-attach-${uuidv4().substring(0, 8)}`,
38
+ InstanceId: instanceId,
39
+ DeviceIndex: deviceIndex,
40
+ Status: 'attached',
41
+ AttachTime: new Date().toISOString()
42
+ };
43
+ this.Status = 'associated';
44
+ }
45
+
46
+ detachFromInstance() {
47
+ if (this.Attachment) {
48
+ this.Attachment.Status = 'detaching';
49
+ setTimeout(() => {
50
+ this.Attachment = null;
51
+ this.Status = 'available';
52
+ }, 1000);
53
+ }
54
+ }
55
+
56
+ toJSON() {
57
+ return {
58
+ NetworkInterfaceId: this.NetworkInterfaceId,
59
+ SubnetId: this.SubnetId,
60
+ VpcId: this.VpcId,
61
+ Description: this.Description,
62
+ PrivateIpAddresses: this.PrivateIpAddresses,
63
+ Groups: this.Groups,
64
+ MacAddress: this.MacAddress,
65
+ Status: this.Status,
66
+ Attachment: this.Attachment,
67
+ SourceDestCheck: this.SourceDestCheck,
68
+ Tags: this.Tags,
69
+ CreatedAt: this.CreatedAt
70
+ };
71
+ }
72
+ }
73
+
74
+ module.exports = NetworkInterface;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Security Group Model
3
+ */
4
+
5
+ const { v4: uuidv4 } = require('uuid');
6
+
7
+ class SecurityGroup {
8
+ constructor(name, description = '', vpcId = null, config = {}) {
9
+ this.GroupId = `sg-${uuidv4().substring(0, 8)}`;
10
+ this.GroupName = name;
11
+ this.Description = description;
12
+ this.VpcId = vpcId;
13
+ this.OwnerId = '123456789012';
14
+ this.IpPermissions = [];
15
+ this.IpPermissionsEgress = [];
16
+ this.Tags = config.Tags || [];
17
+ this.CreatedAt = new Date().toISOString();
18
+
19
+ // Adicionar regra padrão de saída (allow all)
20
+ this.addEgressRule('0.0.0.0/0', null, -1, -1);
21
+ }
22
+
23
+ addIngressRule(cidr, securityGroupId, fromPort, toPort, protocol = 'tcp', description = '') {
24
+ const rule = {
25
+ IpProtocol: protocol,
26
+ FromPort: fromPort,
27
+ ToPort: toPort,
28
+ IpRanges: cidr ? [{ CidrIp: cidr, Description: description }] : [],
29
+ UserIdGroupPairs: securityGroupId ? [{ GroupId: securityGroupId }] : [],
30
+ CreatedAt: new Date().toISOString()
31
+ };
32
+ this.IpPermissions.push(rule);
33
+ return rule;
34
+ }
35
+
36
+ addEgressRule(cidr, securityGroupId, fromPort, toPort, protocol = 'tcp', description = '') {
37
+ const rule = {
38
+ IpProtocol: protocol,
39
+ FromPort: fromPort,
40
+ ToPort: toPort,
41
+ IpRanges: cidr ? [{ CidrIp: cidr, Description: description }] : [],
42
+ UserIdGroupPairs: securityGroupId ? [{ GroupId: securityGroupId }] : [],
43
+ CreatedAt: new Date().toISOString()
44
+ };
45
+ this.IpPermissionsEgress.push(rule);
46
+ return rule;
47
+ }
48
+
49
+ removeIngressRule(index) {
50
+ if (index >= 0 && index < this.IpPermissions.length) {
51
+ return this.IpPermissions.splice(index, 1)[0];
52
+ }
53
+ throw new Error(`Invalid rule index: ${index}`);
54
+ }
55
+
56
+ toJSON() {
57
+ return {
58
+ GroupId: this.GroupId,
59
+ GroupName: this.GroupName,
60
+ Description: this.Description,
61
+ VpcId: this.VpcId,
62
+ OwnerId: this.OwnerId,
63
+ IpPermissions: this.IpPermissions,
64
+ IpPermissionsEgress: this.IpPermissionsEgress,
65
+ Tags: this.Tags,
66
+ CreatedAt: this.CreatedAt
67
+ };
68
+ }
69
+ }
70
+
71
+ module.exports = SecurityGroup;