cdk-factory 0.16.15__py3-none-any.whl → 0.20.0__py3-none-any.whl

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.

Potentially problematic release.


This version of cdk-factory might be problematic. Click here for more details.

Files changed (66) hide show
  1. cdk_factory/configurations/base_config.py +23 -24
  2. cdk_factory/configurations/cdk_config.py +1 -1
  3. cdk_factory/configurations/deployment.py +12 -0
  4. cdk_factory/configurations/devops.py +1 -1
  5. cdk_factory/configurations/resources/acm.py +9 -2
  6. cdk_factory/configurations/resources/auto_scaling.py +7 -5
  7. cdk_factory/configurations/resources/cloudfront.py +7 -2
  8. cdk_factory/configurations/resources/ecr.py +1 -1
  9. cdk_factory/configurations/resources/ecs_cluster.py +12 -5
  10. cdk_factory/configurations/resources/ecs_service.py +30 -3
  11. cdk_factory/configurations/resources/lambda_edge.py +18 -4
  12. cdk_factory/configurations/resources/load_balancer.py +8 -9
  13. cdk_factory/configurations/resources/monitoring.py +8 -3
  14. cdk_factory/configurations/resources/rds.py +8 -9
  15. cdk_factory/configurations/resources/route53.py +5 -0
  16. cdk_factory/configurations/resources/rum.py +7 -2
  17. cdk_factory/configurations/resources/s3.py +10 -2
  18. cdk_factory/configurations/resources/security_group_full_stack.py +7 -8
  19. cdk_factory/configurations/resources/vpc.py +19 -0
  20. cdk_factory/configurations/workload.py +32 -2
  21. cdk_factory/constructs/cloudfront/cloudfront_distribution_construct.py +1 -1
  22. cdk_factory/constructs/ecr/ecr_construct.py +9 -2
  23. cdk_factory/constructs/lambdas/policies/policy_docs.py +4 -4
  24. cdk_factory/interfaces/istack.py +4 -4
  25. cdk_factory/interfaces/networked_stack_mixin.py +6 -6
  26. cdk_factory/interfaces/standardized_ssm_mixin.py +684 -0
  27. cdk_factory/interfaces/vpc_provider_mixin.py +64 -33
  28. cdk_factory/lambdas/edge/ip_gate/handler.py +42 -40
  29. cdk_factory/pipeline/pipeline_factory.py +3 -3
  30. cdk_factory/stack_library/__init__.py +3 -2
  31. cdk_factory/stack_library/acm/acm_stack.py +7 -17
  32. cdk_factory/stack_library/api_gateway/api_gateway_stack.py +84 -59
  33. cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py +454 -537
  34. cdk_factory/stack_library/cloudfront/cloudfront_stack.py +76 -22
  35. cdk_factory/stack_library/code_artifact/code_artifact_stack.py +5 -27
  36. cdk_factory/stack_library/cognito/cognito_stack.py +152 -92
  37. cdk_factory/stack_library/dynamodb/dynamodb_stack.py +19 -15
  38. cdk_factory/stack_library/ecr/ecr_stack.py +2 -2
  39. cdk_factory/stack_library/ecs/__init__.py +1 -3
  40. cdk_factory/stack_library/ecs/ecs_cluster_stack.py +159 -75
  41. cdk_factory/stack_library/ecs/ecs_service_stack.py +59 -52
  42. cdk_factory/stack_library/lambda_edge/EDGE_LOG_RETENTION_TODO.md +226 -0
  43. cdk_factory/stack_library/lambda_edge/LAMBDA_EDGE_LOG_RETENTION_BLOG.md +215 -0
  44. cdk_factory/stack_library/lambda_edge/lambda_edge_stack.py +240 -83
  45. cdk_factory/stack_library/load_balancer/load_balancer_stack.py +139 -212
  46. cdk_factory/stack_library/rds/rds_stack.py +74 -98
  47. cdk_factory/stack_library/route53/route53_stack.py +246 -40
  48. cdk_factory/stack_library/rum/rum_stack.py +108 -91
  49. cdk_factory/stack_library/security_group/security_group_full_stack.py +10 -53
  50. cdk_factory/stack_library/security_group/security_group_stack.py +12 -19
  51. cdk_factory/stack_library/simple_queue_service/sqs_stack.py +1 -34
  52. cdk_factory/stack_library/stack_base.py +5 -0
  53. cdk_factory/stack_library/vpc/vpc_stack.py +171 -130
  54. cdk_factory/stack_library/websites/static_website_stack.py +7 -3
  55. cdk_factory/utilities/api_gateway_integration_utility.py +24 -16
  56. cdk_factory/utilities/environment_services.py +5 -5
  57. cdk_factory/utilities/json_loading_utility.py +1 -1
  58. cdk_factory/validation/config_validator.py +483 -0
  59. cdk_factory/version.py +1 -1
  60. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/METADATA +1 -1
  61. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/RECORD +64 -62
  62. cdk_factory/interfaces/enhanced_ssm_parameter_mixin.py +0 -321
  63. cdk_factory/interfaces/ssm_parameter_mixin.py +0 -454
  64. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/WHEEL +0 -0
  65. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/entry_points.txt +0 -0
  66. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/licenses/LICENSE +0 -0
@@ -17,7 +17,7 @@ from cdk_factory.configurations.deployment import DeploymentConfig
17
17
  from cdk_factory.configurations.resources.cognito import CognitoConfig
18
18
  from cdk_factory.configurations.stack import StackConfig
19
19
  from cdk_factory.interfaces.istack import IStack
20
- from cdk_factory.interfaces.enhanced_ssm_parameter_mixin import EnhancedSsmParameterMixin
20
+ from cdk_factory.interfaces.standardized_ssm_mixin import StandardizedSsmMixin
21
21
  from cdk_factory.stack.stack_module_registry import register_stack
22
22
  from cdk_factory.workload.workload_factory import WorkloadConfig
23
23
 
@@ -26,7 +26,7 @@ logger = Logger(__name__)
26
26
 
27
27
  @register_stack("cognito_library_module")
28
28
  @register_stack("cognito_stack")
29
- class CognitoStack(IStack, EnhancedSsmParameterMixin):
29
+ class CognitoStack(IStack, StandardizedSsmMixin):
30
30
  """
31
31
  Cognito Stack - Creates a Cognito User Pool with configurable settings.
32
32
  """
@@ -40,6 +40,14 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
40
40
  self.user_pool: cognito.UserPool | None = None
41
41
  self.app_clients: dict = {} # Store created app clients by name
42
42
 
43
+ def _build_resource_name(self, name: str) -> str:
44
+ """Build resource name using deployment configuration"""
45
+ if self.deployment:
46
+ return self.deployment.build_resource_name(name)
47
+ else:
48
+ # Fallback naming pattern
49
+ return f"{self.cognito_config.user_pool_name or 'cognito'}-{name}"
50
+
43
51
  def build(
44
52
  self,
45
53
  stack_config: StackConfig,
@@ -50,10 +58,10 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
50
58
  self.stack_config = stack_config
51
59
  self.deployment = deployment
52
60
  self.cognito_config = CognitoConfig(stack_config.dictionary.get("cognito", {}))
53
-
61
+
54
62
  # Create user pool with configuration
55
63
  self._create_user_pool_with_config()
56
-
64
+
57
65
  # Create app clients if configured
58
66
  if self.cognito_config.app_clients:
59
67
  self._create_app_clients()
@@ -151,7 +159,7 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
151
159
 
152
160
  self.user_pool = cognito.UserPool(
153
161
  self,
154
- id=self.deployment.build_resource_name(
162
+ id=self._build_resource_name(
155
163
  self.cognito_config.user_pool_name
156
164
  or self.cognito_config.user_pool_id
157
165
  or "user-pool"
@@ -166,21 +174,21 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
166
174
  """Create app clients for the user pool based on configuration"""
167
175
  if not self.user_pool:
168
176
  raise ValueError("User pool must be created before app clients")
169
-
177
+
170
178
  for client_config in self.cognito_config.app_clients:
171
179
  client_name = client_config.get("name")
172
180
  if not client_name:
173
181
  raise ValueError("App client name is required")
174
-
182
+
175
183
  # Build authentication flows
176
184
  auth_flows = self._build_auth_flows(client_config.get("auth_flows", {}))
177
-
185
+
178
186
  # Build OAuth settings
179
187
  oauth_settings = self._build_oauth_settings(client_config.get("oauth"))
180
-
188
+
181
189
  # Build token validity settings
182
190
  token_validity = self._build_token_validity(client_config)
183
-
191
+
184
192
  # Build app client kwargs
185
193
  client_kwargs = {
186
194
  "user_pool": self.user_pool,
@@ -188,68 +196,78 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
188
196
  "generate_secret": client_config.get("generate_secret", False),
189
197
  "auth_flows": auth_flows,
190
198
  "o_auth": oauth_settings,
191
- "prevent_user_existence_errors": client_config.get("prevent_user_existence_errors"),
192
- "enable_token_revocation": client_config.get("enable_token_revocation", True),
199
+ "prevent_user_existence_errors": client_config.get(
200
+ "prevent_user_existence_errors"
201
+ ),
202
+ "enable_token_revocation": client_config.get(
203
+ "enable_token_revocation", True
204
+ ),
193
205
  "access_token_validity": token_validity.get("access_token"),
194
206
  "id_token_validity": token_validity.get("id_token"),
195
207
  "refresh_token_validity": token_validity.get("refresh_token"),
196
- "read_attributes": self._build_attributes(client_config.get("read_attributes")),
197
- "write_attributes": self._build_attributes(client_config.get("write_attributes")),
208
+ "read_attributes": self._build_attributes(
209
+ client_config.get("read_attributes")
210
+ ),
211
+ "write_attributes": self._build_attributes(
212
+ client_config.get("write_attributes")
213
+ ),
198
214
  "supported_identity_providers": self._build_identity_providers(
199
215
  client_config.get("supported_identity_providers")
200
216
  ),
201
217
  }
202
-
218
+
203
219
  # Remove None values
204
220
  client_kwargs = {k: v for k, v in client_kwargs.items() if v is not None}
205
-
221
+
206
222
  # Create the app client
207
223
  app_client = cognito.UserPoolClient(
208
224
  self,
209
- id=self.deployment.build_resource_name(f"{client_name}-client"),
225
+ id=self._build_resource_name(f"{client_name}-client"),
210
226
  **client_kwargs,
211
227
  )
212
-
228
+
213
229
  # Store reference
214
230
  self.app_clients[client_name] = app_client
215
231
  logger.info(f"Created Cognito App Client: {client_name}")
216
-
232
+
217
233
  # Store client secret in Secrets Manager if generated
218
234
  if client_config.get("generate_secret", False):
219
235
  self._store_client_secret_in_secrets_manager(
220
236
  client_name, app_client, self.user_pool
221
237
  )
222
-
238
+
223
239
  def _build_auth_flows(self, auth_flows_config: dict) -> cognito.AuthFlow:
224
240
  """
225
241
  Build authentication flows from configuration.
226
-
242
+
227
243
  Note: CDK automatically adds ALLOW_REFRESH_TOKEN_AUTH to all app clients,
228
244
  which is required for token refresh functionality.
229
245
  """
230
246
  if not auth_flows_config:
231
247
  return None
232
-
248
+
233
249
  return cognito.AuthFlow(
234
250
  user_password=auth_flows_config.get("user_password", False),
235
251
  user_srp=auth_flows_config.get("user_srp", False),
236
252
  custom=auth_flows_config.get("custom", False),
237
253
  admin_user_password=auth_flows_config.get("admin_user_password", False),
238
254
  )
239
-
255
+
240
256
  def _build_oauth_settings(self, oauth_config: dict) -> cognito.OAuthSettings:
241
257
  """Build OAuth settings from configuration"""
242
258
  if not oauth_config:
243
259
  return None
244
-
260
+
245
261
  # Build OAuth flows
246
262
  flows_config = oauth_config.get("flows", {})
247
263
  flows = cognito.OAuthFlows(
248
- authorization_code_grant=flows_config.get("authorization_code_grant", False),
264
+ authorization_code_grant=flows_config.get(
265
+ "authorization_code_grant", False
266
+ ),
249
267
  implicit_code_grant=flows_config.get("implicit_code_grant", False),
250
268
  client_credentials=flows_config.get("client_credentials", False),
251
269
  )
252
-
270
+
253
271
  # Build OAuth scopes
254
272
  scopes = []
255
273
  scope_list = oauth_config.get("scopes", [])
@@ -267,18 +285,18 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
267
285
  else:
268
286
  # Custom scope
269
287
  scopes.append(cognito.OAuthScope.custom(scope))
270
-
288
+
271
289
  return cognito.OAuthSettings(
272
290
  flows=flows,
273
291
  scopes=scopes if scopes else None,
274
292
  callback_urls=oauth_config.get("callback_urls"),
275
293
  logout_urls=oauth_config.get("logout_urls"),
276
294
  )
277
-
295
+
278
296
  def _build_token_validity(self, client_config: dict) -> dict:
279
297
  """Build token validity settings from configuration"""
280
298
  result = {}
281
-
299
+
282
300
  # Access token validity
283
301
  if "access_token_validity" in client_config:
284
302
  validity = client_config["access_token_validity"]
@@ -288,7 +306,7 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
288
306
  result["access_token"] = cdk.Duration.hours(validity["hours"])
289
307
  elif "days" in validity:
290
308
  result["access_token"] = cdk.Duration.days(validity["days"])
291
-
309
+
292
310
  # ID token validity
293
311
  if "id_token_validity" in client_config:
294
312
  validity = client_config["id_token_validity"]
@@ -298,7 +316,7 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
298
316
  result["id_token"] = cdk.Duration.hours(validity["hours"])
299
317
  elif "days" in validity:
300
318
  result["id_token"] = cdk.Duration.days(validity["days"])
301
-
319
+
302
320
  # Refresh token validity
303
321
  if "refresh_token_validity" in client_config:
304
322
  validity = client_config["refresh_token_validity"]
@@ -308,51 +326,89 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
308
326
  result["refresh_token"] = cdk.Duration.hours(validity["hours"])
309
327
  elif "days" in validity:
310
328
  result["refresh_token"] = cdk.Duration.days(validity["days"])
311
-
329
+
312
330
  return result
313
-
331
+
314
332
  def _build_attributes(self, attribute_list: list) -> cognito.ClientAttributes:
315
333
  """Build client attributes from configuration"""
316
334
  if not attribute_list:
317
335
  return None
318
-
336
+
319
337
  # Standard attributes mapping
320
338
  standard_attrs = {
321
- "address": lambda: cognito.ClientAttributes().with_standard_attributes(address=True),
322
- "birthdate": lambda: cognito.ClientAttributes().with_standard_attributes(birthdate=True),
323
- "email": lambda: cognito.ClientAttributes().with_standard_attributes(email=True),
324
- "email_verified": lambda: cognito.ClientAttributes().with_standard_attributes(email_verified=True),
325
- "family_name": lambda: cognito.ClientAttributes().with_standard_attributes(family_name=True),
326
- "gender": lambda: cognito.ClientAttributes().with_standard_attributes(gender=True),
327
- "given_name": lambda: cognito.ClientAttributes().with_standard_attributes(given_name=True),
328
- "locale": lambda: cognito.ClientAttributes().with_standard_attributes(locale=True),
329
- "middle_name": lambda: cognito.ClientAttributes().with_standard_attributes(middle_name=True),
330
- "name": lambda: cognito.ClientAttributes().with_standard_attributes(fullname=True),
331
- "nickname": lambda: cognito.ClientAttributes().with_standard_attributes(nickname=True),
332
- "phone_number": lambda: cognito.ClientAttributes().with_standard_attributes(phone_number=True),
333
- "phone_number_verified": lambda: cognito.ClientAttributes().with_standard_attributes(phone_number_verified=True),
334
- "picture": lambda: cognito.ClientAttributes().with_standard_attributes(picture=True),
335
- "preferred_username": lambda: cognito.ClientAttributes().with_standard_attributes(preferred_username=True),
336
- "profile": lambda: cognito.ClientAttributes().with_standard_attributes(profile=True),
337
- "timezone": lambda: cognito.ClientAttributes().with_standard_attributes(timezone=True),
338
- "updated_at": lambda: cognito.ClientAttributes().with_standard_attributes(last_update_time=True),
339
- "website": lambda: cognito.ClientAttributes().with_standard_attributes(website=True),
339
+ "address": lambda: cognito.ClientAttributes().with_standard_attributes(
340
+ address=True
341
+ ),
342
+ "birthdate": lambda: cognito.ClientAttributes().with_standard_attributes(
343
+ birthdate=True
344
+ ),
345
+ "email": lambda: cognito.ClientAttributes().with_standard_attributes(
346
+ email=True
347
+ ),
348
+ "email_verified": lambda: cognito.ClientAttributes().with_standard_attributes(
349
+ email_verified=True
350
+ ),
351
+ "family_name": lambda: cognito.ClientAttributes().with_standard_attributes(
352
+ family_name=True
353
+ ),
354
+ "gender": lambda: cognito.ClientAttributes().with_standard_attributes(
355
+ gender=True
356
+ ),
357
+ "given_name": lambda: cognito.ClientAttributes().with_standard_attributes(
358
+ given_name=True
359
+ ),
360
+ "locale": lambda: cognito.ClientAttributes().with_standard_attributes(
361
+ locale=True
362
+ ),
363
+ "middle_name": lambda: cognito.ClientAttributes().with_standard_attributes(
364
+ middle_name=True
365
+ ),
366
+ "name": lambda: cognito.ClientAttributes().with_standard_attributes(
367
+ fullname=True
368
+ ),
369
+ "nickname": lambda: cognito.ClientAttributes().with_standard_attributes(
370
+ nickname=True
371
+ ),
372
+ "phone_number": lambda: cognito.ClientAttributes().with_standard_attributes(
373
+ phone_number=True
374
+ ),
375
+ "phone_number_verified": lambda: cognito.ClientAttributes().with_standard_attributes(
376
+ phone_number_verified=True
377
+ ),
378
+ "picture": lambda: cognito.ClientAttributes().with_standard_attributes(
379
+ picture=True
380
+ ),
381
+ "preferred_username": lambda: cognito.ClientAttributes().with_standard_attributes(
382
+ preferred_username=True
383
+ ),
384
+ "profile": lambda: cognito.ClientAttributes().with_standard_attributes(
385
+ profile=True
386
+ ),
387
+ "timezone": lambda: cognito.ClientAttributes().with_standard_attributes(
388
+ timezone=True
389
+ ),
390
+ "updated_at": lambda: cognito.ClientAttributes().with_standard_attributes(
391
+ last_update_time=True
392
+ ),
393
+ "website": lambda: cognito.ClientAttributes().with_standard_attributes(
394
+ website=True
395
+ ),
340
396
  }
341
-
397
+
342
398
  # Start with empty attributes
343
399
  attrs = cognito.ClientAttributes()
344
-
400
+
345
401
  # Build standard attributes
346
402
  standard_dict = {}
347
403
  custom_list = []
348
-
404
+
349
405
  for attr in attribute_list:
350
406
  if attr in standard_attrs:
351
407
  standard_dict[attr] = True
352
408
  else:
353
409
  # Custom attribute
354
410
  custom_list.append(attr)
355
-
411
+
356
412
  # Apply standard attributes if any
357
413
  if standard_dict:
358
414
  # Map attribute names to CDK parameter names
@@ -377,22 +433,22 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
377
433
  "updated_at": "last_update_time",
378
434
  "website": "website",
379
435
  }
380
-
436
+
381
437
  # Convert to CDK parameter names
382
438
  cdk_attrs = {attr_mapping.get(k, k): v for k, v in standard_dict.items()}
383
439
  attrs = attrs.with_standard_attributes(**cdk_attrs)
384
-
440
+
385
441
  # Add custom attributes if any
386
442
  if custom_list:
387
443
  attrs = attrs.with_custom_attributes(*custom_list)
388
-
444
+
389
445
  return attrs
390
-
446
+
391
447
  def _build_identity_providers(self, providers: list) -> list:
392
448
  """Build identity provider list from configuration"""
393
449
  if not providers:
394
450
  return None
395
-
451
+
396
452
  result = []
397
453
  for provider in providers:
398
454
  if isinstance(provider, str):
@@ -408,15 +464,17 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
408
464
  result.append(cognito.UserPoolClientIdentityProvider.APPLE)
409
465
  else:
410
466
  # Custom provider
411
- result.append(cognito.UserPoolClientIdentityProvider.custom(provider))
412
-
467
+ result.append(
468
+ cognito.UserPoolClientIdentityProvider.custom(provider)
469
+ )
470
+
413
471
  return result if result else None
414
472
 
415
473
  def _store_client_secret_in_secrets_manager(
416
474
  self,
417
475
  client_name: str,
418
476
  app_client: cognito.UserPoolClient,
419
- user_pool: cognito.UserPool
477
+ user_pool: cognito.UserPool,
420
478
  ):
421
479
  """
422
480
  Store Cognito app client secret in AWS Secrets Manager.
@@ -438,37 +496,37 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
438
496
  f"{client_name}-secret-{app_client.user_pool_client_id}"
439
497
  ),
440
498
  ),
441
- policy=cr.AwsCustomResourcePolicy.from_statements([
442
- iam.PolicyStatement(
443
- actions=["cognito-idp:DescribeUserPoolClient"],
444
- resources=[user_pool.user_pool_arn],
445
- )
446
- ]),
499
+ policy=cr.AwsCustomResourcePolicy.from_statements(
500
+ [
501
+ iam.PolicyStatement(
502
+ actions=["cognito-idp:DescribeUserPoolClient"],
503
+ resources=[user_pool.user_pool_arn],
504
+ )
505
+ ]
506
+ ),
447
507
  )
448
-
508
+
449
509
  # Get the client secret from the custom resource response
450
510
  client_secret = get_client_secret.get_response_field(
451
511
  "UserPoolClient.ClientSecret"
452
512
  )
453
-
513
+
454
514
  # Create secret in Secrets Manager
455
515
  secret = secretsmanager.Secret(
456
516
  self,
457
517
  f"{client_name}-client-secret",
458
- secret_name=self.deployment.build_resource_name(
518
+ secret_name=self._build_resource_name(
459
519
  f"cognito/{client_name}/client-secret"
460
520
  ),
461
521
  description=f"Cognito app client secret for {client_name}",
462
522
  secret_string_value=cdk.SecretValue.unsafe_plain_text(client_secret),
463
523
  )
464
-
524
+
465
525
  # Also store client ID in the same secret for convenience
466
526
  secret_with_metadata = secretsmanager.Secret(
467
527
  self,
468
528
  f"{client_name}-client-credentials",
469
- secret_name=self.deployment.build_resource_name(
470
- f"cognito/{client_name}/credentials"
471
- ),
529
+ secret_name=self._build_resource_name(f"cognito/{client_name}/credentials"),
472
530
  description=f"Cognito app client credentials for {client_name}",
473
531
  secret_object_value={
474
532
  "client_id": cdk.SecretValue.unsafe_plain_text(
@@ -480,18 +538,18 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
480
538
  ),
481
539
  },
482
540
  )
483
-
541
+
484
542
  logger.info(
485
543
  f"Stored client secret for {client_name} in Secrets Manager: "
486
544
  f"{secret_with_metadata.secret_name}"
487
545
  )
488
-
546
+
489
547
  # Export secret ARN to SSM for cross-stack reference
490
548
  if self.cognito_config.ssm.get("enabled"):
491
549
  safe_client_name = client_name.replace("-", "_").replace(" ", "_")
492
550
  org = self.cognito_config.ssm.get("organization", "default")
493
551
  env = self.cognito_config.ssm.get("environment", "dev")
494
-
552
+
495
553
  ssm.StringParameter(
496
554
  self,
497
555
  f"{client_name}-secret-arn-param",
@@ -502,37 +560,39 @@ class CognitoStack(IStack, EnhancedSsmParameterMixin):
502
560
 
503
561
  def _export_ssm_parameters(self, user_pool: cognito.UserPool):
504
562
  """Export Cognito resources to SSM using enhanced SSM parameter mixin"""
505
-
563
+
506
564
  # Setup enhanced SSM integration with proper resource type and name
507
565
  # Use "user-pool" as resource identifier for SSM paths, not the full pool name
508
-
509
- self.setup_enhanced_ssm_integration(
566
+
567
+ self.setup_ssm_integration(
510
568
  scope=self,
511
569
  config=self.stack_config.dictionary.get("cognito", {}),
512
570
  resource_type="cognito",
513
- resource_name="user-pool"
571
+ resource_name="user-pool",
514
572
  )
515
-
573
+
516
574
  # Prepare resource values for export
517
575
  resource_values = {
518
576
  "user_pool_id": user_pool.user_pool_id,
519
577
  "user_pool_name": self.cognito_config.user_pool_name,
520
578
  "user_pool_arn": user_pool.user_pool_arn,
521
579
  }
522
-
580
+
523
581
  # Add app client IDs to export
524
582
  for client_name, app_client in self.app_clients.items():
525
583
  # Export client ID
526
584
  safe_client_name = client_name.replace("-", "_").replace(" ", "_")
527
- resource_values[f"app_client_{safe_client_name}_id"] = app_client.user_pool_client_id
528
-
585
+ resource_values[f"app_client_{safe_client_name}_id"] = (
586
+ app_client.user_pool_client_id
587
+ )
588
+
529
589
  # Note: Client secrets cannot be exported via SSM as they are only available
530
590
  # at creation time and CDK doesn't expose them. Use AWS Secrets Manager
531
591
  # or retrieve via AWS Console/CLI if needed.
532
-
592
+
533
593
  # Use enhanced SSM parameter export
534
- exported_params = self.auto_export_resources(resource_values)
535
-
594
+ exported_params = self.export_ssm_parameters(resource_values)
595
+
536
596
  if exported_params:
537
597
  logger.info(f"Exported {len(exported_params)} Cognito parameters to SSM")
538
598
  else:
@@ -9,7 +9,7 @@ import aws_cdk as cdk
9
9
  from aws_cdk import aws_dynamodb as dynamodb
10
10
  from constructs import Construct
11
11
  from cdk_factory.interfaces.istack import IStack
12
- from cdk_factory.interfaces.enhanced_ssm_parameter_mixin import EnhancedSsmParameterMixin
12
+ from cdk_factory.interfaces.standardized_ssm_mixin import StandardizedSsmMixin
13
13
  from aws_lambda_powertools import Logger
14
14
  from cdk_factory.stack.stack_module_registry import register_stack
15
15
  from typing import List, Dict, Any, Optional
@@ -23,7 +23,7 @@ logger = Logger(service="DynamoDBStack")
23
23
 
24
24
  @register_stack("dynamodb_stack")
25
25
  @register_stack("dynamodb_library_module")
26
- class DynamoDBStack(IStack, EnhancedSsmParameterMixin):
26
+ class DynamoDBStack(IStack, StandardizedSsmMixin):
27
27
  """
28
28
  Reusable stack for AWS DynamoDB tables.
29
29
  Supports all major DynamoDB table parameters.
@@ -103,7 +103,7 @@ class DynamoDBStack(IStack, EnhancedSsmParameterMixin):
103
103
  self._configure_gsi()
104
104
  # add replicas if configured
105
105
  self._configure_replicas()
106
-
106
+
107
107
  # Export SSM parameters
108
108
  self._export_ssm_parameters()
109
109
 
@@ -148,34 +148,38 @@ class DynamoDBStack(IStack, EnhancedSsmParameterMixin):
148
148
  """Export DynamoDB resources to SSM using enhanced SSM parameter mixin"""
149
149
  if not self.table:
150
150
  return
151
-
151
+
152
152
  # Setup enhanced SSM integration with proper resource type and name
153
153
  # Use "app-table" as resource identifier for SSM paths, not the full table name
154
-
155
- self.setup_enhanced_ssm_integration(
154
+
155
+ self.setup_ssm_integration(
156
156
  scope=self,
157
157
  config=self.stack_config.dictionary.get("dynamodb", {}),
158
158
  resource_type="dynamodb",
159
- resource_name="app-table"
159
+ resource_name="app-table",
160
160
  )
161
-
161
+
162
162
  # Prepare resource values for export
163
163
  resource_values = {
164
164
  "table_name": self.table.table_name,
165
165
  "table_arn": self.table.table_arn,
166
- "table_stream_arn": self.table.table_stream_arn if hasattr(self.table, 'table_stream_arn') else None,
166
+ "table_stream_arn": (
167
+ self.table.table_stream_arn
168
+ if hasattr(self.table, "table_stream_arn")
169
+ else None
170
+ ),
167
171
  }
168
-
172
+
169
173
  # Add GSI names if available
170
- if hasattr(self, '_gsi_names') and self._gsi_names:
174
+ if hasattr(self, "_gsi_names") and self._gsi_names:
171
175
  resource_values["gsi_names"] = ",".join(self._gsi_names)
172
-
176
+
173
177
  # Filter out None values
174
178
  resource_values = {k: v for k, v in resource_values.items() if v is not None}
175
-
179
+
176
180
  # Use enhanced SSM parameter export
177
- exported_params = self.auto_export_resources(resource_values)
178
-
181
+ exported_params = self.export_ssm_parameters(resource_values)
182
+
179
183
  if exported_params:
180
184
  logger.info(f"Exported {len(exported_params)} DynamoDB parameters to SSM")
181
185
  else:
@@ -12,7 +12,7 @@ from cdk_factory.configurations.resources.ecr import ECRConfig
12
12
  from cdk_factory.configurations.stack import StackConfig
13
13
  from cdk_factory.constructs.ecr.ecr_construct import ECRConstruct
14
14
  from cdk_factory.interfaces.istack import IStack
15
- from cdk_factory.interfaces.enhanced_ssm_parameter_mixin import EnhancedSsmParameterMixin
15
+ from cdk_factory.interfaces.standardized_ssm_mixin import StandardizedSsmMixin
16
16
  from cdk_factory.stack.stack_module_registry import register_stack
17
17
  from cdk_factory.workload.workload_factory import WorkloadConfig
18
18
 
@@ -21,7 +21,7 @@ logger = Logger(__name__)
21
21
 
22
22
  @register_stack("ecr_library_module")
23
23
  @register_stack("ecr_stack")
24
- class ECRStack(IStack, EnhancedSsmParameterMixin):
24
+ class ECRStack(IStack, StandardizedSsmMixin):
25
25
  """
26
26
  A CloudFormation Stack for an ECR
27
27
 
@@ -6,9 +6,7 @@ ECS clusters, services, and related resources.
6
6
  """
7
7
 
8
8
  from .ecs_cluster_stack import EcsClusterStack
9
- from .ecs_service_stack import EcsServiceStack
10
9
 
11
10
  __all__ = [
12
- "EcsClusterStack",
13
- "EcsServiceStack"
11
+ "EcsClusterStack"
14
12
  ]