@stacksjs/ts-cloud-core 0.1.1
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/LICENSE.md +21 -0
- package/README.md +321 -0
- package/package.json +31 -0
- package/src/advanced-features.test.ts +465 -0
- package/src/aws/cloudformation.ts +421 -0
- package/src/aws/cloudfront.ts +158 -0
- package/src/aws/credentials.test.ts +132 -0
- package/src/aws/credentials.ts +545 -0
- package/src/aws/index.ts +87 -0
- package/src/aws/s3.test.ts +188 -0
- package/src/aws/s3.ts +1088 -0
- package/src/aws/signature.test.ts +670 -0
- package/src/aws/signature.ts +1155 -0
- package/src/backup/disaster-recovery.test.ts +726 -0
- package/src/backup/disaster-recovery.ts +500 -0
- package/src/backup/index.ts +34 -0
- package/src/backup/manager.test.ts +498 -0
- package/src/backup/manager.ts +432 -0
- package/src/cicd/circleci.ts +430 -0
- package/src/cicd/github-actions.ts +424 -0
- package/src/cicd/gitlab-ci.ts +255 -0
- package/src/cicd/index.ts +8 -0
- package/src/cli/history.ts +396 -0
- package/src/cli/index.ts +10 -0
- package/src/cli/progress.ts +458 -0
- package/src/cli/repl.ts +454 -0
- package/src/cli/suggestions.ts +327 -0
- package/src/cli/table.test.ts +319 -0
- package/src/cli/table.ts +332 -0
- package/src/cloudformation/builder.test.ts +327 -0
- package/src/cloudformation/builder.ts +378 -0
- package/src/cloudformation/builders/api-gateway.ts +449 -0
- package/src/cloudformation/builders/cache.ts +334 -0
- package/src/cloudformation/builders/cdn.ts +278 -0
- package/src/cloudformation/builders/compute.ts +485 -0
- package/src/cloudformation/builders/database.ts +392 -0
- package/src/cloudformation/builders/functions.ts +343 -0
- package/src/cloudformation/builders/messaging.ts +140 -0
- package/src/cloudformation/builders/monitoring.ts +300 -0
- package/src/cloudformation/builders/network.ts +264 -0
- package/src/cloudformation/builders/queue.ts +147 -0
- package/src/cloudformation/builders/security.ts +399 -0
- package/src/cloudformation/builders/storage.ts +285 -0
- package/src/cloudformation/index.ts +30 -0
- package/src/cloudformation/types.ts +173 -0
- package/src/compliance/aws-config.ts +543 -0
- package/src/compliance/cloudtrail.ts +376 -0
- package/src/compliance/compliance.test.ts +423 -0
- package/src/compliance/guardduty.ts +446 -0
- package/src/compliance/index.ts +66 -0
- package/src/compliance/security-hub.ts +456 -0
- package/src/containers/build-optimization.ts +416 -0
- package/src/containers/containers.test.ts +508 -0
- package/src/containers/image-scanning.ts +360 -0
- package/src/containers/index.ts +9 -0
- package/src/containers/registry.ts +293 -0
- package/src/containers/service-mesh.ts +520 -0
- package/src/database/database.test.ts +762 -0
- package/src/database/index.ts +9 -0
- package/src/database/migrations.ts +444 -0
- package/src/database/performance.ts +528 -0
- package/src/database/replicas.ts +534 -0
- package/src/database/users.ts +494 -0
- package/src/dependency-graph.ts +143 -0
- package/src/deployment/ab-testing.ts +582 -0
- package/src/deployment/blue-green.ts +452 -0
- package/src/deployment/canary.ts +500 -0
- package/src/deployment/deployment.test.ts +526 -0
- package/src/deployment/index.ts +61 -0
- package/src/deployment/progressive.ts +62 -0
- package/src/dns/dns.test.ts +641 -0
- package/src/dns/dnssec.ts +315 -0
- package/src/dns/index.ts +8 -0
- package/src/dns/resolver.ts +496 -0
- package/src/dns/routing.ts +593 -0
- package/src/email/advanced/analytics.ts +445 -0
- package/src/email/advanced/index.ts +11 -0
- package/src/email/advanced/rules.ts +465 -0
- package/src/email/advanced/scheduling.ts +352 -0
- package/src/email/advanced/search.ts +412 -0
- package/src/email/advanced/shared-mailboxes.ts +404 -0
- package/src/email/advanced/templates.ts +455 -0
- package/src/email/advanced/threading.ts +281 -0
- package/src/email/analytics.ts +467 -0
- package/src/email/bounce-handling.ts +425 -0
- package/src/email/email.test.ts +431 -0
- package/src/email/handlers/__tests__/inbound.test.ts +38 -0
- package/src/email/handlers/__tests__/outbound.test.ts +37 -0
- package/src/email/handlers/converter.ts +227 -0
- package/src/email/handlers/feedback.ts +228 -0
- package/src/email/handlers/inbound.ts +169 -0
- package/src/email/handlers/outbound.ts +178 -0
- package/src/email/index.ts +15 -0
- package/src/email/reputation.ts +303 -0
- package/src/email/templates.ts +352 -0
- package/src/errors/index.test.ts +434 -0
- package/src/errors/index.ts +416 -0
- package/src/health-checks/index.ts +40 -0
- package/src/index.ts +360 -0
- package/src/intrinsic-functions.ts +118 -0
- package/src/lambda/concurrency.ts +330 -0
- package/src/lambda/destinations.ts +345 -0
- package/src/lambda/dlq.ts +425 -0
- package/src/lambda/index.ts +11 -0
- package/src/lambda/lambda.test.ts +840 -0
- package/src/lambda/layers.ts +263 -0
- package/src/lambda/versions.ts +376 -0
- package/src/lambda/vpc.ts +399 -0
- package/src/local/config.ts +114 -0
- package/src/local/index.ts +6 -0
- package/src/local/mock-aws.ts +351 -0
- package/src/modules/ai.ts +340 -0
- package/src/modules/api.ts +478 -0
- package/src/modules/auth.ts +805 -0
- package/src/modules/cache.ts +417 -0
- package/src/modules/cdn.ts +1062 -0
- package/src/modules/communication.ts +1094 -0
- package/src/modules/compute.ts +3348 -0
- package/src/modules/database.ts +554 -0
- package/src/modules/deployment.ts +1079 -0
- package/src/modules/dns.ts +337 -0
- package/src/modules/email.ts +1538 -0
- package/src/modules/filesystem.ts +515 -0
- package/src/modules/index.ts +32 -0
- package/src/modules/messaging.ts +486 -0
- package/src/modules/monitoring.ts +2086 -0
- package/src/modules/network.ts +664 -0
- package/src/modules/parameter-store.ts +325 -0
- package/src/modules/permissions.ts +1081 -0
- package/src/modules/phone.ts +494 -0
- package/src/modules/queue.ts +1260 -0
- package/src/modules/redirects.ts +464 -0
- package/src/modules/registry.ts +699 -0
- package/src/modules/search.ts +401 -0
- package/src/modules/secrets.ts +416 -0
- package/src/modules/security.ts +731 -0
- package/src/modules/sms.ts +389 -0
- package/src/modules/storage.ts +1120 -0
- package/src/modules/workflow.ts +680 -0
- package/src/multi-account/config.ts +521 -0
- package/src/multi-account/index.ts +7 -0
- package/src/multi-account/manager.ts +427 -0
- package/src/multi-region/cross-region.ts +410 -0
- package/src/multi-region/index.ts +8 -0
- package/src/multi-region/manager.ts +483 -0
- package/src/multi-region/regions.ts +435 -0
- package/src/network-security/index.ts +48 -0
- package/src/observability/index.ts +9 -0
- package/src/observability/logs.ts +522 -0
- package/src/observability/metrics.ts +460 -0
- package/src/observability/observability.test.ts +782 -0
- package/src/observability/synthetics.ts +568 -0
- package/src/observability/xray.ts +358 -0
- package/src/phone/advanced/analytics.ts +349 -0
- package/src/phone/advanced/callbacks.ts +428 -0
- package/src/phone/advanced/index.ts +8 -0
- package/src/phone/advanced/ivr-builder.ts +504 -0
- package/src/phone/advanced/recording.ts +310 -0
- package/src/phone/handlers/__tests__/incoming-call.test.ts +40 -0
- package/src/phone/handlers/incoming-call.ts +117 -0
- package/src/phone/handlers/missed-call.ts +116 -0
- package/src/phone/handlers/voicemail.ts +179 -0
- package/src/phone/index.ts +9 -0
- package/src/presets/api-backend.ts +134 -0
- package/src/presets/data-pipeline.ts +204 -0
- package/src/presets/extend.test.ts +295 -0
- package/src/presets/extend.ts +297 -0
- package/src/presets/fullstack-app.ts +144 -0
- package/src/presets/index.ts +27 -0
- package/src/presets/jamstack.ts +135 -0
- package/src/presets/microservices.ts +167 -0
- package/src/presets/ml-api.ts +208 -0
- package/src/presets/nodejs-server.ts +104 -0
- package/src/presets/nodejs-serverless.ts +114 -0
- package/src/presets/realtime-app.ts +184 -0
- package/src/presets/static-site.ts +64 -0
- package/src/presets/traditional-web-app.ts +339 -0
- package/src/presets/wordpress.ts +138 -0
- package/src/preview/github.test.ts +249 -0
- package/src/preview/github.ts +297 -0
- package/src/preview/index.ts +37 -0
- package/src/preview/manager.test.ts +440 -0
- package/src/preview/manager.ts +326 -0
- package/src/preview/notifications.test.ts +582 -0
- package/src/preview/notifications.ts +341 -0
- package/src/queue/batch-processing.ts +402 -0
- package/src/queue/dlq-monitoring.ts +402 -0
- package/src/queue/fifo.ts +342 -0
- package/src/queue/index.ts +9 -0
- package/src/queue/management.ts +428 -0
- package/src/queue/queue.test.ts +429 -0
- package/src/resource-mgmt/index.ts +39 -0
- package/src/resource-naming.ts +62 -0
- package/src/s3/index.ts +523 -0
- package/src/schema/cloud-config.schema.json +554 -0
- package/src/schema/index.ts +68 -0
- package/src/security/certificate-manager.ts +492 -0
- package/src/security/index.ts +9 -0
- package/src/security/scanning.ts +545 -0
- package/src/security/secrets-manager.ts +476 -0
- package/src/security/secrets-rotation.ts +456 -0
- package/src/security/security.test.ts +738 -0
- package/src/sms/advanced/ab-testing.ts +389 -0
- package/src/sms/advanced/analytics.ts +336 -0
- package/src/sms/advanced/campaigns.ts +523 -0
- package/src/sms/advanced/chatbot.ts +224 -0
- package/src/sms/advanced/index.ts +10 -0
- package/src/sms/advanced/link-tracking.ts +248 -0
- package/src/sms/advanced/mms.ts +308 -0
- package/src/sms/handlers/__tests__/send.test.ts +40 -0
- package/src/sms/handlers/delivery-status.ts +133 -0
- package/src/sms/handlers/receive.ts +162 -0
- package/src/sms/handlers/send.ts +174 -0
- package/src/sms/index.ts +9 -0
- package/src/stack-diff.ts +389 -0
- package/src/static-site/index.ts +85 -0
- package/src/template-builder.ts +110 -0
- package/src/template-validator.ts +574 -0
- package/src/utils/cache.ts +291 -0
- package/src/utils/diff.ts +269 -0
- package/src/utils/hash.ts +227 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/parallel.ts +294 -0
- package/src/validators/credentials.test.ts +274 -0
- package/src/validators/credentials.ts +233 -0
- package/src/validators/quotas.test.ts +434 -0
- package/src/validators/quotas.ts +217 -0
- package/test/ai.test.ts +327 -0
- package/test/api.test.ts +511 -0
- package/test/auth.test.ts +632 -0
- package/test/cache.test.ts +406 -0
- package/test/cdn.test.ts +247 -0
- package/test/compute.test.ts +861 -0
- package/test/database.test.ts +523 -0
- package/test/deployment.test.ts +499 -0
- package/test/dns.test.ts +270 -0
- package/test/email.test.ts +439 -0
- package/test/filesystem.test.ts +382 -0
- package/test/integration.test.ts +350 -0
- package/test/messaging.test.ts +514 -0
- package/test/monitoring.test.ts +634 -0
- package/test/network.test.ts +425 -0
- package/test/permissions.test.ts +488 -0
- package/test/queue.test.ts +484 -0
- package/test/registry.test.ts +306 -0
- package/test/security.test.ts +462 -0
- package/test/storage.test.ts +463 -0
- package/test/template-validator.test.ts +559 -0
- package/test/workflow.test.ts +592 -0
- package/tsconfig.json +16 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Account Manager
|
|
3
|
+
* Manages deployments across multiple AWS accounts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface AWSAccount {
|
|
7
|
+
id: string
|
|
8
|
+
alias?: string
|
|
9
|
+
email: string
|
|
10
|
+
role: 'management' | 'production' | 'staging' | 'development' | 'security' | 'shared-services'
|
|
11
|
+
organizationalUnit?: string
|
|
12
|
+
assumeRoleArn?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface CrossAccountRole {
|
|
16
|
+
roleArn: string
|
|
17
|
+
roleName: string
|
|
18
|
+
sourceAccountId: string
|
|
19
|
+
targetAccountId: string
|
|
20
|
+
permissions: string[]
|
|
21
|
+
externalId?: string
|
|
22
|
+
sessionDuration?: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface AccountMapping {
|
|
26
|
+
environment: string
|
|
27
|
+
accountId: string
|
|
28
|
+
region: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Multi-account deployment manager
|
|
33
|
+
*/
|
|
34
|
+
export class MultiAccountManager {
|
|
35
|
+
private accounts: Map<string, AWSAccount> = new Map()
|
|
36
|
+
private crossAccountRoles: CrossAccountRole[] = []
|
|
37
|
+
private accountMappings: AccountMapping[] = []
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Register an AWS account
|
|
41
|
+
*/
|
|
42
|
+
registerAccount(account: AWSAccount): void {
|
|
43
|
+
this.accounts.set(account.id, account)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get account by ID
|
|
48
|
+
*/
|
|
49
|
+
getAccount(accountId: string): AWSAccount | undefined {
|
|
50
|
+
return this.accounts.get(accountId)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get account by alias
|
|
55
|
+
*/
|
|
56
|
+
getAccountByAlias(alias: string): AWSAccount | undefined {
|
|
57
|
+
return Array.from(this.accounts.values()).find(acc => acc.alias === alias)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* List all accounts
|
|
62
|
+
*/
|
|
63
|
+
listAccounts(): AWSAccount[] {
|
|
64
|
+
return Array.from(this.accounts.values())
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get accounts by role
|
|
69
|
+
*/
|
|
70
|
+
getAccountsByRole(role: AWSAccount['role']): AWSAccount[] {
|
|
71
|
+
return Array.from(this.accounts.values()).filter(acc => acc.role === role)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create cross-account role for deployment
|
|
76
|
+
*/
|
|
77
|
+
createCrossAccountRole(
|
|
78
|
+
sourceAccountId: string,
|
|
79
|
+
targetAccountId: string,
|
|
80
|
+
roleName: string,
|
|
81
|
+
permissions: string[],
|
|
82
|
+
options?: {
|
|
83
|
+
externalId?: string
|
|
84
|
+
sessionDuration?: number
|
|
85
|
+
},
|
|
86
|
+
): CrossAccountRole {
|
|
87
|
+
const role: CrossAccountRole = {
|
|
88
|
+
roleArn: `arn:aws:iam::${targetAccountId}:role/${roleName}`,
|
|
89
|
+
roleName,
|
|
90
|
+
sourceAccountId,
|
|
91
|
+
targetAccountId,
|
|
92
|
+
permissions,
|
|
93
|
+
externalId: options?.externalId,
|
|
94
|
+
sessionDuration: options?.sessionDuration || 3600,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.crossAccountRoles.push(role)
|
|
98
|
+
|
|
99
|
+
return role
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get assume role policy document
|
|
104
|
+
*/
|
|
105
|
+
getAssumeRolePolicyDocument(sourceAccountId: string, externalId?: string): any {
|
|
106
|
+
const policy: any = {
|
|
107
|
+
Version: '2012-10-17',
|
|
108
|
+
Statement: [
|
|
109
|
+
{
|
|
110
|
+
Effect: 'Allow',
|
|
111
|
+
Principal: {
|
|
112
|
+
AWS: `arn:aws:iam::${sourceAccountId}:root`,
|
|
113
|
+
},
|
|
114
|
+
Action: 'sts:AssumeRole',
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Add external ID condition for enhanced security
|
|
120
|
+
if (externalId) {
|
|
121
|
+
policy.Statement[0].Condition = {
|
|
122
|
+
StringEquals: {
|
|
123
|
+
'sts:ExternalId': externalId,
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return policy
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Generate IAM policy for cross-account access
|
|
133
|
+
*/
|
|
134
|
+
generateCrossAccountPolicy(permissions: string[]): any {
|
|
135
|
+
return {
|
|
136
|
+
Version: '2012-10-17',
|
|
137
|
+
Statement: [
|
|
138
|
+
{
|
|
139
|
+
Effect: 'Allow',
|
|
140
|
+
Action: permissions,
|
|
141
|
+
Resource: '*',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Map environment to account
|
|
149
|
+
*/
|
|
150
|
+
mapEnvironmentToAccount(
|
|
151
|
+
environment: string,
|
|
152
|
+
accountId: string,
|
|
153
|
+
region: string,
|
|
154
|
+
): void {
|
|
155
|
+
this.accountMappings.push({
|
|
156
|
+
environment,
|
|
157
|
+
accountId,
|
|
158
|
+
region,
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get account for environment
|
|
164
|
+
*/
|
|
165
|
+
getAccountForEnvironment(environment: string): AccountMapping | undefined {
|
|
166
|
+
return this.accountMappings.find(mapping => mapping.environment === environment)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Assume role in target account
|
|
171
|
+
*/
|
|
172
|
+
async assumeRole(
|
|
173
|
+
roleArn: string,
|
|
174
|
+
sessionName: string,
|
|
175
|
+
externalId?: string,
|
|
176
|
+
): Promise<{
|
|
177
|
+
accessKeyId: string
|
|
178
|
+
secretAccessKey: string
|
|
179
|
+
sessionToken: string
|
|
180
|
+
expiration: Date
|
|
181
|
+
}> {
|
|
182
|
+
// This would use AWS STS AssumeRole API
|
|
183
|
+
// Placeholder implementation
|
|
184
|
+
console.log(`Assuming role: ${roleArn} with session: ${sessionName}`)
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
|
|
188
|
+
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
|
|
189
|
+
sessionToken: 'token',
|
|
190
|
+
expiration: new Date(Date.now() + 3600000),
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Get credentials for account
|
|
196
|
+
*/
|
|
197
|
+
async getCredentialsForAccount(accountId: string): Promise<{
|
|
198
|
+
accessKeyId: string
|
|
199
|
+
secretAccessKey: string
|
|
200
|
+
sessionToken?: string
|
|
201
|
+
}> {
|
|
202
|
+
const account = this.accounts.get(accountId)
|
|
203
|
+
|
|
204
|
+
if (!account) {
|
|
205
|
+
throw new Error(`Account not found: ${accountId}`)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// If account has assume role ARN, assume the role
|
|
209
|
+
if (account.assumeRoleArn) {
|
|
210
|
+
const credentials = await this.assumeRole(
|
|
211
|
+
account.assumeRoleArn,
|
|
212
|
+
`ts-cloud-${Date.now()}`,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
accessKeyId: credentials.accessKeyId,
|
|
217
|
+
secretAccessKey: credentials.secretAccessKey,
|
|
218
|
+
sessionToken: credentials.sessionToken,
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Otherwise, return default credentials
|
|
223
|
+
// In real implementation, would fetch from environment/credentials file
|
|
224
|
+
throw new Error('No credentials available for account')
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* List cross-account roles
|
|
229
|
+
*/
|
|
230
|
+
listCrossAccountRoles(): CrossAccountRole[] {
|
|
231
|
+
return [...this.crossAccountRoles]
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get cross-account roles for account
|
|
236
|
+
*/
|
|
237
|
+
getCrossAccountRolesForAccount(accountId: string): CrossAccountRole[] {
|
|
238
|
+
return this.crossAccountRoles.filter(
|
|
239
|
+
role => role.sourceAccountId === accountId || role.targetAccountId === accountId,
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Validate account access
|
|
245
|
+
*/
|
|
246
|
+
async validateAccountAccess(accountId: string): Promise<boolean> {
|
|
247
|
+
try {
|
|
248
|
+
const credentials = await this.getCredentialsForAccount(accountId)
|
|
249
|
+
|
|
250
|
+
// Would use STS GetCallerIdentity to validate credentials
|
|
251
|
+
console.log(`Validating access to account: ${accountId}`)
|
|
252
|
+
|
|
253
|
+
return true
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return false
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Get consolidated billing summary
|
|
262
|
+
*/
|
|
263
|
+
async getConsolidatedBilling(): Promise<{
|
|
264
|
+
totalCost: number
|
|
265
|
+
byAccount: Record<string, number>
|
|
266
|
+
}> {
|
|
267
|
+
// Would use AWS Cost Explorer API
|
|
268
|
+
// Placeholder implementation
|
|
269
|
+
const byAccount: Record<string, number> = {}
|
|
270
|
+
|
|
271
|
+
for (const account of this.accounts.values()) {
|
|
272
|
+
byAccount[account.id] = Math.random() * 1000 // Placeholder cost
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const totalCost = Object.values(byAccount).reduce((sum, cost) => sum + cost, 0)
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
totalCost,
|
|
279
|
+
byAccount,
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Clear all data
|
|
285
|
+
*/
|
|
286
|
+
clear(): void {
|
|
287
|
+
this.accounts.clear()
|
|
288
|
+
this.crossAccountRoles = []
|
|
289
|
+
this.accountMappings = []
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* AWS Organizations helper
|
|
295
|
+
*/
|
|
296
|
+
export class OrganizationManager {
|
|
297
|
+
private organizationId?: string
|
|
298
|
+
private organizationalUnits: Map<string, OrganizationalUnit> = new Map()
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Get organization ID
|
|
302
|
+
*/
|
|
303
|
+
getOrganizationId(): string | undefined {
|
|
304
|
+
return this.organizationId
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Set organization ID
|
|
309
|
+
*/
|
|
310
|
+
setOrganizationId(id: string): void {
|
|
311
|
+
this.organizationId = id
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Create organizational unit
|
|
316
|
+
*/
|
|
317
|
+
createOrganizationalUnit(name: string, parentId?: string): OrganizationalUnit {
|
|
318
|
+
const ou: OrganizationalUnit = {
|
|
319
|
+
id: `ou-${Date.now()}`,
|
|
320
|
+
name,
|
|
321
|
+
parentId,
|
|
322
|
+
accounts: [],
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
this.organizationalUnits.set(ou.id, ou)
|
|
326
|
+
|
|
327
|
+
return ou
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Get organizational unit
|
|
332
|
+
*/
|
|
333
|
+
getOrganizationalUnit(id: string): OrganizationalUnit | undefined {
|
|
334
|
+
return this.organizationalUnits.get(id)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* List organizational units
|
|
339
|
+
*/
|
|
340
|
+
listOrganizationalUnits(): OrganizationalUnit[] {
|
|
341
|
+
return Array.from(this.organizationalUnits.values())
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Add account to organizational unit
|
|
346
|
+
*/
|
|
347
|
+
addAccountToOU(ouId: string, accountId: string): void {
|
|
348
|
+
const ou = this.organizationalUnits.get(ouId)
|
|
349
|
+
|
|
350
|
+
if (!ou) {
|
|
351
|
+
throw new Error(`Organizational unit not found: ${ouId}`)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (!ou.accounts.includes(accountId)) {
|
|
355
|
+
ou.accounts.push(accountId)
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Remove account from organizational unit
|
|
361
|
+
*/
|
|
362
|
+
removeAccountFromOU(ouId: string, accountId: string): void {
|
|
363
|
+
const ou = this.organizationalUnits.get(ouId)
|
|
364
|
+
|
|
365
|
+
if (!ou) {
|
|
366
|
+
throw new Error(`Organizational unit not found: ${ouId}`)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
ou.accounts = ou.accounts.filter(id => id !== accountId)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Get accounts in organizational unit
|
|
374
|
+
*/
|
|
375
|
+
getAccountsInOU(ouId: string): string[] {
|
|
376
|
+
const ou = this.organizationalUnits.get(ouId)
|
|
377
|
+
|
|
378
|
+
if (!ou) {
|
|
379
|
+
return []
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return [...ou.accounts]
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Apply service control policy
|
|
387
|
+
*/
|
|
388
|
+
applyServiceControlPolicy(
|
|
389
|
+
targetId: string,
|
|
390
|
+
policyDocument: any,
|
|
391
|
+
): ServiceControlPolicy {
|
|
392
|
+
return {
|
|
393
|
+
id: `scp-${Date.now()}`,
|
|
394
|
+
name: 'Custom SCP',
|
|
395
|
+
targetId,
|
|
396
|
+
policyDocument,
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Clear all data
|
|
402
|
+
*/
|
|
403
|
+
clear(): void {
|
|
404
|
+
this.organizationId = undefined
|
|
405
|
+
this.organizationalUnits.clear()
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface OrganizationalUnit {
|
|
410
|
+
id: string
|
|
411
|
+
name: string
|
|
412
|
+
parentId?: string
|
|
413
|
+
accounts: string[]
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export interface ServiceControlPolicy {
|
|
417
|
+
id: string
|
|
418
|
+
name: string
|
|
419
|
+
targetId: string
|
|
420
|
+
policyDocument: any
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Global instances
|
|
425
|
+
*/
|
|
426
|
+
export const multiAccountManager: MultiAccountManager = new MultiAccountManager()
|
|
427
|
+
export const organizationManager: OrganizationManager = new OrganizationManager()
|