Guide · AWS Backup · Cross-Account · Organizations · Disaster Recovery
AWS Backup Cross-Account Copy — Multi-Region Disaster Recovery for MCP Servers
A backup in the same account as your production data provides no protection against account compromise, accidental bulk deletion, or an AWS regional outage. AWS Backup cross-account copy sends recovery points from your production vault to a vault in a separate AWS account — your DR (disaster recovery) account — optionally in a different region. Combined with AWS Organizations backup policies, you can enforce this cross-account copy for every member account in your organization without touching each account individually. This guide covers the prerequisites (trusted access, delegated admin, vault access policy), how to configure a copy action in your backup plan, how to restore from a cross-account recovery point, and how to enforce backup policies with Organizations SCPs.
TL;DR
Enable trusted access for AWS Backup in Organizations (aws organizations enable-aws-service-access --service-principal backup.amazonaws.com). Create a destination vault in your DR account and add a vault access policy that grants backup:CopyIntoBackupVault to the source account. Add a copy action to your backup plan rule pointing at the destination vault ARN. Cross-account copies use the KMS key of the destination vault — the destination vault's key must grant kms:Decrypt and kms:GenerateDataKey to the AWS Backup service principal in the source account.
Architecture: 3-account DR setup
The recommended setup uses three accounts within an AWS Organization:
- Production account — where MCP server resources (DynamoDB, EFS, RDS) run. Recovery points are created here and immediately copied to DR.
- DR account — receives cross-account copies. Has no running workloads — only backup vaults. Protected against accidental write access to production.
- Management account (optional) — applies Organizations backup policies as Service Control Policies to enforce minimum backup frequency across all member accounts.
Separating production and DR into different accounts means a credential compromise in production cannot delete the DR recovery points (the DR vault policy does not grant delete permissions to the production account's IAM roles).
Step 1: Enable trusted access and cross-account backup
Cross-account backup requires two one-time setup steps from the management account:
# Enable AWS Backup trusted access with Organizations
aws organizations enable-aws-service-access \
--service-principal backup.amazonaws.com
# Enable cross-account backup in AWS Backup (required separately)
aws backup update-global-settings \
--global-settings '{"isCrossAccountBackupEnabled": "true"}'
# Optionally designate a delegated admin account that can manage
# backup policies for the entire organization without using the management account
aws organizations register-delegated-administrator \
--account-id DR_ACCOUNT_ID \
--service-principal backup.amazonaws.com
The isCrossAccountBackupEnabled global setting must be true in both the source account and the destination account. If the DR account has never had a user enable this setting, the copy action will fail with CrossAccountBackupNotEnabled.
Step 2: Create the destination vault in the DR account
The destination vault needs a KMS key that trusts the AWS Backup service principal from the source account, and a vault access policy that grants the copy-into permission to the source account.
# In the DR account: create a KMS key with cross-account backup trust
# Key policy (abbreviated — merge with standard key policy template):
{
"Effect": "Allow",
"Principal": {
"Service": "backup.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "PRODUCTION_ACCOUNT_ID"
}
}
}
// CDK in the DR account stack
import * as backup from 'aws-cdk-lib/aws-backup';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as kms from 'aws-cdk-lib/aws-kms';
const drKey = new kms.Key(this, 'DrBackupKey', {
enableKeyRotation: true,
description: 'AliveMCP DR backup vault key',
policy: new iam.PolicyDocument({
statements: [
// Standard admin grant
new iam.PolicyStatement({
principals: [new iam.AccountRootPrincipal()],
actions: ['kms:*'],
resources: ['*'],
}),
// Cross-account backup service grant
new iam.PolicyStatement({
principals: [new iam.ServicePrincipal('backup.amazonaws.com')],
actions: ['kms:Decrypt', 'kms:GenerateDataKey', 'kms:DescribeKey'],
resources: ['*'],
conditions: {
StringEquals: { 'aws:SourceAccount': PROD_ACCOUNT_ID },
},
}),
],
}),
});
const drVault = new backup.BackupVault(this, 'DrVault', {
backupVaultName: 'alivemcp-dr',
encryptionKey: drKey,
accessPolicy: new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
principals: [new iam.ArnPrincipal(`arn:aws:iam::${PROD_ACCOUNT_ID}:root`)],
actions: ['backup:CopyIntoBackupVault'],
resources: ['*'],
}),
],
}),
});
Step 3: Add the copy action to the backup plan
In the production account, add a CopyActions entry to your backup plan rule pointing at the DR vault ARN. The CDK L2 BackupPlanRule does not expose a copyActions prop directly — use the CloudFormation escape hatch or construct the rule via L1.
// Production account: backup plan with cross-account copy
import * as backup from 'aws-cdk-lib/aws-backup';
const plan = new backup.BackupPlan(this, 'McpBackupPlan', {
backupPlanName: 'alivemcp-prod-plan',
backupVault: prodVault,
});
// Use the CDK escape hatch to add CopyActions (L2 doesn't expose this yet)
const cfnPlan = plan.node.defaultChild as backup.CfnBackupPlan;
cfnPlan.backupPlan = {
backupPlanName: 'alivemcp-prod-plan',
backupPlanRule: [
{
ruleName: 'daily-with-cross-account-copy',
targetBackupVault: prodVault.backupVaultName,
scheduleExpression: 'cron(0 3 * * ? *)',
startWindowMinutes: 60,
completionWindowMinutes: 240,
lifecycle: {
deleteAfterDays: 35,
moveToColdStorageAfterDays: 7,
},
copyActions: [
{
destinationBackupVaultArn:
`arn:aws:backup:us-west-2:${DR_ACCOUNT_ID}:backup-vault:alivemcp-dr`,
lifecycle: {
deleteAfterDays: 90, // keep DR copies longer than prod hot copies
},
},
],
},
],
};
The copy is performed asynchronously after the original backup job completes. The original recovery point's status is COMPLETED before the copy starts. Monitor copy job status via EventBridge Copy Job State Change events from the aws.backup source.
Enforcing backup with Organizations backup policies
AWS Organizations backup policies let the management account (or delegated admin) attach a backup plan to any OU or set of accounts. The policy is applied on top of each member account's existing plans — it does not replace them. Backup policies support the same rule types as account-level plans.
# Organizations backup policy JSON (attached to the production OU)
{
"plans": {
"OrgDailyBackupPlan": {
"regions": {
"@@assign": ["us-east-1", "us-west-2"]
},
"rules": {
"OrgDailyRule": {
"schedule_expression": {
"@@assign": "cron(0 5 * * ? *)"
},
"target_backup_vault_name": {
"@@assign": "alivemcp-prod"
},
"lifecycle": {
"delete_after_days": { "@@assign": 35 },
"move_to_cold_storage_after_days": { "@@assign": 7 }
},
"copy_actions": {
"arn:aws:backup:us-west-2:DR_ACCOUNT_ID:backup-vault:alivemcp-dr": {
"lifecycle": {
"delete_after_days": { "@@assign": 90 }
}
}
}
}
},
"selections": {
"tags": {
"OrgBackupSelection": {
"iam_role_arn": {
"@@assign": "arn:aws:iam::$account:role/AWSBackupDefaultServiceRole"
},
"tag_key": { "@@assign": "Backup" },
"tag_value": { "@@assign": ["true"] }
}
}
}
}
}
}
The $account variable in the IAM role ARN is a macro that substitutes each member account's account ID when the policy is applied. This means every member account uses its own AWSBackupDefaultServiceRole role — you don't need a cross-account role for the backup agent itself.
Restoring from a cross-account recovery point
To restore from the DR account, assume an IAM role in the DR account that has backup:StartRestoreJob permission, then start the restore into the DR account or into a new production account after account recovery.
# List recovery points in the DR vault
aws backup list-recovery-points-by-backup-vault \
--backup-vault-name alivemcp-dr \
--profile dr-account \
--query 'RecoveryPoints[?ResourceType==`DynamoDB` && Status==`COMPLETED`]|sort_by(@,&CreationDate)[-3:]'
# Start a restore into the DR account
aws backup start-restore-job \
--recovery-point-arn arn:aws:backup:us-west-2:DR_ACCT:recovery-point:abc123 \
--iam-role-arn arn:aws:iam::DR_ACCT:role/AWSBackupDefaultServiceRole \
--resource-type DynamoDB \
--metadata '{"targetTableName": "alivemcp-sessions-restored"}' \
--profile dr-account
Restoring from the DR account creates the resource in the DR account. If you need to restore into a third account (e.g., a new production account), you must first copy the recovery point from the DR vault to a vault in the new production account, then start the restore there. Direct cross-account restore to an arbitrary third account is not supported — restore always targets the account that owns the vault.
Common failures
| Symptom | Cause | Fix |
|---|---|---|
Copy job fails: CrossAccountBackupNotEnabled | isCrossAccountBackupEnabled is false in either the source or destination account | Run aws backup update-global-settings --global-settings '{"isCrossAccountBackupEnabled":"true"}' in both accounts |
Copy job fails: AccessDeniedException from KMS | The destination vault's KMS key policy does not grant the backup service principal from the source account the needed KMS actions | Add a key policy statement granting kms:Decrypt, kms:GenerateDataKey, and kms:DescribeKey to backup.amazonaws.com with a aws:SourceAccount condition for the source account ID |
Copy job fails: AccessDeniedException from Backup | The destination vault's access policy does not grant backup:CopyIntoBackupVault to the source account | Add an allow statement for backup:CopyIntoBackupVault granting access to arn:aws:iam::SOURCE_ACCT:root |
| Organizations backup policy not applied to member account | Trusted access for backup.amazonaws.com is not enabled in Organizations | Run aws organizations enable-aws-service-access --service-principal backup.amazonaws.com from the management account |
| Restore from DR vault fails: resource type not supported in destination region | DynamoDB Global Tables or some RDS versions are not available in all regions | Choose DR region carefully based on the resource types you need to restore; verify service availability at the AWS regional services list before choosing DR region |