Skip to content

Commit 40e03c6

Browse files
committed
Backups for s3
1 parent b676f7e commit 40e03c6

19 files changed

+206
-162
lines changed

backend/compact-connect/cdk.context.beta-example.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
"schedule": "cron(0 6 * * ? *)",
4343
"delete_after_days": 365,
4444
"cold_storage_after_days": 30
45+
},
46+
"document_storage": {
47+
"schedule": "cron(0 5 * * ? *)",
48+
"delete_after_days": 365,
49+
"cold_storage_after_days": 30
4550
}
4651
}
4752
}

backend/compact-connect/cdk.context.prod-example.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
"schedule": "cron(0 * ? * * *)",
4343
"delete_after_days": 365,
4444
"cold_storage_after_days": 30
45+
},
46+
"document_storage": {
47+
"schedule": "cron(0 5 * * ? *)",
48+
"delete_after_days": 365,
49+
"cold_storage_after_days": 30
4550
}
4651
}
4752
}

backend/compact-connect/cdk.context.sandbox-example.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
"schedule": "cron(0 6 * * ? *)",
4141
"delete_after_days": 365,
4242
"cold_storage_after_days": 30
43+
},
44+
"document_storage": {
45+
"schedule": "cron(0 5 * * ? *)",
46+
"delete_after_days": 365,
47+
"cold_storage_after_days": 30
4348
}
4449
}
4550
}

backend/compact-connect/cdk.context.test-example.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@
4343
"schedule": "cron(0 6 * * ? *)",
4444
"delete_after_days": 365,
4545
"cold_storage_after_days": 30
46+
},
47+
"document_storage": {
48+
"schedule": "cron(0 5 * * ? *)",
49+
"delete_after_days": 365,
50+
"cold_storage_after_days": 30
4651
}
4752
}
4853
}
Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from aws_cdk import Duration
2-
from aws_cdk.aws_events import Schedule
32
from aws_cdk.aws_backup import (
43
BackupPlan,
54
BackupPlanCopyActionProps,
@@ -9,22 +8,27 @@
98
BackupVault,
109
IBackupVault,
1110
)
12-
from aws_cdk.aws_dynamodb import ITable
11+
from aws_cdk.aws_events import Schedule
1312
from aws_cdk.aws_iam import IRole
1413
from constructs import Construct
1514

1615

17-
class TableBackupPlan(Construct):
16+
class CCBackupPlan(Construct):
1817
"""
19-
Common construct for creating backup plans for DynamoDB tables with cross-account replication.
18+
Common construct for creating backup plans for CompactConnect resources with cross-account replication.
19+
20+
This consolidated backup plan construct can be used for any AWS resource type that supports
21+
AWS Backup (DynamoDB tables, S3 buckets, etc.) by accepting a list of backup resources
22+
and a name prefix.
2023
"""
2124

2225
def __init__(
2326
self,
2427
scope: Construct,
2528
construct_id: str,
2629
*,
27-
table: ITable,
30+
backup_plan_name_prefix: str,
31+
backup_resources: list[BackupResource],
2832
backup_vault: BackupVault,
2933
backup_service_role: IRole,
3034
cross_account_backup_vault: IBackupVault,
@@ -36,32 +40,32 @@ def __init__(
3640
# Create backup plan
3741
self.backup_plan = BackupPlan(
3842
self,
39-
"BackupPlan",
40-
backup_plan_name=f"{table.table_name}-BackupPlan",
43+
'BackupPlan',
44+
backup_plan_name=f'{backup_plan_name_prefix}-BackupPlan',
4145
backup_plan_rules=[
4246
BackupPlanRule(
43-
rule_name=f"{table.table_name}-DailyBackup",
47+
rule_name=f'{backup_plan_name_prefix}-Backup',
4448
backup_vault=backup_vault,
45-
schedule_expression=Schedule.expression(backup_policy["schedule"]),
46-
delete_after=Duration.days(backup_policy["delete_after_days"]),
47-
move_to_cold_storage_after=Duration.days(backup_policy["cold_storage_after_days"]),
49+
schedule_expression=Schedule.expression(backup_policy['schedule']),
50+
delete_after=Duration.days(backup_policy['delete_after_days']),
51+
move_to_cold_storage_after=Duration.days(backup_policy['cold_storage_after_days']),
4852
copy_actions=[
4953
BackupPlanCopyActionProps(
5054
destination_backup_vault=cross_account_backup_vault,
51-
delete_after=Duration.days(backup_policy["delete_after_days"]),
52-
move_to_cold_storage_after=Duration.days(backup_policy["cold_storage_after_days"]),
55+
delete_after=Duration.days(backup_policy['delete_after_days']),
56+
move_to_cold_storage_after=Duration.days(backup_policy['cold_storage_after_days']),
5357
)
5458
],
5559
)
5660
],
5761
)
5862

59-
# Create backup selection to include the table
63+
# Create backup selection to include the resources
6064
self.backup_selection = BackupSelection(
6165
self,
62-
"BackupSelection",
66+
'BackupSelection',
6367
backup_plan=self.backup_plan,
64-
resources=[BackupResource.from_dynamo_db_table(table)],
65-
backup_selection_name=f"{table.table_name}-Selection",
68+
resources=backup_resources,
69+
backup_selection_name=f'{backup_plan_name_prefix}-Selection',
6670
role=backup_service_role,
67-
)
71+
)

backend/compact-connect/stacks/backup_infrastructure_stack.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ def _create_backup_event_rules(self) -> None:
413413
"""Create EventBridge rules for real-time backup failure events."""
414414

415415
# Backup job failure events
416-
backup_job_failure_rule = Rule(
416+
Rule(
417417
self,
418418
'BackupJobFailureRule',
419419
event_pattern=EventPattern(
@@ -427,7 +427,7 @@ def _create_backup_event_rules(self) -> None:
427427
)
428428

429429
# Copy job failure events
430-
copy_job_failure_rule = Rule(
430+
Rule(
431431
self,
432432
'CopyJobFailureRule',
433433
event_pattern=EventPattern(
@@ -441,7 +441,7 @@ def _create_backup_event_rules(self) -> None:
441441
)
442442

443443
# Recovery point partial/failed events
444-
recovery_point_issues_rule = Rule(
444+
Rule(
445445
self,
446446
'RecoveryPointIssuesRule',
447447
event_pattern=EventPattern(
@@ -458,7 +458,7 @@ def _create_operational_security_rules(self) -> None:
458458
"""Create EventBridge rules for operational security monitoring."""
459459

460460
# Manual backup deletion monitoring
461-
manual_deletion_rule = Rule(
461+
Rule(
462462
self,
463463
'ManualBackupDeletionRule',
464464
event_pattern=EventPattern(
@@ -473,7 +473,7 @@ def _create_operational_security_rules(self) -> None:
473473
)
474474

475475
# Backup vault modifications
476-
vault_modification_rule = Rule(
476+
Rule(
477477
self,
478478
'BackupVaultModificationRule',
479479
event_pattern=EventPattern(
@@ -487,7 +487,7 @@ def _create_operational_security_rules(self) -> None:
487487
)
488488

489489
# Backup plan modifications/deletions
490-
backup_plan_changes_rule = Rule(
490+
Rule(
491491
self,
492492
'BackupPlanChangesRule',
493493
event_pattern=EventPattern(
@@ -509,10 +509,13 @@ def _add_cdk_nag_suppressions(self) -> None:
509509
[
510510
{
511511
'id': 'HIPAA.Security-IAMNoInlinePolicy',
512-
'reason': 'CDK allows for granular permissions crafting that is attached to policies directly to each resource, '
513-
'by virtue of its Resource.grant_* methods. This approach results in an improvement in the principle '
514-
'of least privilege, because each resource has permissions specifically crafted for that resource '
515-
'and only allows exactly what it needs to do, rather than sharing more coarse managed policies.',
512+
'reason': (
513+
'CDK allows for granular permissions crafting that is attached to policies '
514+
'directly to each resource, by virtue of its Resource.grant_* methods. '
515+
'This approach results in an improvement in the principle of least privilege, '
516+
'because each resource has permissions specifically crafted for that resource '
517+
'and only allows exactly what it needs to do, rather than sharing more coarse managed policies.'
518+
),
516519
},
517520
],
518521
)
@@ -524,8 +527,11 @@ def _add_cdk_nag_suppressions(self) -> None:
524527
[
525528
{
526529
'id': 'AwsSolutions-IAM4',
527-
'reason': 'AWS Backup service requires these standard AWS managed policies for backup and restore operations. '
528-
'These are the minimal required permissions for backup service functionality.',
530+
'reason': (
531+
'AWS Backup service requires these standard AWS managed policies for backup '
532+
'and restore operations. These are the minimal required permissions for '
533+
'backup service functionality.'
534+
),
529535
},
530536
],
531537
)
@@ -535,8 +541,11 @@ def _add_cdk_nag_suppressions(self) -> None:
535541
[
536542
{
537543
'id': 'AwsSolutions-IAM4',
538-
'reason': 'AWS Backup service requires these standard AWS managed policies for backup and restore operations. '
539-
'SSN backup role uses the same base policies with additional customer-managed security restrictions.',
544+
'reason': (
545+
'AWS Backup service requires these standard AWS managed policies for backup '
546+
'and restore operations. SSN backup role uses the same base policies with '
547+
'additional customer-managed security restrictions.'
548+
),
540549
},
541550
],
542551
)

backend/compact-connect/stacks/persistent_stack/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from cdk_nag import NagSuppressions
1111
from common_constructs.access_logs_bucket import AccessLogsBucket
1212
from common_constructs.alarm_topic import AlarmTopic
13-
from common_constructs.backup_plan import TableBackupPlan
1413
from common_constructs.data_migration import DataMigration
1514
from common_constructs.frontend_app_config_utility import PersistentStackFrontendAppConfigUtility
1615
from common_constructs.nodejs_function import NodejsFunction
@@ -359,6 +358,8 @@ def _add_data_resources(
359358
encryption_key=self.shared_encryption_key,
360359
provider_table=self.provider_table,
361360
removal_policy=removal_policy,
361+
backup_infrastructure_stack=backup_infrastructure_stack,
362+
environment_context=self.environment_context,
362363
)
363364

364365
def _add_migrations(self):

backend/compact-connect/stacks/persistent_stack/compact_configuration_table.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from aws_cdk import RemovalPolicy
2+
from aws_cdk.aws_backup import BackupResource
23
from aws_cdk.aws_dynamodb import Attribute, AttributeType, BillingMode, Table, TableEncryption
34
from aws_cdk.aws_kms import IKey
4-
from common_constructs.backup_plan import TableBackupPlan
5+
from common_constructs.backup_plan import CCBackupPlan
56
from constructs import Construct
67

8+
from stacks.backup_infrastructure_stack import BackupInfrastructureStack
9+
710

811
class CompactConfigurationTable(Table):
912
"""DynamoDB table to house compact configuration data"""
@@ -15,7 +18,7 @@ def __init__(
1518
*,
1619
encryption_key: IKey,
1720
removal_policy: RemovalPolicy,
18-
backup_infrastructure_stack: 'BackupInfrastructureStack',
21+
backup_infrastructure_stack: BackupInfrastructureStack,
1922
environment_context: dict,
2023
**kwargs,
2124
):
@@ -33,10 +36,11 @@ def __init__(
3336
)
3437

3538
# Set up backup plan
36-
self.backup_plan = TableBackupPlan(
39+
self.backup_plan = CCBackupPlan(
3740
self,
3841
'CompactConfigurationTableBackup',
39-
table=self,
42+
backup_plan_name_prefix=self.table_name,
43+
backup_resources=[BackupResource.from_dynamo_db_table(self)],
4044
backup_vault=backup_infrastructure_stack.local_backup_vault,
4145
backup_service_role=backup_infrastructure_stack.backup_service_role,
4246
cross_account_backup_vault=backup_infrastructure_stack.cross_account_backup_vault,

backend/compact-connect/stacks/persistent_stack/data_event_table.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44

55
from aws_cdk import Duration, RemovalPolicy
6+
from aws_cdk.aws_backup import BackupResource
67
from aws_cdk.aws_cloudwatch import Alarm, ComparisonOperator, Metric, Stats, TreatMissingData
78
from aws_cdk.aws_cloudwatch_actions import SnsAction
89
from aws_cdk.aws_dynamodb import Attribute, AttributeType, BillingMode, Table, TableEncryption
@@ -11,12 +12,13 @@
1112
from aws_cdk.aws_kms import IKey
1213
from aws_cdk.aws_sns import ITopic
1314
from cdk_nag import NagSuppressions
14-
from common_constructs.backup_plan import TableBackupPlan
15+
from common_constructs.backup_plan import CCBackupPlan
1516
from common_constructs.python_function import PythonFunction
1617
from common_constructs.queued_lambda_processor import QueuedLambdaProcessor
1718
from constructs import Construct
1819

1920
from stacks import persistent_stack as ps
21+
from stacks.backup_infrastructure_stack import BackupInfrastructureStack
2022

2123

2224
class DataEventTable(Table):
@@ -132,10 +134,11 @@ def __init__(
132134
).add_alarm_action(SnsAction(stack.alarm_topic))
133135

134136
# Set up backup plan
135-
self.backup_plan = TableBackupPlan(
137+
self.backup_plan = CCBackupPlan(
136138
self,
137139
'DataEventTableBackup',
138-
table=self,
140+
backup_plan_name_prefix=self.table_name,
141+
backup_resources=[BackupResource.from_dynamo_db_table(self)],
139142
backup_vault=backup_infrastructure_stack.local_backup_vault,
140143
backup_service_role=backup_infrastructure_stack.backup_service_role,
141144
cross_account_backup_vault=backup_infrastructure_stack.cross_account_backup_vault,

backend/compact-connect/stacks/persistent_stack/provider_table.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from aws_cdk import RemovalPolicy
2+
from aws_cdk.aws_backup import BackupResource
23
from aws_cdk.aws_dynamodb import Attribute, AttributeType, BillingMode, ProjectionType, Table, TableEncryption
34
from aws_cdk.aws_kms import IKey
4-
from common_constructs.backup_plan import TableBackupPlan
5+
from common_constructs.backup_plan import CCBackupPlan
56
from constructs import Construct
67

78
from stacks.backup_infrastructure_stack import BackupInfrastructureStack
@@ -73,10 +74,11 @@ def __init__(
7374
],
7475
)
7576
# Set up backup plan
76-
self.backup_plan = TableBackupPlan(
77+
self.backup_plan = CCBackupPlan(
7778
self,
7879
'ProviderTableBackup',
79-
table=self,
80+
backup_plan_name_prefix=self.table_name,
81+
backup_resources=[BackupResource.from_dynamo_db_table(self)],
8082
backup_vault=backup_infrastructure_stack.local_backup_vault,
8183
backup_service_role=backup_infrastructure_stack.backup_service_role,
8284
cross_account_backup_vault=backup_infrastructure_stack.cross_account_backup_vault,

0 commit comments

Comments
 (0)