@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.
- package/README.md +662 -658
- package/package.json +10 -3
- package/src/config/default-config.js +71 -0
- package/src/config/env-loader.js +4 -2
- package/src/middleware/authorization.js +271 -0
- package/src/middleware/cloudtrail-logger.js +333 -0
- package/src/middleware/error-handler.js +138 -0
- package/src/middleware/index.js +79 -0
- package/src/middleware/policy-enforcement.js +407 -0
- package/src/server.js +74 -4
- package/src/services/acm/index.js +66 -0
- package/src/services/acm/models/certificate.js +202 -0
- package/src/services/acm/server.js +224 -0
- package/src/services/acm/simulator.js +293 -0
- package/src/services/alb/index.js +104 -0
- package/src/services/alb/models/loadBalancer.js +88 -0
- package/src/services/alb/models/targetGroup.js +128 -0
- package/src/services/alb/server.js +160 -0
- package/src/services/alb/simulator.js +262 -0
- package/src/services/apigateway/index.js +22 -0
- package/src/services/apigateway/server.js +247 -35
- package/src/services/apigateway/simulator.js +780 -26
- package/src/services/asg/index.js +100 -0
- package/src/services/asg/models/autoScalingGroup.js +110 -0
- package/src/services/asg/models/launchTemplate.js +41 -0
- package/src/services/asg/models/scalingPolicy.js +51 -0
- package/src/services/asg/server.js +236 -0
- package/src/services/asg/simulator.js +410 -0
- package/src/services/aurora/cluster-manager.js +731 -0
- package/src/services/aurora/data-api.js +514 -0
- package/src/services/aurora/db-engine.js +270 -0
- package/src/services/aurora/index.js +159 -0
- package/src/services/aurora/rds-api.js +189 -0
- package/src/services/aurora/server.js +213 -0
- package/src/services/aurora/sql-translator.js +334 -0
- package/src/services/cloudformation/index.js +2 -2
- package/src/services/cloudformation/server.js +1 -0
- package/src/services/cloudfront/cache-engine.js +225 -0
- package/src/services/cloudfront/geo-restrictions.js +377 -0
- package/src/services/cloudfront/index.js +220 -0
- package/src/services/cloudfront/models/behavior.js +158 -0
- package/src/services/cloudfront/models/distribution.js +284 -0
- package/src/services/cloudfront/models/index.js +99 -0
- package/src/services/cloudfront/models/invalidation.js +109 -0
- package/src/services/cloudfront/models/origin.js +155 -0
- package/src/services/cloudfront/origin-router.js +552 -0
- package/src/services/cloudfront/origin-validator.js +398 -0
- package/src/services/cloudfront/server.js +512 -0
- package/src/services/cloudfront/signed-url-generator.js +377 -0
- package/src/services/cloudfront/simulator.js +425 -0
- package/src/services/cloudfront/store.js +326 -0
- package/src/services/cloudshell/env-builder.js +27 -0
- package/src/services/cloudshell/index.js +48 -0
- package/src/services/cloudshell/routes.js +60 -0
- package/src/services/cloudshell/session-manager.js +226 -0
- package/src/services/cloudshell/static/.gitkeep +0 -0
- package/src/services/cloudshell/static/index.html +406 -0
- package/src/services/cloudshell/websocket-handler.js +107 -0
- package/src/services/cloudtrail/index.js +2 -3
- package/src/services/cloudtrail/server.js +68 -0
- package/src/services/cognito/server.js +4 -1
- package/src/services/dynamodb/server.js +4 -1
- package/src/services/dynamodb/simulator.js +2 -1
- package/src/services/ec2/index.js +101 -0
- package/src/services/ec2/instanceServer.js +311 -0
- package/src/services/ec2/models/ami.js +39 -0
- package/src/services/ec2/models/instance.js +98 -0
- package/src/services/ec2/models/networkInterface.js +74 -0
- package/src/services/ec2/models/securityGroup.js +71 -0
- package/src/services/ec2/server.js +350 -0
- package/src/services/ec2/simulator.js +436 -0
- package/src/services/eventbridge/server.js +36 -0
- package/src/services/eventbridge/simulator.js +230 -45
- package/src/services/iam/index.js +65 -0
- package/src/services/iam/middleware.js +99 -0
- package/src/services/iam/server.js +331 -0
- package/src/services/iam/simulator.js +1432 -0
- package/src/services/index.js +28 -0
- package/src/services/kinesis-analytics/index.js +105 -0
- package/src/services/kinesis-analytics/models/application.js +325 -0
- package/src/services/kinesis-analytics/models/index.js +12 -0
- package/src/services/kinesis-analytics/server.js +250 -0
- package/src/services/kinesis-analytics/simulator.js +407 -0
- package/src/services/kinesis-analytics/store.js +176 -0
- package/src/services/kinesis-data-streams/index.js +106 -0
- package/src/services/kinesis-data-streams/models/index.js +12 -0
- package/src/services/kinesis-data-streams/models/record.js +70 -0
- package/src/services/kinesis-data-streams/models/stream.js +280 -0
- package/src/services/kinesis-data-streams/server.js +255 -0
- package/src/services/kinesis-data-streams/simulator.js +514 -0
- package/src/services/kinesis-data-streams/store.js +163 -0
- package/src/services/kinesis-firehose/index.js +106 -0
- package/src/services/kinesis-firehose/models/delivery-stream.js +265 -0
- package/src/services/kinesis-firehose/models/index.js +10 -0
- package/src/services/kinesis-firehose/server.js +215 -0
- package/src/services/kinesis-firehose/simulator.js +388 -0
- package/src/services/kinesis-firehose/store.js +163 -0
- package/src/services/kms/server.js +4 -1
- package/src/services/lambda/index.js +26 -0
- package/src/services/lambda/server.js +12 -1
- package/src/services/lambda/simulator.js +4 -0
- package/src/services/opensearch/index.js +105 -0
- package/src/services/opensearch/models/document.js +115 -0
- package/src/services/opensearch/models/index.js +73 -0
- package/src/services/opensearch/server.js +310 -0
- package/src/services/opensearch/simulator.js +605 -0
- package/src/services/opensearch/store.js +162 -0
- package/src/services/organizations/control-tower-simulator.js +321 -0
- package/src/services/organizations/control-tower-store.js +182 -0
- package/src/services/organizations/iam-integration.js +413 -0
- package/src/services/organizations/index.js +172 -0
- package/src/services/organizations/models/index.js +13 -0
- package/src/services/organizations/models/invitation.js +48 -0
- package/src/services/organizations/models/organization.js +566 -0
- package/src/services/organizations/models/role.js +244 -0
- package/src/services/organizations/models/scp.js +131 -0
- package/src/services/organizations/server.js +736 -0
- package/src/services/organizations/simulator.js +593 -0
- package/src/services/organizations/store.js +235 -0
- package/src/services/organizations/vpc-integration.js +453 -0
- package/src/services/route53/index.js +67 -0
- package/src/services/route53/models/healthCheck.js +101 -0
- package/src/services/route53/models/hostedZone.js +37 -0
- package/src/services/route53/models/resourceRecord.js +106 -0
- package/src/services/route53/server.js +841 -0
- package/src/services/route53/simulator.js +350 -0
- package/src/services/s3/index.js +62 -0
- package/src/services/s3/presigned-url-generator.js +337 -0
- package/src/services/s3/server.js +231 -0
- package/src/services/s3/simulator.js +551 -4
- package/src/services/sns/index.js +31 -0
- package/src/services/sns/server.js +9 -0
- package/src/services/sqs/index.js +38 -0
- package/src/services/sqs/server.js +57 -4
- package/src/services/sqs/simulator.js +423 -33
- package/src/services/sts/simulator.js +209 -17
- package/src/services/vpc/README.md +459 -0
- package/src/services/vpc/ec2ResponseFormatter.js +431 -0
- package/src/services/vpc/index.js +90 -0
- package/src/services/vpc/models/internetGateway.js +71 -0
- package/src/services/vpc/models/routeTable.js +160 -0
- package/src/services/vpc/models/subnet.js +48 -0
- package/src/services/vpc/models/vpc.js +37 -0
- package/src/services/vpc/models/vpcEndpoint.js +100 -0
- package/src/services/vpc/models/vpcGateway.js +134 -0
- package/src/services/vpc/server.js +836 -0
- package/src/services/vpc/simulator.js +613 -0
- package/src/utils/policy-cache.js +215 -0
- package/aws-config +0 -154
|
@@ -2,61 +2,253 @@ const crypto = require('crypto');
|
|
|
2
2
|
const logger = require('../../utils/logger');
|
|
3
3
|
|
|
4
4
|
class STSSimulator {
|
|
5
|
-
constructor(config) {
|
|
5
|
+
constructor(config, organizationsService = null) {
|
|
6
6
|
this.config = config;
|
|
7
|
+
this.organizationsService = organizationsService;
|
|
7
8
|
this.assumedRoles = new Map();
|
|
9
|
+
this.sessions = new Map(); // Track active sessions
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
async initialize() {
|
|
11
13
|
logger.debug('Inicializando STS Simulator...');
|
|
12
14
|
}
|
|
13
15
|
|
|
16
|
+
/**
|
|
17
|
+
* AssumeRole - com integração a Organizations
|
|
18
|
+
* Retorna temporary credentials com SessionToken JWT
|
|
19
|
+
*/
|
|
14
20
|
assumeRole(params = {}) {
|
|
15
|
-
const { RoleArn, RoleSessionName, DurationSeconds = 3600 } = params;
|
|
21
|
+
const { RoleArn, RoleSessionName, DurationSeconds = 3600, ExternalId = null, SerialNumber = null, TokenCode = null } = params;
|
|
22
|
+
|
|
16
23
|
if (!RoleArn) throw new Error('RoleArn is required');
|
|
17
24
|
if (!RoleSessionName) throw new Error('RoleSessionName is required');
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
26
|
+
// Extrair accountId e roleName do ARN
|
|
27
|
+
// Format: arn:aws:iam::123456789012:role/role-name
|
|
28
|
+
const arnParts = RoleArn.match(/arn:aws:iam::(\d+):role\/(.+)/);
|
|
29
|
+
if (!arnParts) throw new Error('Invalid RoleArn format');
|
|
30
|
+
|
|
31
|
+
const [, accountId, roleName] = arnParts;
|
|
32
|
+
|
|
33
|
+
// Validar role existe na organização (se Organizations está disponível)
|
|
34
|
+
if (this.organizationsService?.organizationsSimulator?.roles) {
|
|
35
|
+
const roleExists = this.organizationsService.organizationsSimulator.roles.has(RoleArn);
|
|
36
|
+
if (!roleExists) {
|
|
37
|
+
throw new Error(`Role ${RoleArn} does not exist`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Gerar temporary credentials
|
|
42
|
+
const credentials = this.generateTemporaryCredentials(
|
|
43
|
+
accountId,
|
|
44
|
+
RoleArn,
|
|
45
|
+
RoleSessionName,
|
|
46
|
+
DurationSeconds
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Armazenar session para rastreamento
|
|
50
|
+
this.sessions.set(credentials.sessionId, {
|
|
51
|
+
roleArn: RoleArn,
|
|
52
|
+
sessionName: RoleSessionName,
|
|
53
|
+
createdAt: Date.now(),
|
|
54
|
+
expiresAt: credentials.expiresAtMs,
|
|
55
|
+
accountId,
|
|
56
|
+
accessKeyId: credentials.accessKeyId
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const expiration = new Date(credentials.expiresAtMs).toISOString();
|
|
23
60
|
const assumedRoleId = `AROA${crypto.randomBytes(8).toString('hex').toUpperCase()}:${RoleSessionName}`;
|
|
24
61
|
|
|
25
62
|
return {
|
|
26
|
-
Credentials: {
|
|
27
|
-
|
|
28
|
-
|
|
63
|
+
Credentials: {
|
|
64
|
+
AccessKeyId: credentials.accessKeyId,
|
|
65
|
+
SecretAccessKey: credentials.secretAccessKey,
|
|
66
|
+
SessionToken: credentials.sessionToken,
|
|
67
|
+
Expiration: expiration
|
|
68
|
+
},
|
|
69
|
+
AssumedRoleUser: {
|
|
70
|
+
AssumedRoleId: assumedRoleId,
|
|
71
|
+
Arn: `${RoleArn}/${RoleSessionName}`
|
|
72
|
+
},
|
|
73
|
+
PackedPolicySize: 6
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Gerar credentials temporárias com JWT SessionToken
|
|
79
|
+
* SessionToken contém informações do role para validação posterior
|
|
80
|
+
*/
|
|
81
|
+
generateTemporaryCredentials(accountId, roleArn, sessionName, durationSeconds) {
|
|
82
|
+
const now = Date.now();
|
|
83
|
+
const expiresAtMs = now + (durationSeconds * 1000);
|
|
84
|
+
|
|
85
|
+
// AccessKeyId com prefixo ASIA (indica temporary credentials)
|
|
86
|
+
const accessKeyId = `ASIA${crypto.randomBytes(8).toString('hex').toUpperCase()}`;
|
|
87
|
+
const secretAccessKey = crypto.randomBytes(20).toString('hex');
|
|
88
|
+
|
|
89
|
+
// Gerar JWT SessionToken com informações do role
|
|
90
|
+
const sessionId = crypto.randomBytes(16).toString('hex');
|
|
91
|
+
|
|
92
|
+
const payload = {
|
|
93
|
+
sessionId,
|
|
94
|
+
accountId,
|
|
95
|
+
assumedRole: roleArn,
|
|
96
|
+
sessionName,
|
|
97
|
+
principal: 'unknown',
|
|
98
|
+
issuedAt: now,
|
|
99
|
+
expiresAt: expiresAtMs,
|
|
100
|
+
accessKeyId,
|
|
101
|
+
secretAccessKey,
|
|
102
|
+
iss: 'aws-local-simulator-sts',
|
|
103
|
+
type: 'temporary-credentials'
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Criar JWT simples
|
|
107
|
+
const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
|
|
108
|
+
const payloadEncoded = Buffer.from(JSON.stringify(payload)).toString('base64url');
|
|
109
|
+
|
|
110
|
+
const signature = crypto
|
|
111
|
+
.createHmac('sha256', this.config.jwtSecret || 'local-simulator-secret')
|
|
112
|
+
.update(`${header}.${payloadEncoded}`)
|
|
113
|
+
.digest('base64url');
|
|
114
|
+
|
|
115
|
+
const sessionToken = `${header}.${payloadEncoded}.${signature}`;
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
sessionId,
|
|
119
|
+
accessKeyId,
|
|
120
|
+
secretAccessKey,
|
|
121
|
+
sessionToken,
|
|
122
|
+
expiresAtMs,
|
|
123
|
+
accountId,
|
|
124
|
+
roleArn
|
|
29
125
|
};
|
|
30
126
|
}
|
|
31
127
|
|
|
32
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Validar SessionToken JWT
|
|
130
|
+
*/
|
|
131
|
+
validateSessionToken(token) {
|
|
132
|
+
try {
|
|
133
|
+
const parts = token.split('.');
|
|
134
|
+
if (parts.length !== 3) return null;
|
|
135
|
+
|
|
136
|
+
const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));
|
|
137
|
+
|
|
138
|
+
if (payload.expiresAt < Date.now()) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return payload;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
logger.debug('SessionToken validation error:', error.message);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* GetCallerIdentity - Retorna informações do principal
|
|
151
|
+
*/
|
|
152
|
+
getCallerIdentity(params = {}, sessionToken = null) {
|
|
153
|
+
if (sessionToken) {
|
|
154
|
+
const payload = this.validateSessionToken(sessionToken);
|
|
155
|
+
if (payload) {
|
|
156
|
+
return {
|
|
157
|
+
UserId: payload.sessionId,
|
|
158
|
+
Account: payload.accountId,
|
|
159
|
+
Arn: payload.assumedRole,
|
|
160
|
+
SessionToken: sessionToken,
|
|
161
|
+
Type: 'AssumedRole'
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
33
166
|
return {
|
|
34
167
|
UserId: 'AKIAIOSFODNN7EXAMPLE',
|
|
35
168
|
Account: '123456789012',
|
|
36
|
-
Arn: 'arn:aws:iam::123456789012:user/local-simulator'
|
|
169
|
+
Arn: 'arn:aws:iam::123456789012:user/local-simulator',
|
|
170
|
+
Type: 'IAMUser'
|
|
37
171
|
};
|
|
38
172
|
}
|
|
39
173
|
|
|
174
|
+
/**
|
|
175
|
+
* GetSessionToken - Gera session token para MFA
|
|
176
|
+
*/
|
|
40
177
|
getSessionToken(params = {}) {
|
|
41
178
|
const { DurationSeconds = 3600 } = params;
|
|
179
|
+
|
|
180
|
+
const credentials = this.generateTemporaryCredentials(
|
|
181
|
+
'123456789012',
|
|
182
|
+
'arn:aws:iam::123456789012:root',
|
|
183
|
+
'mfa-session',
|
|
184
|
+
DurationSeconds
|
|
185
|
+
);
|
|
186
|
+
|
|
42
187
|
return {
|
|
43
188
|
Credentials: {
|
|
44
|
-
AccessKeyId:
|
|
45
|
-
SecretAccessKey:
|
|
46
|
-
SessionToken:
|
|
47
|
-
Expiration: new Date(
|
|
189
|
+
AccessKeyId: credentials.accessKeyId,
|
|
190
|
+
SecretAccessKey: credentials.secretAccessKey,
|
|
191
|
+
SessionToken: credentials.sessionToken,
|
|
192
|
+
Expiration: new Date(credentials.expiresAtMs).toISOString()
|
|
48
193
|
}
|
|
49
194
|
};
|
|
50
195
|
}
|
|
51
196
|
|
|
197
|
+
/**
|
|
198
|
+
* AssumeRoleWithWebIdentity
|
|
199
|
+
*/
|
|
52
200
|
assumeRoleWithWebIdentity(params = {}) {
|
|
53
|
-
return this.assumeRole({
|
|
201
|
+
return this.assumeRole({
|
|
202
|
+
...params,
|
|
203
|
+
RoleSessionName: params.RoleSessionName || 'web-identity-session'
|
|
204
|
+
});
|
|
54
205
|
}
|
|
55
206
|
|
|
207
|
+
/**
|
|
208
|
+
* AssumeRoleWithSAML
|
|
209
|
+
*/
|
|
56
210
|
assumeRoleWithSAML(params = {}) {
|
|
57
|
-
return this.assumeRole({
|
|
211
|
+
return this.assumeRole({
|
|
212
|
+
...params,
|
|
213
|
+
RoleSessionName: params.RoleSessionName || 'saml-session'
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* GetStats
|
|
219
|
+
*/
|
|
220
|
+
getStats() {
|
|
221
|
+
const now = Date.now();
|
|
222
|
+
let activeSessions = 0;
|
|
223
|
+
let expiredSessions = 0;
|
|
224
|
+
|
|
225
|
+
for (const session of this.sessions.values()) {
|
|
226
|
+
if (session.expiresAt > now) {
|
|
227
|
+
activeSessions++;
|
|
228
|
+
} else {
|
|
229
|
+
expiredSessions++;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
activeSessions,
|
|
235
|
+
expiredSessions,
|
|
236
|
+
totalSessions: this.sessions.size
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Reset
|
|
242
|
+
*/
|
|
243
|
+
async reset() {
|
|
244
|
+
this.assumedRoles.clear();
|
|
245
|
+
this.sessions.clear();
|
|
246
|
+
logger.debug('STS Simulator reset');
|
|
58
247
|
}
|
|
59
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Generate error response
|
|
251
|
+
*/
|
|
60
252
|
generateErrorResponse(code, message) {
|
|
61
253
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
62
254
|
<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
|