Migrating between cloud providers - whether from AWS to Azure, GCP to AWS, or implementing a multi-cloud strategy - introduces significant security risks. This guide covers the essential security practices for protecting your data and maintaining compliance throughout the migration process.
Why Cloud Migrations Are Security-Critical
Cloud migrations are high-risk periods because:
- Data in transit: Sensitive data moves across networks, potentially exposed
- Dual environments: You're securing two clouds simultaneously
- Configuration drift: Security controls may not translate directly between providers
- Access sprawl: Temporary elevated permissions often become permanent
- Compliance gaps: Regulations may have different requirements per provider
Phase 1: Pre-Migration Security Assessment
Inventory and Classify Your Data
Before moving anything, understand what you're migrating:
# Example data classification framework
CLASSIFICATION_LEVELS = {
"public": {
"encryption": "optional",
"transfer": "standard",
"compliance": []
},
"internal": {
"encryption": "required_in_transit",
"transfer": "encrypted_channel",
"compliance": ["SOC2"]
},
"confidential": {
"encryption": "required_at_rest_and_transit",
"transfer": "dedicated_connection",
"compliance": ["SOC2", "GDPR"]
},
"restricted": {
"encryption": "customer_managed_keys",
"transfer": "private_link_only",
"compliance": ["SOC2", "GDPR", "PCI-DSS", "HIPAA"]
}
}
Security Baseline Documentation
Document your current security posture:
- All IAM roles, policies, and service accounts
- Network security groups and firewall rules
- Encryption keys and their rotation schedules
- Compliance certifications and audit requirements
- Security monitoring and alerting configurations
Map Security Controls Between Providers
| Security Control | AWS | Azure | GCP |
|---|---|---|---|
| Identity Provider | IAM, IAM Identity Center | Azure AD, Entra ID | Cloud Identity, IAM |
| Secret Management | Secrets Manager | Key Vault | Secret Manager |
| Key Management | KMS | Key Vault | Cloud KMS |
| Network Firewall | Security Groups, NACLs | NSGs, Azure Firewall | Firewall Rules, Cloud Armor |
| Threat Detection | GuardDuty | Defender for Cloud | Security Command Center |
Phase 2: Secure Data Transfer
Establish Private Connectivity
Never transfer sensitive data over the public internet:
Option 1: Direct Connect / ExpressRoute / Dedicated Interconnect
For large-scale migrations, establish dedicated private connections:
# AWS Direct Connect + Azure ExpressRoute peering
# Requires physical cross-connect at a colocation facility
# Alternative: Use cloud-to-cloud VPN
# AWS to Azure VPN example
aws ec2 create-vpn-gateway --type ipsec.1 --amazon-side-asn 65000
# Then configure Azure Virtual Network Gateway to connect
Option 2: Cloud-Native Transfer Services
# AWS to GCP: Use Storage Transfer Service
gcloud transfer jobs create \
--source-agent-pool=aws-pool \
--destination=gs://my-gcp-bucket \
--source-creds-file=aws-credentials.json
# Azure to AWS: Use AWS DataSync
aws datasync create-location-azure-blob \
--agent-arns arn:aws:datasync:region:account:agent/agent-id \
--container-url "https://account.blob.core.windows.net/container" \
--authentication-type SAS
Encrypt Data in Transit
Always use TLS 1.2+ for data transfer:
# Verify TLS version in transfer
openssl s_client -connect target-endpoint:443 -tls1_2
# For database migrations, use SSL connections
# PostgreSQL example
psql "host=target-db.region.rds.amazonaws.com \
dbname=mydb \
user=admin \
sslmode=verify-full \
sslrootcert=rds-ca-cert.pem"
Re-encrypt Data with Target Cloud Keys
Don't transfer encryption keys between clouds. Re-encrypt data with the target cloud's KMS:
# Step 1: Decrypt with source cloud key
aws kms decrypt \
--ciphertext-blob fileb://encrypted-data \
--output text --query Plaintext | base64 --decode > decrypted-data
# Step 2: Re-encrypt with target cloud key
gcloud kms encrypt \
--location=us-central1 \
--keyring=migration-keyring \
--key=data-key \
--plaintext-file=decrypted-data \
--ciphertext-file=reencrypted-data
# Step 3: Securely delete plaintext
shred -vfz -n 5 decrypted-data
Phase 3: Identity and Access Migration
Federate Identity Across Clouds
Use a single identity provider for both clouds during migration:
# Configure AWS to trust Azure AD
# In AWS IAM Identity Provider:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT:saml-provider/AzureAD"
},
"Action": "sts:AssumeRoleWithSAML",
"Condition": {
"StringEquals": {
"SAML:aud": "https://signin.aws.amazon.com/saml"
}
}
}]
}
Implement Just-in-Time Access
Migration requires elevated access, but limit its scope and duration:
# Use temporary credentials with expiration
# AWS STS example
aws sts assume-role \
--role-arn arn:aws:iam::ACCOUNT:role/MigrationRole \
--role-session-name migration-session \
--duration-seconds 3600
# Azure PIM - activate role for limited time
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignmentScheduleRequests" \
--body '{
"action": "selfActivate",
"justification": "Cloud migration task",
"scheduleInfo": {
"expiration": {
"type": "afterDuration",
"duration": "PT4H"
}
}
}'
Audit and Remove Temporary Access
# Script to find and flag migration-related IAM entities
# Run weekly during migration
# AWS - Find roles with "migration" in name
aws iam list-roles --query "Roles[?contains(RoleName, 'migration')]"
# Azure - Find migration-related role assignments
az role assignment list --query "[?contains(roleDefinitionName, 'migration')]"
# GCP - Find migration service accounts
gcloud iam service-accounts list --filter="email:migration"
Phase 4: Application Migration Security
Secrets Migration
Never copy secrets directly. Rotate and recreate in the target environment:
# 1. Create new secrets in target cloud
gcloud secrets create db-password --data-file=-
# 2. Update application to use new secret reference
# 3. Rotate the secret in source cloud to invalidate old value
aws secretsmanager rotate-secret --secret-id old-db-password
# 4. After verification, delete from source
aws secretsmanager delete-secret --secret-id old-db-password --force-delete-without-recovery
Container Image Migration
# Scan images before migration
trivy image my-registry/my-app:latest
# Sign images for the target registry
cosign sign --key gcpkms://projects/PROJECT/locations/LOCATION/keyRings/KEYRING/cryptoKeys/KEY \
gcr.io/target-project/my-app:latest
# Verify signature in target environment
cosign verify --key gcpkms://... gcr.io/target-project/my-app:latest
Database Migration Security
# Use SSL/TLS for database migration
# AWS DMS with SSL
aws dms create-endpoint \
--endpoint-identifier source-db \
--endpoint-type source \
--engine-name postgres \
--ssl-mode verify-full \
--certificate-arn arn:aws:dms:region:account:cert:cert-id
# Verify no sensitive data in logs
# Disable query logging during migration
ALTER SYSTEM SET log_statement = 'none';
SELECT pg_reload_conf();
Phase 5: Network Security During Migration
Temporary Network Architecture
# Create isolated migration network segment
# AWS VPC for migration
aws ec2 create-vpc --cidr-block 10.200.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=migration-vpc}]'
# Strict security group - only allow migration traffic
aws ec2 create-security-group \
--group-name migration-sg \
--description "Migration traffic only" \
--vpc-id vpc-migration
aws ec2 authorize-security-group-ingress \
--group-id sg-migration \
--protocol tcp \
--port 443 \
--source-group sg-source-apps
Monitor Cross-Cloud Traffic
# Enable VPC Flow Logs on migration subnets
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-migration \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /migration/flow-logs
# Alert on unexpected destinations
# CloudWatch Logs Insights query
fields @timestamp, srcAddr, dstAddr, bytes
| filter dstAddr not like /^10\./ and dstAddr not like /^172\.16\./
| stats sum(bytes) as totalBytes by dstAddr
| sort totalBytes desc
| limit 20
Phase 6: Compliance and Audit
Maintain Audit Trail
Document every action during migration for compliance:
# Centralize logs from both clouds
# Send to a SIEM or log aggregator
# AWS CloudTrail to S3
aws cloudtrail create-trail \
--name migration-audit-trail \
--s3-bucket-name central-audit-logs \
--include-global-service-events \
--is-multi-region-trail
# Azure Activity Logs to same destination
az monitor diagnostic-settings create \
--name migration-audit \
--resource /subscriptions/SUB_ID \
--storage-account /subscriptions/SUB_ID/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/centrallogs
Compliance Validation Checklist
- Data residency requirements met in target cloud
- Encryption standards maintained (AES-256, TLS 1.2+)
- Access controls replicated and tested
- Audit logging enabled and retained per policy
- Penetration test scheduled for post-migration
- Compliance certifications verified for target services
Phase 7: Post-Migration Security
Cleanup Checklist
# 1. Remove temporary IAM roles and permissions
aws iam delete-role --role-name MigrationAdminRole
# 2. Delete temporary network connections
aws ec2 delete-vpc-peering-connection --vpc-peering-connection-id pcx-migration
# 3. Revoke temporary credentials
aws iam delete-access-key --user-name migration-user --access-key-id AKIA...
# 4. Remove migration security groups
aws ec2 delete-security-group --group-id sg-migration
# 5. Verify source environment decommissioning
# Run security scan to find orphaned resources
Security Validation
# Run security assessment on target environment
# Using cloud-native tools
# AWS Security Hub
aws securityhub get-findings --filters '{"GeneratorId":[{"Value":"security-control","Comparison":"PREFIX"}]}'
# Azure Defender
az security assessment list --query "[?status.code=='Unhealthy']"
# GCP Security Command Center
gcloud scc findings list organizations/ORG_ID --filter="state=\"ACTIVE\""
Migration Security Checklist
- Pre-Migration:
- Data classified and documented
- Security controls mapped between clouds
- Compliance requirements identified
- Private connectivity established
- During Migration:
- All data encrypted in transit
- Temporary access time-limited
- Audit logging enabled on both clouds
- Network traffic monitored
- Post-Migration:
- Temporary resources deleted
- Access permissions audited
- Security assessment completed
- Source environment decommissioned securely
Next Steps
Cloud migration security requires careful planning and execution. The temporary nature of migrations often leads to security shortcuts that become permanent vulnerabilities. Treat your migration as a security-critical project with proper oversight and validation at every phase.
Need help with a secure cloud migration? Contact us for expert guidance and implementation support.