@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.
Files changed (251) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +321 -0
  3. package/package.json +31 -0
  4. package/src/advanced-features.test.ts +465 -0
  5. package/src/aws/cloudformation.ts +421 -0
  6. package/src/aws/cloudfront.ts +158 -0
  7. package/src/aws/credentials.test.ts +132 -0
  8. package/src/aws/credentials.ts +545 -0
  9. package/src/aws/index.ts +87 -0
  10. package/src/aws/s3.test.ts +188 -0
  11. package/src/aws/s3.ts +1088 -0
  12. package/src/aws/signature.test.ts +670 -0
  13. package/src/aws/signature.ts +1155 -0
  14. package/src/backup/disaster-recovery.test.ts +726 -0
  15. package/src/backup/disaster-recovery.ts +500 -0
  16. package/src/backup/index.ts +34 -0
  17. package/src/backup/manager.test.ts +498 -0
  18. package/src/backup/manager.ts +432 -0
  19. package/src/cicd/circleci.ts +430 -0
  20. package/src/cicd/github-actions.ts +424 -0
  21. package/src/cicd/gitlab-ci.ts +255 -0
  22. package/src/cicd/index.ts +8 -0
  23. package/src/cli/history.ts +396 -0
  24. package/src/cli/index.ts +10 -0
  25. package/src/cli/progress.ts +458 -0
  26. package/src/cli/repl.ts +454 -0
  27. package/src/cli/suggestions.ts +327 -0
  28. package/src/cli/table.test.ts +319 -0
  29. package/src/cli/table.ts +332 -0
  30. package/src/cloudformation/builder.test.ts +327 -0
  31. package/src/cloudformation/builder.ts +378 -0
  32. package/src/cloudformation/builders/api-gateway.ts +449 -0
  33. package/src/cloudformation/builders/cache.ts +334 -0
  34. package/src/cloudformation/builders/cdn.ts +278 -0
  35. package/src/cloudformation/builders/compute.ts +485 -0
  36. package/src/cloudformation/builders/database.ts +392 -0
  37. package/src/cloudformation/builders/functions.ts +343 -0
  38. package/src/cloudformation/builders/messaging.ts +140 -0
  39. package/src/cloudformation/builders/monitoring.ts +300 -0
  40. package/src/cloudformation/builders/network.ts +264 -0
  41. package/src/cloudformation/builders/queue.ts +147 -0
  42. package/src/cloudformation/builders/security.ts +399 -0
  43. package/src/cloudformation/builders/storage.ts +285 -0
  44. package/src/cloudformation/index.ts +30 -0
  45. package/src/cloudformation/types.ts +173 -0
  46. package/src/compliance/aws-config.ts +543 -0
  47. package/src/compliance/cloudtrail.ts +376 -0
  48. package/src/compliance/compliance.test.ts +423 -0
  49. package/src/compliance/guardduty.ts +446 -0
  50. package/src/compliance/index.ts +66 -0
  51. package/src/compliance/security-hub.ts +456 -0
  52. package/src/containers/build-optimization.ts +416 -0
  53. package/src/containers/containers.test.ts +508 -0
  54. package/src/containers/image-scanning.ts +360 -0
  55. package/src/containers/index.ts +9 -0
  56. package/src/containers/registry.ts +293 -0
  57. package/src/containers/service-mesh.ts +520 -0
  58. package/src/database/database.test.ts +762 -0
  59. package/src/database/index.ts +9 -0
  60. package/src/database/migrations.ts +444 -0
  61. package/src/database/performance.ts +528 -0
  62. package/src/database/replicas.ts +534 -0
  63. package/src/database/users.ts +494 -0
  64. package/src/dependency-graph.ts +143 -0
  65. package/src/deployment/ab-testing.ts +582 -0
  66. package/src/deployment/blue-green.ts +452 -0
  67. package/src/deployment/canary.ts +500 -0
  68. package/src/deployment/deployment.test.ts +526 -0
  69. package/src/deployment/index.ts +61 -0
  70. package/src/deployment/progressive.ts +62 -0
  71. package/src/dns/dns.test.ts +641 -0
  72. package/src/dns/dnssec.ts +315 -0
  73. package/src/dns/index.ts +8 -0
  74. package/src/dns/resolver.ts +496 -0
  75. package/src/dns/routing.ts +593 -0
  76. package/src/email/advanced/analytics.ts +445 -0
  77. package/src/email/advanced/index.ts +11 -0
  78. package/src/email/advanced/rules.ts +465 -0
  79. package/src/email/advanced/scheduling.ts +352 -0
  80. package/src/email/advanced/search.ts +412 -0
  81. package/src/email/advanced/shared-mailboxes.ts +404 -0
  82. package/src/email/advanced/templates.ts +455 -0
  83. package/src/email/advanced/threading.ts +281 -0
  84. package/src/email/analytics.ts +467 -0
  85. package/src/email/bounce-handling.ts +425 -0
  86. package/src/email/email.test.ts +431 -0
  87. package/src/email/handlers/__tests__/inbound.test.ts +38 -0
  88. package/src/email/handlers/__tests__/outbound.test.ts +37 -0
  89. package/src/email/handlers/converter.ts +227 -0
  90. package/src/email/handlers/feedback.ts +228 -0
  91. package/src/email/handlers/inbound.ts +169 -0
  92. package/src/email/handlers/outbound.ts +178 -0
  93. package/src/email/index.ts +15 -0
  94. package/src/email/reputation.ts +303 -0
  95. package/src/email/templates.ts +352 -0
  96. package/src/errors/index.test.ts +434 -0
  97. package/src/errors/index.ts +416 -0
  98. package/src/health-checks/index.ts +40 -0
  99. package/src/index.ts +360 -0
  100. package/src/intrinsic-functions.ts +118 -0
  101. package/src/lambda/concurrency.ts +330 -0
  102. package/src/lambda/destinations.ts +345 -0
  103. package/src/lambda/dlq.ts +425 -0
  104. package/src/lambda/index.ts +11 -0
  105. package/src/lambda/lambda.test.ts +840 -0
  106. package/src/lambda/layers.ts +263 -0
  107. package/src/lambda/versions.ts +376 -0
  108. package/src/lambda/vpc.ts +399 -0
  109. package/src/local/config.ts +114 -0
  110. package/src/local/index.ts +6 -0
  111. package/src/local/mock-aws.ts +351 -0
  112. package/src/modules/ai.ts +340 -0
  113. package/src/modules/api.ts +478 -0
  114. package/src/modules/auth.ts +805 -0
  115. package/src/modules/cache.ts +417 -0
  116. package/src/modules/cdn.ts +1062 -0
  117. package/src/modules/communication.ts +1094 -0
  118. package/src/modules/compute.ts +3348 -0
  119. package/src/modules/database.ts +554 -0
  120. package/src/modules/deployment.ts +1079 -0
  121. package/src/modules/dns.ts +337 -0
  122. package/src/modules/email.ts +1538 -0
  123. package/src/modules/filesystem.ts +515 -0
  124. package/src/modules/index.ts +32 -0
  125. package/src/modules/messaging.ts +486 -0
  126. package/src/modules/monitoring.ts +2086 -0
  127. package/src/modules/network.ts +664 -0
  128. package/src/modules/parameter-store.ts +325 -0
  129. package/src/modules/permissions.ts +1081 -0
  130. package/src/modules/phone.ts +494 -0
  131. package/src/modules/queue.ts +1260 -0
  132. package/src/modules/redirects.ts +464 -0
  133. package/src/modules/registry.ts +699 -0
  134. package/src/modules/search.ts +401 -0
  135. package/src/modules/secrets.ts +416 -0
  136. package/src/modules/security.ts +731 -0
  137. package/src/modules/sms.ts +389 -0
  138. package/src/modules/storage.ts +1120 -0
  139. package/src/modules/workflow.ts +680 -0
  140. package/src/multi-account/config.ts +521 -0
  141. package/src/multi-account/index.ts +7 -0
  142. package/src/multi-account/manager.ts +427 -0
  143. package/src/multi-region/cross-region.ts +410 -0
  144. package/src/multi-region/index.ts +8 -0
  145. package/src/multi-region/manager.ts +483 -0
  146. package/src/multi-region/regions.ts +435 -0
  147. package/src/network-security/index.ts +48 -0
  148. package/src/observability/index.ts +9 -0
  149. package/src/observability/logs.ts +522 -0
  150. package/src/observability/metrics.ts +460 -0
  151. package/src/observability/observability.test.ts +782 -0
  152. package/src/observability/synthetics.ts +568 -0
  153. package/src/observability/xray.ts +358 -0
  154. package/src/phone/advanced/analytics.ts +349 -0
  155. package/src/phone/advanced/callbacks.ts +428 -0
  156. package/src/phone/advanced/index.ts +8 -0
  157. package/src/phone/advanced/ivr-builder.ts +504 -0
  158. package/src/phone/advanced/recording.ts +310 -0
  159. package/src/phone/handlers/__tests__/incoming-call.test.ts +40 -0
  160. package/src/phone/handlers/incoming-call.ts +117 -0
  161. package/src/phone/handlers/missed-call.ts +116 -0
  162. package/src/phone/handlers/voicemail.ts +179 -0
  163. package/src/phone/index.ts +9 -0
  164. package/src/presets/api-backend.ts +134 -0
  165. package/src/presets/data-pipeline.ts +204 -0
  166. package/src/presets/extend.test.ts +295 -0
  167. package/src/presets/extend.ts +297 -0
  168. package/src/presets/fullstack-app.ts +144 -0
  169. package/src/presets/index.ts +27 -0
  170. package/src/presets/jamstack.ts +135 -0
  171. package/src/presets/microservices.ts +167 -0
  172. package/src/presets/ml-api.ts +208 -0
  173. package/src/presets/nodejs-server.ts +104 -0
  174. package/src/presets/nodejs-serverless.ts +114 -0
  175. package/src/presets/realtime-app.ts +184 -0
  176. package/src/presets/static-site.ts +64 -0
  177. package/src/presets/traditional-web-app.ts +339 -0
  178. package/src/presets/wordpress.ts +138 -0
  179. package/src/preview/github.test.ts +249 -0
  180. package/src/preview/github.ts +297 -0
  181. package/src/preview/index.ts +37 -0
  182. package/src/preview/manager.test.ts +440 -0
  183. package/src/preview/manager.ts +326 -0
  184. package/src/preview/notifications.test.ts +582 -0
  185. package/src/preview/notifications.ts +341 -0
  186. package/src/queue/batch-processing.ts +402 -0
  187. package/src/queue/dlq-monitoring.ts +402 -0
  188. package/src/queue/fifo.ts +342 -0
  189. package/src/queue/index.ts +9 -0
  190. package/src/queue/management.ts +428 -0
  191. package/src/queue/queue.test.ts +429 -0
  192. package/src/resource-mgmt/index.ts +39 -0
  193. package/src/resource-naming.ts +62 -0
  194. package/src/s3/index.ts +523 -0
  195. package/src/schema/cloud-config.schema.json +554 -0
  196. package/src/schema/index.ts +68 -0
  197. package/src/security/certificate-manager.ts +492 -0
  198. package/src/security/index.ts +9 -0
  199. package/src/security/scanning.ts +545 -0
  200. package/src/security/secrets-manager.ts +476 -0
  201. package/src/security/secrets-rotation.ts +456 -0
  202. package/src/security/security.test.ts +738 -0
  203. package/src/sms/advanced/ab-testing.ts +389 -0
  204. package/src/sms/advanced/analytics.ts +336 -0
  205. package/src/sms/advanced/campaigns.ts +523 -0
  206. package/src/sms/advanced/chatbot.ts +224 -0
  207. package/src/sms/advanced/index.ts +10 -0
  208. package/src/sms/advanced/link-tracking.ts +248 -0
  209. package/src/sms/advanced/mms.ts +308 -0
  210. package/src/sms/handlers/__tests__/send.test.ts +40 -0
  211. package/src/sms/handlers/delivery-status.ts +133 -0
  212. package/src/sms/handlers/receive.ts +162 -0
  213. package/src/sms/handlers/send.ts +174 -0
  214. package/src/sms/index.ts +9 -0
  215. package/src/stack-diff.ts +389 -0
  216. package/src/static-site/index.ts +85 -0
  217. package/src/template-builder.ts +110 -0
  218. package/src/template-validator.ts +574 -0
  219. package/src/utils/cache.ts +291 -0
  220. package/src/utils/diff.ts +269 -0
  221. package/src/utils/hash.ts +227 -0
  222. package/src/utils/index.ts +8 -0
  223. package/src/utils/parallel.ts +294 -0
  224. package/src/validators/credentials.test.ts +274 -0
  225. package/src/validators/credentials.ts +233 -0
  226. package/src/validators/quotas.test.ts +434 -0
  227. package/src/validators/quotas.ts +217 -0
  228. package/test/ai.test.ts +327 -0
  229. package/test/api.test.ts +511 -0
  230. package/test/auth.test.ts +632 -0
  231. package/test/cache.test.ts +406 -0
  232. package/test/cdn.test.ts +247 -0
  233. package/test/compute.test.ts +861 -0
  234. package/test/database.test.ts +523 -0
  235. package/test/deployment.test.ts +499 -0
  236. package/test/dns.test.ts +270 -0
  237. package/test/email.test.ts +439 -0
  238. package/test/filesystem.test.ts +382 -0
  239. package/test/integration.test.ts +350 -0
  240. package/test/messaging.test.ts +514 -0
  241. package/test/monitoring.test.ts +634 -0
  242. package/test/network.test.ts +425 -0
  243. package/test/permissions.test.ts +488 -0
  244. package/test/queue.test.ts +484 -0
  245. package/test/registry.test.ts +306 -0
  246. package/test/security.test.ts +462 -0
  247. package/test/storage.test.ts +463 -0
  248. package/test/template-validator.test.ts +559 -0
  249. package/test/workflow.test.ts +592 -0
  250. package/tsconfig.json +16 -0
  251. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,456 @@
1
+ /**
2
+ * Automated Secrets Rotation
3
+ * Automatic rotation for RDS credentials, API keys, and other secrets
4
+ */
5
+
6
+ export interface SecretRotation {
7
+ id: string
8
+ secretId: string
9
+ secretType: SecretType
10
+ rotationEnabled: boolean
11
+ rotationDays: number
12
+ rotationLambdaArn?: string
13
+ lastRotated?: Date
14
+ nextRotation?: Date
15
+ versionStages?: string[]
16
+ }
17
+
18
+ export type SecretType =
19
+ | 'rds_credentials'
20
+ | 'api_key'
21
+ | 'oauth_token'
22
+ | 'ssh_key'
23
+ | 'certificate'
24
+ | 'generic'
25
+
26
+ export interface RotationConfig {
27
+ automaticallyAfterDays: number
28
+ rotationLambda?: RotationLambda
29
+ requireMasterPassword?: boolean
30
+ excludeCharacters?: string
31
+ passwordLength?: number
32
+ }
33
+
34
+ export interface RotationLambda {
35
+ functionArn: string
36
+ functionName: string
37
+ runtime: string
38
+ handler: string
39
+ }
40
+
41
+ export interface RotationSchedule {
42
+ id: string
43
+ name: string
44
+ secrets: string[] // secret IDs
45
+ schedule: string // rate or cron expression
46
+ enabled: boolean
47
+ lastRun?: Date
48
+ nextRun?: Date
49
+ }
50
+
51
+ export interface RotationResult {
52
+ success: boolean
53
+ secretId: string
54
+ oldVersion: string
55
+ newVersion: string
56
+ rotatedAt: Date
57
+ error?: string
58
+ }
59
+
60
+ export interface RDSRotationConfig {
61
+ secretArn: string
62
+ databaseIdentifier: string
63
+ engine: 'postgres' | 'mysql' | 'sqlserver' | 'oracle'
64
+ masterSecretArn?: string
65
+ superuserSecretArn?: string
66
+ }
67
+
68
+ /**
69
+ * Secrets rotation manager
70
+ */
71
+ export class SecretsRotationManager {
72
+ private rotations: Map<string, SecretRotation> = new Map()
73
+ private schedules: Map<string, RotationSchedule> = new Map()
74
+ private rotationCounter = 0
75
+ private scheduleCounter = 0
76
+
77
+ /**
78
+ * Create secret rotation
79
+ */
80
+ createRotation(rotation: Omit<SecretRotation, 'id'>): SecretRotation {
81
+ const id = `rotation-${Date.now()}-${this.rotationCounter++}`
82
+
83
+ const secretRotation: SecretRotation = {
84
+ id,
85
+ ...rotation,
86
+ }
87
+
88
+ this.rotations.set(id, secretRotation)
89
+
90
+ return secretRotation
91
+ }
92
+
93
+ /**
94
+ * Enable RDS credentials rotation
95
+ */
96
+ enableRDSRotation(options: {
97
+ secretId: string
98
+ databaseIdentifier: string
99
+ engine: 'postgres' | 'mysql' | 'sqlserver' | 'oracle'
100
+ rotationDays?: number
101
+ masterSecretArn?: string
102
+ }): SecretRotation {
103
+ const rotation = this.createRotation({
104
+ secretId: options.secretId,
105
+ secretType: 'rds_credentials',
106
+ rotationEnabled: true,
107
+ rotationDays: options.rotationDays || 30,
108
+ rotationLambdaArn: this.generateRDSRotationLambdaArn(options.engine),
109
+ })
110
+
111
+ // Calculate next rotation
112
+ rotation.nextRotation = new Date(Date.now() + rotation.rotationDays * 24 * 60 * 60 * 1000)
113
+
114
+ return rotation
115
+ }
116
+
117
+ /**
118
+ * Enable API key rotation
119
+ */
120
+ enableAPIKeyRotation(options: {
121
+ secretId: string
122
+ rotationDays?: number
123
+ rotationLambdaArn?: string
124
+ }): SecretRotation {
125
+ return this.createRotation({
126
+ secretId: options.secretId,
127
+ secretType: 'api_key',
128
+ rotationEnabled: true,
129
+ rotationDays: options.rotationDays || 90,
130
+ rotationLambdaArn: options.rotationLambdaArn,
131
+ })
132
+ }
133
+
134
+ /**
135
+ * Enable OAuth token rotation
136
+ */
137
+ enableOAuthRotation(options: {
138
+ secretId: string
139
+ rotationDays?: number
140
+ rotationLambdaArn: string
141
+ }): SecretRotation {
142
+ return this.createRotation({
143
+ secretId: options.secretId,
144
+ secretType: 'oauth_token',
145
+ rotationEnabled: true,
146
+ rotationDays: options.rotationDays || 60,
147
+ rotationLambdaArn: options.rotationLambdaArn,
148
+ })
149
+ }
150
+
151
+ /**
152
+ * Enable SSH key rotation
153
+ */
154
+ enableSSHKeyRotation(options: {
155
+ secretId: string
156
+ rotationDays?: number
157
+ rotationLambdaArn: string
158
+ }): SecretRotation {
159
+ return this.createRotation({
160
+ secretId: options.secretId,
161
+ secretType: 'ssh_key',
162
+ rotationEnabled: true,
163
+ rotationDays: options.rotationDays || 180,
164
+ rotationLambdaArn: options.rotationLambdaArn,
165
+ })
166
+ }
167
+
168
+ /**
169
+ * Create rotation schedule
170
+ */
171
+ createSchedule(schedule: Omit<RotationSchedule, 'id'>): RotationSchedule {
172
+ const id = `schedule-${Date.now()}-${this.scheduleCounter++}`
173
+
174
+ const rotationSchedule: RotationSchedule = {
175
+ id,
176
+ ...schedule,
177
+ }
178
+
179
+ this.schedules.set(id, rotationSchedule)
180
+
181
+ return rotationSchedule
182
+ }
183
+
184
+ /**
185
+ * Execute rotation
186
+ */
187
+ async executeRotation(rotationId: string): Promise<RotationResult> {
188
+ const rotation = this.rotations.get(rotationId)
189
+
190
+ if (!rotation) {
191
+ throw new Error(`Rotation not found: ${rotationId}`)
192
+ }
193
+
194
+ console.log(`\nExecuting rotation for secret: ${rotation.secretId}`)
195
+ console.log(`Secret type: ${rotation.secretType}`)
196
+ console.log(`Rotation interval: ${rotation.rotationDays} days`)
197
+
198
+ try {
199
+ // Simulate rotation steps
200
+ console.log('\nRotation steps:')
201
+ console.log('1. Creating new secret version...')
202
+ const newVersion = `v${Date.now()}`
203
+
204
+ console.log('2. Testing new credentials...')
205
+ // Test logic would go here
206
+
207
+ console.log('3. Updating application references...')
208
+ // Update logic would go here
209
+
210
+ console.log('4. Marking previous version as deprecated...')
211
+ const oldVersion = rotation.versionStages?.[0] || 'v1'
212
+
213
+ console.log('5. Finalizing rotation...')
214
+ rotation.lastRotated = new Date()
215
+ rotation.nextRotation = new Date(
216
+ Date.now() + rotation.rotationDays * 24 * 60 * 60 * 1000
217
+ )
218
+
219
+ console.log('\n✓ Rotation completed successfully')
220
+ console.log(` New version: ${newVersion}`)
221
+ console.log(` Next rotation: ${rotation.nextRotation.toISOString()}`)
222
+
223
+ return {
224
+ success: true,
225
+ secretId: rotation.secretId,
226
+ oldVersion,
227
+ newVersion,
228
+ rotatedAt: new Date(),
229
+ }
230
+ } catch (error) {
231
+ console.error('\n✗ Rotation failed:', error)
232
+
233
+ return {
234
+ success: false,
235
+ secretId: rotation.secretId,
236
+ oldVersion: 'unknown',
237
+ newVersion: 'unknown',
238
+ rotatedAt: new Date(),
239
+ error: error instanceof Error ? error.message : String(error),
240
+ }
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Check if rotation needed
246
+ */
247
+ needsRotation(rotationId: string): boolean {
248
+ const rotation = this.rotations.get(rotationId)
249
+
250
+ if (!rotation || !rotation.rotationEnabled) {
251
+ return false
252
+ }
253
+
254
+ if (!rotation.lastRotated) {
255
+ return true
256
+ }
257
+
258
+ const daysSinceRotation =
259
+ (Date.now() - rotation.lastRotated.getTime()) / (1000 * 60 * 60 * 24)
260
+
261
+ return daysSinceRotation >= rotation.rotationDays
262
+ }
263
+
264
+ /**
265
+ * Get secrets needing rotation
266
+ */
267
+ getSecretsNeedingRotation(): SecretRotation[] {
268
+ return Array.from(this.rotations.values()).filter(rotation =>
269
+ this.needsRotation(rotation.id)
270
+ )
271
+ }
272
+
273
+ /**
274
+ * Generate RDS rotation Lambda ARN
275
+ */
276
+ private generateRDSRotationLambdaArn(engine: string): string {
277
+ const functionMap: Record<string, string> = {
278
+ postgres: 'SecretsManagerRDSPostgreSQLRotationSingleUser',
279
+ mysql: 'SecretsManagerRDSMySQLRotationSingleUser',
280
+ sqlserver: 'SecretsManagerRDSSQLServerRotationSingleUser',
281
+ oracle: 'SecretsManagerRDSOracleRotationSingleUser',
282
+ }
283
+
284
+ const functionName = functionMap[engine] || functionMap.postgres
285
+
286
+ return `arn:aws:lambda:us-east-1:123456789012:function:${functionName}`
287
+ }
288
+
289
+ /**
290
+ * Get rotation
291
+ */
292
+ getRotation(id: string): SecretRotation | undefined {
293
+ return this.rotations.get(id)
294
+ }
295
+
296
+ /**
297
+ * List rotations
298
+ */
299
+ listRotations(): SecretRotation[] {
300
+ return Array.from(this.rotations.values())
301
+ }
302
+
303
+ /**
304
+ * Get schedule
305
+ */
306
+ getSchedule(id: string): RotationSchedule | undefined {
307
+ return this.schedules.get(id)
308
+ }
309
+
310
+ /**
311
+ * List schedules
312
+ */
313
+ listSchedules(): RotationSchedule[] {
314
+ return Array.from(this.schedules.values())
315
+ }
316
+
317
+ /**
318
+ * Generate CloudFormation for rotation
319
+ */
320
+ generateRotationCF(rotation: SecretRotation): any {
321
+ return {
322
+ RotationEnabled: rotation.rotationEnabled,
323
+ RotationRules: {
324
+ AutomaticallyAfterDays: rotation.rotationDays,
325
+ },
326
+ ...(rotation.rotationLambdaArn && {
327
+ RotationLambdaARN: rotation.rotationLambdaArn,
328
+ }),
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Generate CloudFormation for rotation Lambda
334
+ */
335
+ generateRotationLambdaCF(options: {
336
+ functionName: string
337
+ secretType: SecretType
338
+ vpcConfig?: {
339
+ subnetIds: string[]
340
+ securityGroupIds: string[]
341
+ }
342
+ }): any {
343
+ return {
344
+ Type: 'AWS::Lambda::Function',
345
+ Properties: {
346
+ FunctionName: options.functionName,
347
+ Runtime: 'python3.11',
348
+ Handler: 'lambda_function.lambda_handler',
349
+ Role: { 'Fn::GetAtt': ['RotationLambdaRole', 'Arn'] },
350
+ Timeout: 30,
351
+ Environment: {
352
+ Variables: {
353
+ SECRETS_MANAGER_ENDPOINT: 'https://secretsmanager.us-east-1.amazonaws.com',
354
+ },
355
+ },
356
+ ...(options.vpcConfig && {
357
+ VpcConfig: {
358
+ SubnetIds: options.vpcConfig.subnetIds,
359
+ SecurityGroupIds: options.vpcConfig.securityGroupIds,
360
+ },
361
+ }),
362
+ },
363
+ }
364
+ }
365
+
366
+ /**
367
+ * Generate CloudFormation for rotation Lambda role
368
+ */
369
+ generateRotationLambdaRoleCF(): any {
370
+ return {
371
+ Type: 'AWS::IAM::Role',
372
+ Properties: {
373
+ AssumeRolePolicyDocument: {
374
+ Version: '2012-10-17',
375
+ Statement: [
376
+ {
377
+ Effect: 'Allow',
378
+ Principal: {
379
+ Service: 'lambda.amazonaws.com',
380
+ },
381
+ Action: 'sts:AssumeRole',
382
+ },
383
+ ],
384
+ },
385
+ ManagedPolicyArns: [
386
+ 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole',
387
+ 'arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole',
388
+ ],
389
+ Policies: [
390
+ {
391
+ PolicyName: 'SecretsRotationPolicy',
392
+ PolicyDocument: {
393
+ Version: '2012-10-17',
394
+ Statement: [
395
+ {
396
+ Effect: 'Allow',
397
+ Action: [
398
+ 'secretsmanager:DescribeSecret',
399
+ 'secretsmanager:GetSecretValue',
400
+ 'secretsmanager:PutSecretValue',
401
+ 'secretsmanager:UpdateSecretVersionStage',
402
+ ],
403
+ Resource: '*',
404
+ },
405
+ {
406
+ Effect: 'Allow',
407
+ Action: ['secretsmanager:GetRandomPassword'],
408
+ Resource: '*',
409
+ },
410
+ ],
411
+ },
412
+ },
413
+ ],
414
+ },
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Generate EventBridge rule for rotation schedule
420
+ */
421
+ generateRotationScheduleCF(schedule: RotationSchedule): any {
422
+ return {
423
+ Type: 'AWS::Events::Rule',
424
+ Properties: {
425
+ Name: schedule.name,
426
+ Description: `Rotation schedule for ${schedule.secrets.length} secrets`,
427
+ ScheduleExpression: schedule.schedule,
428
+ State: schedule.enabled ? 'ENABLED' : 'DISABLED',
429
+ Targets: [
430
+ {
431
+ Arn: { 'Fn::GetAtt': ['RotationStateMachine', 'Arn'] },
432
+ RoleArn: { 'Fn::GetAtt': ['EventBridgeRotationRole', 'Arn'] },
433
+ Input: JSON.stringify({
434
+ secrets: schedule.secrets,
435
+ }),
436
+ },
437
+ ],
438
+ },
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Clear all data
444
+ */
445
+ clear(): void {
446
+ this.rotations.clear()
447
+ this.schedules.clear()
448
+ this.rotationCounter = 0
449
+ this.scheduleCounter = 0
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Global secrets rotation manager instance
455
+ */
456
+ export const secretsRotationManager: SecretsRotationManager = new SecretsRotationManager()