@stacksjs/ts-cloud-core 0.1.3 → 0.1.6

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 (250) hide show
  1. package/README.md +98 -13
  2. package/package.json +12 -3
  3. package/src/advanced-features.test.ts +0 -465
  4. package/src/aws/cloudformation.ts +0 -421
  5. package/src/aws/cloudfront.ts +0 -158
  6. package/src/aws/credentials.test.ts +0 -132
  7. package/src/aws/credentials.ts +0 -545
  8. package/src/aws/index.ts +0 -87
  9. package/src/aws/s3.test.ts +0 -188
  10. package/src/aws/s3.ts +0 -1088
  11. package/src/aws/signature.test.ts +0 -670
  12. package/src/aws/signature.ts +0 -1155
  13. package/src/backup/disaster-recovery.test.ts +0 -726
  14. package/src/backup/disaster-recovery.ts +0 -500
  15. package/src/backup/index.ts +0 -34
  16. package/src/backup/manager.test.ts +0 -498
  17. package/src/backup/manager.ts +0 -432
  18. package/src/cicd/circleci.ts +0 -430
  19. package/src/cicd/github-actions.ts +0 -424
  20. package/src/cicd/gitlab-ci.ts +0 -255
  21. package/src/cicd/index.ts +0 -8
  22. package/src/cli/history.ts +0 -396
  23. package/src/cli/index.ts +0 -10
  24. package/src/cli/progress.ts +0 -458
  25. package/src/cli/repl.ts +0 -454
  26. package/src/cli/suggestions.ts +0 -327
  27. package/src/cli/table.test.ts +0 -319
  28. package/src/cli/table.ts +0 -332
  29. package/src/cloudformation/builder.test.ts +0 -327
  30. package/src/cloudformation/builder.ts +0 -378
  31. package/src/cloudformation/builders/api-gateway.ts +0 -449
  32. package/src/cloudformation/builders/cache.ts +0 -334
  33. package/src/cloudformation/builders/cdn.ts +0 -278
  34. package/src/cloudformation/builders/compute.ts +0 -485
  35. package/src/cloudformation/builders/database.ts +0 -392
  36. package/src/cloudformation/builders/functions.ts +0 -343
  37. package/src/cloudformation/builders/messaging.ts +0 -140
  38. package/src/cloudformation/builders/monitoring.ts +0 -300
  39. package/src/cloudformation/builders/network.ts +0 -264
  40. package/src/cloudformation/builders/queue.ts +0 -147
  41. package/src/cloudformation/builders/security.ts +0 -399
  42. package/src/cloudformation/builders/storage.ts +0 -285
  43. package/src/cloudformation/index.ts +0 -30
  44. package/src/cloudformation/types.ts +0 -173
  45. package/src/compliance/aws-config.ts +0 -543
  46. package/src/compliance/cloudtrail.ts +0 -376
  47. package/src/compliance/compliance.test.ts +0 -423
  48. package/src/compliance/guardduty.ts +0 -446
  49. package/src/compliance/index.ts +0 -66
  50. package/src/compliance/security-hub.ts +0 -456
  51. package/src/containers/build-optimization.ts +0 -416
  52. package/src/containers/containers.test.ts +0 -508
  53. package/src/containers/image-scanning.ts +0 -360
  54. package/src/containers/index.ts +0 -9
  55. package/src/containers/registry.ts +0 -293
  56. package/src/containers/service-mesh.ts +0 -520
  57. package/src/database/database.test.ts +0 -762
  58. package/src/database/index.ts +0 -9
  59. package/src/database/migrations.ts +0 -444
  60. package/src/database/performance.ts +0 -528
  61. package/src/database/replicas.ts +0 -534
  62. package/src/database/users.ts +0 -494
  63. package/src/dependency-graph.ts +0 -143
  64. package/src/deployment/ab-testing.ts +0 -582
  65. package/src/deployment/blue-green.ts +0 -452
  66. package/src/deployment/canary.ts +0 -500
  67. package/src/deployment/deployment.test.ts +0 -526
  68. package/src/deployment/index.ts +0 -61
  69. package/src/deployment/progressive.ts +0 -62
  70. package/src/dns/dns.test.ts +0 -641
  71. package/src/dns/dnssec.ts +0 -315
  72. package/src/dns/index.ts +0 -8
  73. package/src/dns/resolver.ts +0 -496
  74. package/src/dns/routing.ts +0 -593
  75. package/src/email/advanced/analytics.ts +0 -445
  76. package/src/email/advanced/index.ts +0 -11
  77. package/src/email/advanced/rules.ts +0 -465
  78. package/src/email/advanced/scheduling.ts +0 -352
  79. package/src/email/advanced/search.ts +0 -412
  80. package/src/email/advanced/shared-mailboxes.ts +0 -404
  81. package/src/email/advanced/templates.ts +0 -455
  82. package/src/email/advanced/threading.ts +0 -281
  83. package/src/email/analytics.ts +0 -467
  84. package/src/email/bounce-handling.ts +0 -425
  85. package/src/email/email.test.ts +0 -431
  86. package/src/email/handlers/__tests__/inbound.test.ts +0 -38
  87. package/src/email/handlers/__tests__/outbound.test.ts +0 -37
  88. package/src/email/handlers/converter.ts +0 -227
  89. package/src/email/handlers/feedback.ts +0 -228
  90. package/src/email/handlers/inbound.ts +0 -169
  91. package/src/email/handlers/outbound.ts +0 -178
  92. package/src/email/index.ts +0 -15
  93. package/src/email/reputation.ts +0 -303
  94. package/src/email/templates.ts +0 -352
  95. package/src/errors/index.test.ts +0 -434
  96. package/src/errors/index.ts +0 -416
  97. package/src/health-checks/index.ts +0 -40
  98. package/src/index.ts +0 -360
  99. package/src/intrinsic-functions.ts +0 -118
  100. package/src/lambda/concurrency.ts +0 -330
  101. package/src/lambda/destinations.ts +0 -345
  102. package/src/lambda/dlq.ts +0 -425
  103. package/src/lambda/index.ts +0 -11
  104. package/src/lambda/lambda.test.ts +0 -840
  105. package/src/lambda/layers.ts +0 -263
  106. package/src/lambda/versions.ts +0 -376
  107. package/src/lambda/vpc.ts +0 -399
  108. package/src/local/config.ts +0 -114
  109. package/src/local/index.ts +0 -6
  110. package/src/local/mock-aws.ts +0 -351
  111. package/src/modules/ai.ts +0 -340
  112. package/src/modules/api.ts +0 -478
  113. package/src/modules/auth.ts +0 -805
  114. package/src/modules/cache.ts +0 -417
  115. package/src/modules/cdn.ts +0 -1062
  116. package/src/modules/communication.ts +0 -1094
  117. package/src/modules/compute.ts +0 -3348
  118. package/src/modules/database.ts +0 -554
  119. package/src/modules/deployment.ts +0 -1079
  120. package/src/modules/dns.ts +0 -337
  121. package/src/modules/email.ts +0 -1538
  122. package/src/modules/filesystem.ts +0 -515
  123. package/src/modules/index.ts +0 -32
  124. package/src/modules/messaging.ts +0 -486
  125. package/src/modules/monitoring.ts +0 -2086
  126. package/src/modules/network.ts +0 -664
  127. package/src/modules/parameter-store.ts +0 -325
  128. package/src/modules/permissions.ts +0 -1081
  129. package/src/modules/phone.ts +0 -494
  130. package/src/modules/queue.ts +0 -1260
  131. package/src/modules/redirects.ts +0 -464
  132. package/src/modules/registry.ts +0 -699
  133. package/src/modules/search.ts +0 -401
  134. package/src/modules/secrets.ts +0 -416
  135. package/src/modules/security.ts +0 -731
  136. package/src/modules/sms.ts +0 -389
  137. package/src/modules/storage.ts +0 -1120
  138. package/src/modules/workflow.ts +0 -680
  139. package/src/multi-account/config.ts +0 -521
  140. package/src/multi-account/index.ts +0 -7
  141. package/src/multi-account/manager.ts +0 -427
  142. package/src/multi-region/cross-region.ts +0 -410
  143. package/src/multi-region/index.ts +0 -8
  144. package/src/multi-region/manager.ts +0 -483
  145. package/src/multi-region/regions.ts +0 -435
  146. package/src/network-security/index.ts +0 -48
  147. package/src/observability/index.ts +0 -9
  148. package/src/observability/logs.ts +0 -522
  149. package/src/observability/metrics.ts +0 -460
  150. package/src/observability/observability.test.ts +0 -782
  151. package/src/observability/synthetics.ts +0 -568
  152. package/src/observability/xray.ts +0 -358
  153. package/src/phone/advanced/analytics.ts +0 -349
  154. package/src/phone/advanced/callbacks.ts +0 -428
  155. package/src/phone/advanced/index.ts +0 -8
  156. package/src/phone/advanced/ivr-builder.ts +0 -504
  157. package/src/phone/advanced/recording.ts +0 -310
  158. package/src/phone/handlers/__tests__/incoming-call.test.ts +0 -40
  159. package/src/phone/handlers/incoming-call.ts +0 -117
  160. package/src/phone/handlers/missed-call.ts +0 -116
  161. package/src/phone/handlers/voicemail.ts +0 -179
  162. package/src/phone/index.ts +0 -9
  163. package/src/presets/api-backend.ts +0 -134
  164. package/src/presets/data-pipeline.ts +0 -204
  165. package/src/presets/extend.test.ts +0 -295
  166. package/src/presets/extend.ts +0 -297
  167. package/src/presets/fullstack-app.ts +0 -144
  168. package/src/presets/index.ts +0 -27
  169. package/src/presets/jamstack.ts +0 -135
  170. package/src/presets/microservices.ts +0 -167
  171. package/src/presets/ml-api.ts +0 -208
  172. package/src/presets/nodejs-server.ts +0 -104
  173. package/src/presets/nodejs-serverless.ts +0 -114
  174. package/src/presets/realtime-app.ts +0 -184
  175. package/src/presets/static-site.ts +0 -64
  176. package/src/presets/traditional-web-app.ts +0 -339
  177. package/src/presets/wordpress.ts +0 -138
  178. package/src/preview/github.test.ts +0 -249
  179. package/src/preview/github.ts +0 -297
  180. package/src/preview/index.ts +0 -37
  181. package/src/preview/manager.test.ts +0 -440
  182. package/src/preview/manager.ts +0 -326
  183. package/src/preview/notifications.test.ts +0 -582
  184. package/src/preview/notifications.ts +0 -341
  185. package/src/queue/batch-processing.ts +0 -402
  186. package/src/queue/dlq-monitoring.ts +0 -402
  187. package/src/queue/fifo.ts +0 -342
  188. package/src/queue/index.ts +0 -9
  189. package/src/queue/management.ts +0 -428
  190. package/src/queue/queue.test.ts +0 -429
  191. package/src/resource-mgmt/index.ts +0 -39
  192. package/src/resource-naming.ts +0 -62
  193. package/src/s3/index.ts +0 -523
  194. package/src/schema/cloud-config.schema.json +0 -554
  195. package/src/schema/index.ts +0 -68
  196. package/src/security/certificate-manager.ts +0 -492
  197. package/src/security/index.ts +0 -9
  198. package/src/security/scanning.ts +0 -545
  199. package/src/security/secrets-manager.ts +0 -476
  200. package/src/security/secrets-rotation.ts +0 -456
  201. package/src/security/security.test.ts +0 -738
  202. package/src/sms/advanced/ab-testing.ts +0 -389
  203. package/src/sms/advanced/analytics.ts +0 -336
  204. package/src/sms/advanced/campaigns.ts +0 -523
  205. package/src/sms/advanced/chatbot.ts +0 -224
  206. package/src/sms/advanced/index.ts +0 -10
  207. package/src/sms/advanced/link-tracking.ts +0 -248
  208. package/src/sms/advanced/mms.ts +0 -308
  209. package/src/sms/handlers/__tests__/send.test.ts +0 -40
  210. package/src/sms/handlers/delivery-status.ts +0 -133
  211. package/src/sms/handlers/receive.ts +0 -162
  212. package/src/sms/handlers/send.ts +0 -174
  213. package/src/sms/index.ts +0 -9
  214. package/src/stack-diff.ts +0 -389
  215. package/src/static-site/index.ts +0 -85
  216. package/src/template-builder.ts +0 -110
  217. package/src/template-validator.ts +0 -574
  218. package/src/utils/cache.ts +0 -291
  219. package/src/utils/diff.ts +0 -269
  220. package/src/utils/hash.ts +0 -227
  221. package/src/utils/index.ts +0 -8
  222. package/src/utils/parallel.ts +0 -294
  223. package/src/validators/credentials.test.ts +0 -274
  224. package/src/validators/credentials.ts +0 -233
  225. package/src/validators/quotas.test.ts +0 -434
  226. package/src/validators/quotas.ts +0 -217
  227. package/test/ai.test.ts +0 -327
  228. package/test/api.test.ts +0 -511
  229. package/test/auth.test.ts +0 -632
  230. package/test/cache.test.ts +0 -406
  231. package/test/cdn.test.ts +0 -247
  232. package/test/compute.test.ts +0 -861
  233. package/test/database.test.ts +0 -523
  234. package/test/deployment.test.ts +0 -499
  235. package/test/dns.test.ts +0 -270
  236. package/test/email.test.ts +0 -439
  237. package/test/filesystem.test.ts +0 -382
  238. package/test/integration.test.ts +0 -350
  239. package/test/messaging.test.ts +0 -514
  240. package/test/monitoring.test.ts +0 -634
  241. package/test/network.test.ts +0 -425
  242. package/test/permissions.test.ts +0 -488
  243. package/test/queue.test.ts +0 -484
  244. package/test/registry.test.ts +0 -306
  245. package/test/security.test.ts +0 -462
  246. package/test/storage.test.ts +0 -463
  247. package/test/template-validator.test.ts +0 -559
  248. package/test/workflow.test.ts +0 -592
  249. package/tsconfig.json +0 -16
  250. package/tsconfig.tsbuildinfo +0 -1
@@ -1,1081 +0,0 @@
1
- import type {
2
- IAMAccessKey,
3
- IAMGroup,
4
- IAMInstanceProfile,
5
- IAMManagedPolicy,
6
- IAMRole,
7
- IAMUser,
8
- } from '@stacksjs/ts-cloud-aws-types'
9
- import type { EnvironmentType } from '@stacksjs/ts-cloud-types'
10
- import { Fn } from '../intrinsic-functions'
11
- import { generateLogicalId, generateResourceName } from '../resource-naming'
12
-
13
- export interface PolicyStatement {
14
- sid?: string
15
- effect?: 'Allow' | 'Deny'
16
- actions: string | string[]
17
- resources: string | string[]
18
- conditions?: Record<string, unknown>
19
- }
20
-
21
- export interface UserOptions {
22
- slug: string
23
- environment: EnvironmentType
24
- userName?: string
25
- groups?: string[]
26
- managedPolicyArns?: string[]
27
- }
28
-
29
- export interface RoleOptions {
30
- slug: string
31
- environment: EnvironmentType
32
- roleName?: string
33
- servicePrincipal?: string | string[]
34
- awsPrincipal?: string | string[]
35
- managedPolicyArns?: string[]
36
- }
37
-
38
- export interface GroupOptions {
39
- slug: string
40
- environment: EnvironmentType
41
- groupName?: string
42
- managedPolicyArns?: string[]
43
- }
44
-
45
- export interface ManagedPolicyOptions {
46
- slug: string
47
- environment: EnvironmentType
48
- policyName?: string
49
- description?: string
50
- statements: PolicyStatement[]
51
- }
52
-
53
- /**
54
- * Permissions Module - IAM (Identity and Access Management)
55
- * Provides clean API for creating users, roles, policies, and groups
56
- */
57
- export class Permissions {
58
- /**
59
- * Create an IAM user
60
- */
61
- static createUser(options: UserOptions): {
62
- user: IAMUser
63
- logicalId: string
64
- } {
65
- const {
66
- slug,
67
- environment,
68
- userName,
69
- groups,
70
- managedPolicyArns,
71
- } = options
72
-
73
- const resourceName = userName || generateResourceName({
74
- slug,
75
- environment,
76
- resourceType: 'user',
77
- })
78
-
79
- const logicalId = generateLogicalId(resourceName)
80
-
81
- const user: IAMUser = {
82
- Type: 'AWS::IAM::User',
83
- Properties: {
84
- UserName: resourceName,
85
- Tags: [
86
- { Key: 'Name', Value: resourceName },
87
- { Key: 'Environment', Value: environment },
88
- ],
89
- },
90
- }
91
-
92
- if (groups && groups.length > 0) {
93
- user.Properties.Groups = groups
94
- }
95
-
96
- if (managedPolicyArns && managedPolicyArns.length > 0) {
97
- user.Properties.ManagedPolicyArns = managedPolicyArns
98
- }
99
-
100
- return { user, logicalId }
101
- }
102
-
103
- /**
104
- * Create an IAM role
105
- */
106
- static createRole(options: RoleOptions): {
107
- role: IAMRole
108
- logicalId: string
109
- } {
110
- const {
111
- slug,
112
- environment,
113
- roleName,
114
- servicePrincipal,
115
- awsPrincipal,
116
- managedPolicyArns,
117
- } = options
118
-
119
- const resourceName = roleName || generateResourceName({
120
- slug,
121
- environment,
122
- resourceType: 'role',
123
- })
124
-
125
- const logicalId = generateLogicalId(resourceName)
126
-
127
- const principal: IAMRole['Properties']['AssumeRolePolicyDocument']['Statement'][0]['Principal'] = {}
128
-
129
- if (servicePrincipal) {
130
- principal.Service = servicePrincipal
131
- }
132
-
133
- if (awsPrincipal) {
134
- principal.AWS = awsPrincipal
135
- }
136
-
137
- const role: IAMRole = {
138
- Type: 'AWS::IAM::Role',
139
- Properties: {
140
- RoleName: resourceName,
141
- AssumeRolePolicyDocument: {
142
- Version: '2012-10-17',
143
- Statement: [
144
- {
145
- Effect: 'Allow',
146
- Principal: principal,
147
- Action: 'sts:AssumeRole',
148
- },
149
- ],
150
- },
151
- Tags: [
152
- { Key: 'Name', Value: resourceName },
153
- { Key: 'Environment', Value: environment },
154
- ],
155
- },
156
- }
157
-
158
- if (managedPolicyArns && managedPolicyArns.length > 0) {
159
- role.Properties.ManagedPolicyArns = managedPolicyArns
160
- }
161
-
162
- return { role, logicalId }
163
- }
164
-
165
- /**
166
- * Create an IAM group
167
- */
168
- static createGroup(options: GroupOptions): {
169
- group: IAMGroup
170
- logicalId: string
171
- } {
172
- const {
173
- slug,
174
- environment,
175
- groupName,
176
- managedPolicyArns,
177
- } = options
178
-
179
- const resourceName = groupName || generateResourceName({
180
- slug,
181
- environment,
182
- resourceType: 'group',
183
- })
184
-
185
- const logicalId = generateLogicalId(resourceName)
186
-
187
- const group: IAMGroup = {
188
- Type: 'AWS::IAM::Group',
189
- Properties: {
190
- GroupName: resourceName,
191
- },
192
- }
193
-
194
- if (managedPolicyArns && managedPolicyArns.length > 0) {
195
- group.Properties.ManagedPolicyArns = managedPolicyArns
196
- }
197
-
198
- return { group, logicalId }
199
- }
200
-
201
- /**
202
- * Create a managed policy
203
- */
204
- static createPolicy(options: ManagedPolicyOptions): {
205
- policy: IAMManagedPolicy
206
- logicalId: string
207
- } {
208
- const {
209
- slug,
210
- environment,
211
- policyName,
212
- description,
213
- statements,
214
- } = options
215
-
216
- const resourceName = policyName || generateResourceName({
217
- slug,
218
- environment,
219
- resourceType: 'policy',
220
- })
221
-
222
- const logicalId = generateLogicalId(resourceName)
223
-
224
- const policyStatements = statements.map(stmt => ({
225
- Sid: stmt.sid,
226
- Effect: stmt.effect || 'Allow',
227
- Action: stmt.actions,
228
- Resource: stmt.resources,
229
- Condition: stmt.conditions,
230
- }))
231
-
232
- const policy: IAMManagedPolicy = {
233
- Type: 'AWS::IAM::ManagedPolicy',
234
- Properties: {
235
- ManagedPolicyName: resourceName,
236
- Description: description || `Managed policy for ${resourceName}`,
237
- PolicyDocument: {
238
- Version: '2012-10-17',
239
- Statement: policyStatements,
240
- },
241
- },
242
- }
243
-
244
- return { policy, logicalId }
245
- }
246
-
247
- /**
248
- * Attach a policy to a role
249
- */
250
- static attachPolicyToRole(
251
- role: IAMRole,
252
- policyArn: string,
253
- ): IAMRole {
254
- if (!role.Properties.ManagedPolicyArns) {
255
- role.Properties.ManagedPolicyArns = []
256
- }
257
-
258
- if (!role.Properties.ManagedPolicyArns.includes(policyArn)) {
259
- role.Properties.ManagedPolicyArns.push(policyArn)
260
- }
261
-
262
- return role
263
- }
264
-
265
- /**
266
- * Attach a policy to a user
267
- */
268
- static attachPolicyToUser(
269
- user: IAMUser,
270
- policyArn: string,
271
- ): IAMUser {
272
- if (!user.Properties.ManagedPolicyArns) {
273
- user.Properties.ManagedPolicyArns = []
274
- }
275
-
276
- if (!user.Properties.ManagedPolicyArns.includes(policyArn)) {
277
- user.Properties.ManagedPolicyArns.push(policyArn)
278
- }
279
-
280
- return user
281
- }
282
-
283
- /**
284
- * Attach a policy to a group
285
- */
286
- static attachPolicyToGroup(
287
- group: IAMGroup,
288
- policyArn: string,
289
- ): IAMGroup {
290
- if (!group.Properties.ManagedPolicyArns) {
291
- group.Properties.ManagedPolicyArns = []
292
- }
293
-
294
- if (!group.Properties.ManagedPolicyArns.includes(policyArn)) {
295
- group.Properties.ManagedPolicyArns.push(policyArn)
296
- }
297
-
298
- return group
299
- }
300
-
301
- /**
302
- * Add inline policy to a role
303
- */
304
- static addInlinePolicyToRole(
305
- role: IAMRole,
306
- policyName: string,
307
- statements: PolicyStatement[],
308
- ): IAMRole {
309
- if (!role.Properties.Policies) {
310
- role.Properties.Policies = []
311
- }
312
-
313
- const policyStatements = statements.map(stmt => ({
314
- Effect: stmt.effect || 'Allow',
315
- Action: stmt.actions,
316
- Resource: stmt.resources,
317
- }))
318
-
319
- role.Properties.Policies.push({
320
- PolicyName: policyName,
321
- PolicyDocument: {
322
- Version: '2012-10-17',
323
- Statement: policyStatements,
324
- },
325
- })
326
-
327
- return role
328
- }
329
-
330
- /**
331
- * Add inline policy to a user
332
- */
333
- static addInlinePolicyToUser(
334
- user: IAMUser,
335
- policyName: string,
336
- statements: PolicyStatement[],
337
- ): IAMUser {
338
- if (!user.Properties.Policies) {
339
- user.Properties.Policies = []
340
- }
341
-
342
- const policyStatements = statements.map(stmt => ({
343
- Effect: stmt.effect || 'Allow',
344
- Action: stmt.actions,
345
- Resource: stmt.resources,
346
- }))
347
-
348
- user.Properties.Policies.push({
349
- PolicyName: policyName,
350
- PolicyDocument: {
351
- Version: '2012-10-17',
352
- Statement: policyStatements,
353
- },
354
- })
355
-
356
- return user
357
- }
358
-
359
- /**
360
- * Create an access key for programmatic access
361
- */
362
- static createAccessKey(
363
- userLogicalId: string,
364
- options: {
365
- slug: string
366
- environment: EnvironmentType
367
- status?: 'Active' | 'Inactive'
368
- },
369
- ): {
370
- accessKey: IAMAccessKey
371
- logicalId: string
372
- } {
373
- const { slug, environment, status = 'Active' } = options
374
-
375
- const resourceName = generateResourceName({
376
- slug,
377
- environment,
378
- resourceType: 'access-key',
379
- })
380
-
381
- const logicalId = generateLogicalId(resourceName)
382
-
383
- const accessKey: IAMAccessKey = {
384
- Type: 'AWS::IAM::AccessKey',
385
- Properties: {
386
- UserName: Fn.Ref(userLogicalId) as unknown as string,
387
- Status: status,
388
- },
389
- }
390
-
391
- return { accessKey, logicalId }
392
- }
393
-
394
- /**
395
- * Create an instance profile for EC2
396
- */
397
- static createInstanceProfile(
398
- roleLogicalId: string,
399
- options: {
400
- slug: string
401
- environment: EnvironmentType
402
- profileName?: string
403
- },
404
- ): {
405
- instanceProfile: IAMInstanceProfile
406
- logicalId: string
407
- } {
408
- const { slug, environment, profileName } = options
409
-
410
- const resourceName = profileName || generateResourceName({
411
- slug,
412
- environment,
413
- resourceType: 'instance-profile',
414
- })
415
-
416
- const logicalId = generateLogicalId(resourceName)
417
-
418
- const instanceProfile: IAMInstanceProfile = {
419
- Type: 'AWS::IAM::InstanceProfile',
420
- Properties: {
421
- InstanceProfileName: resourceName,
422
- Roles: [Fn.Ref(roleLogicalId) as unknown as string],
423
- },
424
- }
425
-
426
- return { instanceProfile, logicalId }
427
- }
428
-
429
- /**
430
- * AWS Managed Policies (common)
431
- */
432
- static readonly ManagedPolicies = {
433
- // Administrator Access
434
- AdministratorAccess: 'arn:aws:iam::aws:policy/AdministratorAccess',
435
-
436
- // Power User
437
- PowerUserAccess: 'arn:aws:iam::aws:policy/PowerUserAccess',
438
-
439
- // Read Only
440
- ReadOnlyAccess: 'arn:aws:iam::aws:policy/ReadOnlyAccess',
441
-
442
- // S3
443
- S3FullAccess: 'arn:aws:iam::aws:policy/AmazonS3FullAccess',
444
- S3ReadOnlyAccess: 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess',
445
-
446
- // DynamoDB
447
- DynamoDBFullAccess: 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess',
448
- DynamoDBReadOnlyAccess: 'arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess',
449
-
450
- // RDS
451
- RDSFullAccess: 'arn:aws:iam::aws:policy/AmazonRDSFullAccess',
452
- RDSReadOnlyAccess: 'arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess',
453
-
454
- // Lambda
455
- LambdaFullAccess: 'arn:aws:iam::aws:policy/AWSLambda_FullAccess',
456
- LambdaReadOnlyAccess: 'arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess',
457
- LambdaBasicExecutionRole: 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole',
458
- LambdaVPCAccessExecutionRole: 'arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole',
459
-
460
- // EC2
461
- EC2FullAccess: 'arn:aws:iam::aws:policy/AmazonEC2FullAccess',
462
- EC2ReadOnlyAccess: 'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess',
463
- EC2ContainerRegistryReadOnly: 'arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly',
464
- EC2ContainerRegistryPowerUser: 'arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser',
465
-
466
- // ECS
467
- ECSTaskExecutionRole: 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy',
468
- ECSFullAccess: 'arn:aws:iam::aws:policy/AmazonECS_FullAccess',
469
-
470
- // CloudWatch
471
- CloudWatchFullAccess: 'arn:aws:iam::aws:policy/CloudWatchFullAccess',
472
- CloudWatchLogsFullAccess: 'arn:aws:iam::aws:policy/CloudWatchLogsFullAccess',
473
-
474
- // SES
475
- SESFullAccess: 'arn:aws:iam::aws:policy/AmazonSESFullAccess',
476
-
477
- // SNS
478
- SNSFullAccess: 'arn:aws:iam::aws:policy/AmazonSNSFullAccess',
479
-
480
- // SQS
481
- SQSFullAccess: 'arn:aws:iam::aws:policy/AmazonSQSFullAccess',
482
-
483
- // Secrets Manager
484
- SecretsManagerReadWrite: 'arn:aws:iam::aws:policy/SecretsManagerReadWrite',
485
- } as const
486
-
487
- /**
488
- * Common service principals
489
- */
490
- static readonly ServicePrincipals = {
491
- Lambda: 'lambda.amazonaws.com',
492
- EC2: 'ec2.amazonaws.com',
493
- ECS: 'ecs.amazonaws.com',
494
- ECSTaskExecution: 'ecs-tasks.amazonaws.com',
495
- APIGateway: 'apigateway.amazonaws.com',
496
- Events: 'events.amazonaws.com',
497
- States: 'states.amazonaws.com',
498
- CodeBuild: 'codebuild.amazonaws.com',
499
- CodeDeploy: 'codedeploy.amazonaws.com',
500
- CloudFormation: 'cloudformation.amazonaws.com',
501
- } as const
502
-
503
- /**
504
- * Create a CI/CD user with deployment permissions
505
- */
506
- static createCiCdUser(options: {
507
- slug: string
508
- environment: EnvironmentType
509
- permissions: {
510
- s3Buckets?: string[]
511
- cloudFrontDistributions?: string[]
512
- ecrRepositories?: string[]
513
- ecsServices?: string[]
514
- cloudFormationStacks?: string[]
515
- lambdaFunctions?: string[]
516
- secretsManagerSecrets?: string[]
517
- }
518
- createAccessKey?: boolean
519
- }): {
520
- user: IAMUser
521
- accessKey?: IAMAccessKey
522
- policy: IAMManagedPolicy
523
- userLogicalId: string
524
- accessKeyLogicalId?: string
525
- policyLogicalId: string
526
- resources: Record<string, any>
527
- } {
528
- const {
529
- slug,
530
- environment,
531
- permissions,
532
- createAccessKey = true,
533
- } = options
534
-
535
- const resources: Record<string, any> = {}
536
-
537
- // Build policy statements based on permissions
538
- const statements: PolicyStatement[] = []
539
-
540
- // S3 permissions
541
- if (permissions.s3Buckets && permissions.s3Buckets.length > 0) {
542
- statements.push({
543
- sid: 'S3Access',
544
- actions: [
545
- 's3:GetBucketLocation',
546
- 's3:ListBucket',
547
- 's3:GetObject',
548
- 's3:PutObject',
549
- 's3:DeleteObject',
550
- 's3:ListBucketMultipartUploads',
551
- 's3:AbortMultipartUpload',
552
- ],
553
- resources: [
554
- ...permissions.s3Buckets,
555
- ...permissions.s3Buckets.map(b => `${b}/*`),
556
- ],
557
- })
558
- }
559
-
560
- // CloudFront permissions
561
- if (permissions.cloudFrontDistributions && permissions.cloudFrontDistributions.length > 0) {
562
- statements.push({
563
- sid: 'CloudFrontAccess',
564
- actions: [
565
- 'cloudfront:CreateInvalidation',
566
- 'cloudfront:GetInvalidation',
567
- 'cloudfront:ListInvalidations',
568
- 'cloudfront:GetDistribution',
569
- ],
570
- resources: permissions.cloudFrontDistributions,
571
- })
572
- }
573
-
574
- // ECR permissions
575
- if (permissions.ecrRepositories && permissions.ecrRepositories.length > 0) {
576
- statements.push({
577
- sid: 'ECRAccess',
578
- actions: [
579
- 'ecr:GetAuthorizationToken',
580
- 'ecr:BatchCheckLayerAvailability',
581
- 'ecr:GetDownloadUrlForLayer',
582
- 'ecr:GetRepositoryPolicy',
583
- 'ecr:DescribeRepositories',
584
- 'ecr:ListImages',
585
- 'ecr:DescribeImages',
586
- 'ecr:BatchGetImage',
587
- 'ecr:InitiateLayerUpload',
588
- 'ecr:UploadLayerPart',
589
- 'ecr:CompleteLayerUpload',
590
- 'ecr:PutImage',
591
- ],
592
- resources: permissions.ecrRepositories,
593
- })
594
-
595
- // ECR login requires permission on all resources
596
- statements.push({
597
- sid: 'ECRLogin',
598
- actions: ['ecr:GetAuthorizationToken'],
599
- resources: '*',
600
- })
601
- }
602
-
603
- // ECS permissions
604
- if (permissions.ecsServices && permissions.ecsServices.length > 0) {
605
- statements.push({
606
- sid: 'ECSAccess',
607
- actions: [
608
- 'ecs:DescribeServices',
609
- 'ecs:DescribeTaskDefinition',
610
- 'ecs:DescribeTasks',
611
- 'ecs:ListTasks',
612
- 'ecs:RegisterTaskDefinition',
613
- 'ecs:UpdateService',
614
- 'ecs:RunTask',
615
- 'ecs:StopTask',
616
- ],
617
- resources: permissions.ecsServices,
618
- })
619
-
620
- // Task definition registration requires broader permissions
621
- statements.push({
622
- sid: 'ECSTaskDefinitions',
623
- actions: [
624
- 'ecs:RegisterTaskDefinition',
625
- 'ecs:DeregisterTaskDefinition',
626
- ],
627
- resources: '*',
628
- })
629
-
630
- // IAM PassRole for ECS
631
- statements.push({
632
- sid: 'ECSPassRole',
633
- actions: ['iam:PassRole'],
634
- resources: '*',
635
- conditions: {
636
- StringLike: {
637
- 'iam:PassedToService': 'ecs-tasks.amazonaws.com',
638
- },
639
- },
640
- })
641
- }
642
-
643
- // CloudFormation permissions
644
- if (permissions.cloudFormationStacks && permissions.cloudFormationStacks.length > 0) {
645
- statements.push({
646
- sid: 'CloudFormationAccess',
647
- actions: [
648
- 'cloudformation:CreateStack',
649
- 'cloudformation:UpdateStack',
650
- 'cloudformation:DeleteStack',
651
- 'cloudformation:DescribeStacks',
652
- 'cloudformation:DescribeStackEvents',
653
- 'cloudformation:DescribeStackResources',
654
- 'cloudformation:GetTemplate',
655
- 'cloudformation:ListStackResources',
656
- 'cloudformation:ValidateTemplate',
657
- ],
658
- resources: permissions.cloudFormationStacks,
659
- })
660
- }
661
-
662
- // Lambda permissions
663
- if (permissions.lambdaFunctions && permissions.lambdaFunctions.length > 0) {
664
- statements.push({
665
- sid: 'LambdaAccess',
666
- actions: [
667
- 'lambda:GetFunction',
668
- 'lambda:UpdateFunctionCode',
669
- 'lambda:UpdateFunctionConfiguration',
670
- 'lambda:PublishVersion',
671
- 'lambda:UpdateAlias',
672
- 'lambda:CreateAlias',
673
- ],
674
- resources: permissions.lambdaFunctions,
675
- })
676
- }
677
-
678
- // Secrets Manager permissions
679
- if (permissions.secretsManagerSecrets && permissions.secretsManagerSecrets.length > 0) {
680
- statements.push({
681
- sid: 'SecretsManagerAccess',
682
- actions: [
683
- 'secretsmanager:GetSecretValue',
684
- 'secretsmanager:DescribeSecret',
685
- ],
686
- resources: permissions.secretsManagerSecrets,
687
- })
688
- }
689
-
690
- // Create the policy
691
- const { policy, logicalId: policyLogicalId } = Permissions.createPolicy({
692
- slug,
693
- environment,
694
- policyName: generateResourceName({
695
- slug,
696
- environment,
697
- resourceType: 'cicd-policy',
698
- }),
699
- description: `CI/CD deployment policy for ${slug} (${environment})`,
700
- statements,
701
- })
702
- resources[policyLogicalId] = policy
703
-
704
- // Create the user
705
- const { user, logicalId: userLogicalId } = Permissions.createUser({
706
- slug,
707
- environment,
708
- userName: generateResourceName({
709
- slug,
710
- environment,
711
- resourceType: 'cicd-user',
712
- }),
713
- managedPolicyArns: [Fn.Ref(policyLogicalId) as unknown as string],
714
- })
715
- resources[userLogicalId] = user
716
-
717
- // Create access key if requested
718
- let accessKey: IAMAccessKey | undefined
719
- let accessKeyLogicalId: string | undefined
720
-
721
- if (createAccessKey) {
722
- const keyResult = Permissions.createAccessKey(userLogicalId, { slug, environment })
723
- accessKey = keyResult.accessKey
724
- accessKeyLogicalId = keyResult.logicalId
725
- resources[accessKeyLogicalId] = accessKey
726
- }
727
-
728
- return {
729
- user,
730
- accessKey,
731
- policy,
732
- userLogicalId,
733
- accessKeyLogicalId,
734
- policyLogicalId,
735
- resources,
736
- }
737
- }
738
-
739
- /**
740
- * Create a cross-account access role
741
- */
742
- static createCrossAccountRole(options: {
743
- slug: string
744
- environment: EnvironmentType
745
- trustedAccountIds: string[]
746
- externalId?: string
747
- permissions: PolicyStatement[]
748
- maxSessionDuration?: number
749
- }): {
750
- role: IAMRole
751
- policy: IAMManagedPolicy
752
- roleLogicalId: string
753
- policyLogicalId: string
754
- resources: Record<string, any>
755
- } {
756
- const {
757
- slug,
758
- environment,
759
- trustedAccountIds,
760
- externalId,
761
- permissions,
762
- maxSessionDuration = 3600,
763
- } = options
764
-
765
- const resources: Record<string, any> = {}
766
-
767
- // Create the policy
768
- const { policy, logicalId: policyLogicalId } = Permissions.createPolicy({
769
- slug,
770
- environment,
771
- policyName: generateResourceName({
772
- slug,
773
- environment,
774
- resourceType: 'cross-account-policy',
775
- }),
776
- description: `Cross-account access policy for ${slug} (${environment})`,
777
- statements: permissions,
778
- })
779
- resources[policyLogicalId] = policy
780
-
781
- const resourceName = generateResourceName({
782
- slug,
783
- environment,
784
- resourceType: 'cross-account-role',
785
- })
786
-
787
- const roleLogicalId = generateLogicalId(resourceName)
788
-
789
- // Build trust policy
790
- const conditions: Record<string, any> = {}
791
- if (externalId) {
792
- conditions.StringEquals = {
793
- 'sts:ExternalId': externalId,
794
- }
795
- }
796
-
797
- const role: IAMRole = {
798
- Type: 'AWS::IAM::Role',
799
- Properties: {
800
- RoleName: resourceName,
801
- MaxSessionDuration: maxSessionDuration,
802
- AssumeRolePolicyDocument: {
803
- Version: '2012-10-17',
804
- Statement: [{
805
- Effect: 'Allow',
806
- Principal: {
807
- AWS: trustedAccountIds.map(id => `arn:aws:iam::${id}:root`),
808
- },
809
- Action: 'sts:AssumeRole',
810
- ...(Object.keys(conditions).length > 0 ? { Condition: conditions } : {}),
811
- }],
812
- },
813
- ManagedPolicyArns: [Fn.Ref(policyLogicalId) as unknown as string],
814
- Tags: [
815
- { Key: 'Name', Value: resourceName },
816
- { Key: 'Environment', Value: environment },
817
- { Key: 'Purpose', Value: 'Cross-Account Access' },
818
- ],
819
- },
820
- }
821
- resources[roleLogicalId] = role
822
-
823
- return {
824
- role,
825
- policy,
826
- roleLogicalId,
827
- policyLogicalId,
828
- resources,
829
- }
830
- }
831
-
832
- /**
833
- * Create a CLI access user with minimal permissions
834
- */
835
- static createCliUser(options: {
836
- slug: string
837
- environment: EnvironmentType
838
- permissions?: 'readonly' | 'deploy' | 'admin'
839
- }): {
840
- user: IAMUser
841
- accessKey: IAMAccessKey
842
- policy?: IAMManagedPolicy
843
- userLogicalId: string
844
- accessKeyLogicalId: string
845
- policyLogicalId?: string
846
- resources: Record<string, any>
847
- } {
848
- const {
849
- slug,
850
- environment,
851
- permissions = 'readonly',
852
- } = options
853
-
854
- const resources: Record<string, any> = {}
855
-
856
- // Define statements based on permission level
857
- let statements: PolicyStatement[] = []
858
- let managedPolicyArns: string[] = []
859
-
860
- switch (permissions) {
861
- case 'readonly':
862
- managedPolicyArns = [Permissions.ManagedPolicies.ReadOnlyAccess]
863
- break
864
-
865
- case 'deploy':
866
- statements = [
867
- {
868
- sid: 'S3Deploy',
869
- actions: ['s3:*'],
870
- resources: '*',
871
- },
872
- {
873
- sid: 'CloudFrontDeploy',
874
- actions: ['cloudfront:*'],
875
- resources: '*',
876
- },
877
- {
878
- sid: 'ECSDeploy',
879
- actions: ['ecs:*'],
880
- resources: '*',
881
- },
882
- {
883
- sid: 'ECRDeploy',
884
- actions: ['ecr:*'],
885
- resources: '*',
886
- },
887
- {
888
- sid: 'LambdaDeploy',
889
- actions: ['lambda:*'],
890
- resources: '*',
891
- },
892
- {
893
- sid: 'CloudFormationDeploy',
894
- actions: ['cloudformation:*'],
895
- resources: '*',
896
- },
897
- {
898
- sid: 'IAMPassRole',
899
- actions: ['iam:PassRole'],
900
- resources: '*',
901
- },
902
- ]
903
- break
904
-
905
- case 'admin':
906
- managedPolicyArns = [Permissions.ManagedPolicies.AdministratorAccess]
907
- break
908
- }
909
-
910
- // Create policy if needed
911
- let policy: IAMManagedPolicy | undefined
912
- let policyLogicalId: string | undefined
913
-
914
- if (statements.length > 0) {
915
- const policyResult = Permissions.createPolicy({
916
- slug,
917
- environment,
918
- policyName: generateResourceName({
919
- slug,
920
- environment,
921
- resourceType: 'cli-policy',
922
- }),
923
- description: `CLI access policy for ${slug} (${environment})`,
924
- statements,
925
- })
926
- policy = policyResult.policy
927
- policyLogicalId = policyResult.logicalId
928
- resources[policyLogicalId] = policy
929
- managedPolicyArns = [Fn.Ref(policyLogicalId) as unknown as string]
930
- }
931
-
932
- // Create user
933
- const { user, logicalId: userLogicalId } = Permissions.createUser({
934
- slug,
935
- environment,
936
- userName: generateResourceName({
937
- slug,
938
- environment,
939
- resourceType: 'cli-user',
940
- }),
941
- managedPolicyArns,
942
- })
943
- resources[userLogicalId] = user
944
-
945
- // Create access key
946
- const { accessKey, logicalId: accessKeyLogicalId } = Permissions.createAccessKey(
947
- userLogicalId,
948
- { slug, environment },
949
- )
950
- resources[accessKeyLogicalId] = accessKey
951
-
952
- return {
953
- user,
954
- accessKey,
955
- policy,
956
- userLogicalId,
957
- accessKeyLogicalId,
958
- policyLogicalId,
959
- resources,
960
- }
961
- }
962
-
963
- /**
964
- * Common CI/CD policy templates
965
- */
966
- static readonly CiCdPolicies = {
967
- /**
968
- * S3 static site deployment policy
969
- */
970
- s3Deployment: (bucketArns: string[]): PolicyStatement[] => [
971
- {
972
- sid: 'S3ListBuckets',
973
- actions: ['s3:ListBucket', 's3:GetBucketLocation'],
974
- resources: bucketArns,
975
- },
976
- {
977
- sid: 'S3Objects',
978
- actions: ['s3:GetObject', 's3:PutObject', 's3:DeleteObject'],
979
- resources: bucketArns.map(arn => `${arn}/*`),
980
- },
981
- ],
982
-
983
- /**
984
- * CloudFront invalidation policy
985
- */
986
- cloudFrontInvalidation: (distributionArns: string[]): PolicyStatement[] => [
987
- {
988
- sid: 'CloudFrontInvalidation',
989
- actions: [
990
- 'cloudfront:CreateInvalidation',
991
- 'cloudfront:GetInvalidation',
992
- 'cloudfront:ListInvalidations',
993
- ],
994
- resources: distributionArns,
995
- },
996
- ],
997
-
998
- /**
999
- * ECS deployment policy
1000
- */
1001
- ecsDeployment: (): PolicyStatement[] => [
1002
- {
1003
- sid: 'ECSServices',
1004
- actions: [
1005
- 'ecs:DescribeServices',
1006
- 'ecs:UpdateService',
1007
- 'ecs:DescribeTaskDefinition',
1008
- 'ecs:RegisterTaskDefinition',
1009
- ],
1010
- resources: '*',
1011
- },
1012
- {
1013
- sid: 'ECSPassRole',
1014
- actions: ['iam:PassRole'],
1015
- resources: '*',
1016
- conditions: {
1017
- StringLike: {
1018
- 'iam:PassedToService': 'ecs-tasks.amazonaws.com',
1019
- },
1020
- },
1021
- },
1022
- ],
1023
-
1024
- /**
1025
- * ECR push policy
1026
- */
1027
- ecrPush: (repositoryArns: string[]): PolicyStatement[] => [
1028
- {
1029
- sid: 'ECRAuth',
1030
- actions: ['ecr:GetAuthorizationToken'],
1031
- resources: '*',
1032
- },
1033
- {
1034
- sid: 'ECRPush',
1035
- actions: [
1036
- 'ecr:BatchCheckLayerAvailability',
1037
- 'ecr:GetDownloadUrlForLayer',
1038
- 'ecr:BatchGetImage',
1039
- 'ecr:InitiateLayerUpload',
1040
- 'ecr:UploadLayerPart',
1041
- 'ecr:CompleteLayerUpload',
1042
- 'ecr:PutImage',
1043
- ],
1044
- resources: repositoryArns,
1045
- },
1046
- ],
1047
-
1048
- /**
1049
- * Lambda deployment policy
1050
- */
1051
- lambdaDeployment: (functionArns: string[]): PolicyStatement[] => [
1052
- {
1053
- sid: 'LambdaDeploy',
1054
- actions: [
1055
- 'lambda:GetFunction',
1056
- 'lambda:UpdateFunctionCode',
1057
- 'lambda:UpdateFunctionConfiguration',
1058
- 'lambda:PublishVersion',
1059
- ],
1060
- resources: functionArns,
1061
- },
1062
- ],
1063
-
1064
- /**
1065
- * CloudFormation deployment policy
1066
- */
1067
- cloudFormationDeployment: (stackArns: string[]): PolicyStatement[] => [
1068
- {
1069
- sid: 'CloudFormationDeploy',
1070
- actions: [
1071
- 'cloudformation:CreateStack',
1072
- 'cloudformation:UpdateStack',
1073
- 'cloudformation:DescribeStacks',
1074
- 'cloudformation:DescribeStackEvents',
1075
- 'cloudformation:GetTemplate',
1076
- ],
1077
- resources: stackArns,
1078
- },
1079
- ],
1080
- }
1081
- }