Account Encryption
Lab Objective
In this hands-on lab, you will learn how to:
- Configure storage account encryption with Microsoft-managed and customer-managed keys
- Set up Azure Key Vault integration for customer-managed keys (CMK)
- Implement encryption scopes for granular encryption control
- Configure encryption at rest and in transit for comprehensive data protection
- Test key rotation scenarios and disaster recovery procedures
- Monitor encryption status and compliance requirements
- Troubleshoot encryption-related access issues
Scenario: Your organization has strict data protection requirements that mandate customer-managed encryption keys for sensitive data. You’ll configure various encryption options and test key management scenarios to ensure compliance and security.
Please sign in to launch lab.
Pre-Provisioned Environment
The following Azure resources have been pre-deployed in your environment:
Resource Overview
Resource Type | Resource Name | Configuration | Purpose |
---|---|---|---|
Resource Group | Encryption-Lab-RG | Contains all lab resources | Logical container |
Key Vault | encryptionkv[unique] | East US, RBAC enabled | Customer-managed keys |
Storage Account | mskmanagedstore[unique] | Microsoft-managed keys | Default encryption |
Storage Account | cmkstore[unique] | Ready for CMK setup | Customer-managed encryption |
Storage Account | scopestore[unique] | Multiple encryption scopes | Scope-based encryption |
User Identity | EncryptionIdentity | Managed identity | Key Vault access |
Test VM | EncryptionVM | Windows Server 2019 | Encryption testing |
Key Vault Configuration
Component | Configuration | Purpose |
---|---|---|
Access Policy Model | RBAC (Recommended) | Modern permission model |
Soft Delete | Enabled (90 days) | Key recovery protection |
Purge Protection | Enabled | Permanent deletion prevention |
Network Access | All networks (for lab) | Connectivity testing |
Storage Account Encryption Status
Account | Encryption Type | Key Source | Encryption Scope |
---|---|---|---|
mskmanagedstore[unique] | Microsoft-managed | Microsoft.Storage | Default |
cmkstore[unique] | Ready for CMK | Will configure | Custom |
scopestore[unique] | Multiple scopes | Mixed | Multiple |
Managed Identity Details
Identity | Type | Permissions | Purpose |
---|---|---|---|
EncryptionIdentity | User-assigned | Key Vault access | CMK operations |
Lab Exercises
Part 1: Understand Default Encryption
Step 1: Examine Microsoft-Managed Encryption
- Navigate to Encryption-Lab-RG resource group
- Click on
mskmanagedstore[unique]
storage account - Go to Security + Networking → Encryption
Observe the default settings:
- Encryption type: Microsoft-managed keys
- Infrastructure encryption: Disabled (can be enabled for additional security)
- Blob service: Enabled
- File service: Enabled
- Table service: Enabled
- Queue service: Enabled
Step 2: Upload Test Data
- Go to Storage browser → Blob containers
- Create a new container named
test-data
- Set access level to Private
- Upload sample files:
- Create a text file with sample sensitive data
- Upload an image or document
- Note: All data is automatically encrypted at rest
Step 3: Understand Encryption Scope
Key Point: With Microsoft-managed keys:
- Azure handles all encryption key management
- No additional configuration required
- Keys are rotated automatically by Microsoft
- No additional cost for encryption
Part 2: Configure Customer-Managed Keys (CMK)
Step 1: Create Encryption Key in Key Vault
- Navigate to encryptionkv[unique] Key Vault
- Go to Objects → Keys
- Click “Generate/Import”
Create new key:
- Name:
StoragePrimaryKey
- Key type: RSA
- RSA key size: 2048
- Set activation/expiration dates: (Optional)
- Click Create
Step 2: Configure Storage Account Identity
- Navigate to cmkstore[unique] storage account
- Go to Security + Networking → Identity
- System assigned identity:
- Status: On
- Click Save
- Note the Object (principal) ID for later use
Step 3: Grant Key Vault Permissions
- Return to encryptionkv[unique] Key Vault
- Go to Access control (IAM)
- Click “Add role assignment”
Assign role:
- Role: Key Vault Crypto Service Encryption User
- Assign access to: Managed identity
- Members: Select the storage account identity
- Click Review + assign
Step 4: Configure Customer-Managed Key
- Return to cmkstore[unique] storage account
- Go to Security + Networking → Encryption
- Change encryption type:
- Select Customer-managed keys
- Key selection method: Select from Key Vault
- Key Vault: encryptionkv[unique]
- Key: StoragePrimaryKey
- Version: (Latest) or specific version
- Click Save
Step 5: Test CMK Encryption
- Create a new container named
cmk-test-data
- Upload test files
- Verify encryption status:
- Go back to Encryption settings
- Confirm it shows “Customer-managed keys”
- Note the key version in use
Part 3: Understanding Encryption Scopes
Step 1: Create Encryption Scopes (Portal Method)
- Navigate to scopestore[unique] storage account
- Go to Security + Networking → Encryption
- Scroll down to Encryption scopes
- Click “Add encryption scope”
Create Default Scope:
- Name:
DefaultScope
- Encryption type: Microsoft-managed keys
- Infrastructure encryption: Disabled
- Click Add
Create Sensitive Scope:
- Name:
SensitiveScope
- Encryption type: Customer-managed keys
- Key Vault: encryptionkv[unique]
- Key: StoragePrimaryKey
- Click Add
Step 2: Test Scope-Based Uploads
- Go to Storage browser → Blob containers
- Create containers:
general-data
(for default scope)sensitive-data
(for sensitive scope)
Upload with specific scopes:
- In Azure Storage Explorer or portal:
- When uploading to
general-data
, use DefaultScope - When uploading to
sensitive-data
, use SensitiveScope
- When uploading to
- Verify scope assignment in blob properties
Step 3: Compare Encryption Methods
Create a comparison table:
Container | Encryption Method | Key Management | Use Case |
---|---|---|---|
test-data | Microsoft-managed | Automatic | General data |
cmk-test-data | Customer-managed | Manual rotation | Sensitive data |
general-data | Scope: Default | Automatic | Standard files |
sensitive-data | Scope: Customer | Manual rotation | Confidential files |
Part 4: Key Rotation and Management
Step 1: Create New Key Version (Portal)
- Navigate to encryptionkv[unique] Key Vault
- Go to Objects → Keys → StoragePrimaryKey
- Click “New Version”
- Keep same settings, click Create
- Note the new version number
Step 2: Update Storage Account Key Version
- Navigate to cmkstore[unique] storage account
- Go to Security + Networking → Encryption
- Update key version:
- Change from “Latest” to the new specific version
- OR keep as “Latest” for automatic updates
- Click Save
Step 3: Test Data Access After Rotation
- Access existing data in the CMK container
- Upload new data to verify encryption works
- Confirm both old and new data remain accessible
Key Learning Points:
- Existing data remains accessible with old key versions
- New data uses the current key version
- Azure maintains access to all key versions needed
Part 5: Monitor Encryption Status
Step 1: Create Encryption Monitoring Checklist
Review each storage account:
Storage Account | Encryption Type | Key Source | Status |
---|---|---|---|
mskmanagedstore[unique] | Microsoft-managed | Microsoft.Storage | ✅ Active |
cmkstore[unique] | Customer-managed | Key Vault | ✅ Active |
scopestore[unique] | Multiple scopes | Mixed | ✅ Active |
Step 2: Verify Compliance Requirements
Check each requirement:
- ✅ All data encrypted at rest
- ✅ Customer-managed keys for sensitive data
- ✅ Key rotation capability demonstrated
- ✅ Access controls properly configured
- ✅ Encryption scopes properly applied
Step 3: Document Key Management Procedures
Create procedures for:
- Regular key rotation (quarterly/annually)
- Key backup and recovery processes
- Access review for Key Vault permissions
- Monitoring encryption status changes
- Incident response for key compromise
Optional Advanced Exercises
For users wanting more technical depth, try these PowerShell-based exercises:
Advanced Exercise 1: Automated Key Rotation
# Connect to Azure (run in CloudShell or local PowerShell)Connect-AzAccount
# Create new key version and update storage automatically$keyVault = "encryptionkv[unique]"$storageAccount = "cmkstore[unique]"$resourceGroup = "Encryption-Lab-RG"
# Create new key version$newKey = Add-AzKeyVaultKey -VaultName $keyVault -Name "StoragePrimaryKey" -Destination "Software"
# Update storage account to use new versionSet-AzStorageAccount -ResourceGroupName $resourceGroup -Name $storageAccount -KeyvaultEncryption -KeyName "StoragePrimaryKey" -KeyVersion $newKey.Version -KeyVaultUri "https://$keyVault.vault.azure.net/"
Advanced Exercise 2: Bulk Encryption Status Check
# Check encryption status across all storage accountsGet-AzStorageAccount -ResourceGroupName "Encryption-Lab-RG" | ForEach-Object { Write-Host "Account: $($_.StorageAccountName)" Write-Host " Encryption: $($_.Encryption.KeySource)" if ($_.Encryption.KeyVaultProperties) { Write-Host " Key: $($_.Encryption.KeyVaultProperties.KeyName)" } Write-Host "---"}
Optional Advanced Exercises
For users wanting more technical depth, try these PowerShell-based exercises:
Step 2: Test Key Rotation Impact
# Update storage account to use new key versionWrite-Host "Updating storage account to use new key version..."
Set-AzStorageAccount -ResourceGroupName $resourceGroup -Name $cmkAccount -KeyvaultEncryption -KeyName "StoragePrimaryKey" -KeyVersion $newPrimaryKey.Version -KeyVaultUri $keyVaultUri
# Verify the update$updatedCmkStorage = Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $cmkAccountWrite-Host "Updated CMK configuration:"Write-Host " Key Version (Old): $($primaryKey.Version)"Write-Host " Key Version (New): $($updatedCmkStorage.Encryption.KeyVaultProperties.KeyVersion)"
# Test access to existing encrypted dataWrite-Host "Testing access to existing encrypted data after key rotation..."$cmkContext = $updatedCmkStorage.Context
try { $blobs = Get-AzStorageBlob -Container "cmk-encrypted-data" -Context $cmkContext Write-Host "SUCCESS: Can access existing encrypted blobs after key rotation" Write-Host " Accessible blobs: $($blobs.Count)"} catch { Write-Host "ERROR: Cannot access existing encrypted blobs after key rotation" Write-Host " Error: $($_.Exception.Message)"}
# Upload new data with rotated key$newTestFile = "C:\temp\rotated-key-test.txt"New-Item -ItemType Directory -Path "C:\temp" -Force"Test data encrypted with rotated key - $(Get-Date)" | Out-File -FilePath $newTestFile -Encoding UTF8
Set-AzStorageBlobContent -File $newTestFile -Container "cmk-encrypted-data" -Blob "rotated-key-test.txt" -Context $cmkContext -ForceWrite-Host "SUCCESS: Uploaded new data with rotated key"
Step 3: Test Key Disabling Scenario
# Simulate key compromise scenario by disabling the old key versionWrite-Host "Testing key disabling scenario..."
# First, ensure we're using the new key version$currentStorage = Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $cmkAccountWrite-Host "Current key version in use: $($currentStorage.Encryption.KeyVaultProperties.KeyVersion)"
# Disable the old key version (simulate key compromise)Update-AzKeyVaultKey -VaultName $keyVaultName -Name "StoragePrimaryKey" -Version $primaryKey.Version -Enable $falseWrite-Host "Disabled old key version: $($primaryKey.Version)"
# Test access with disabled keyStart-Sleep -Seconds 10 # Wait for changes to propagate
try { $testAccess = Get-AzStorageBlob -Container "cmk-encrypted-data" -Context $cmkContext | Select-Object -First 1 Write-Host "Storage access status: ACCESSIBLE (using current key version)"} catch { Write-Host "Storage access status: FAILED - $($_.Exception.Message)"}
# Re-enable the key for continued testingUpdate-AzKeyVaultKey -VaultName $keyVaultName -Name "StoragePrimaryKey" -Version $primaryKey.Version -Enable $trueWrite-Host "Re-enabled old key version for testing continuity"
Part 5: Monitor Encryption Status and Compliance
Step 1: Create Encryption Monitoring Dashboard
# Function to check encryption status across all storage accountsfunction Get-EncryptionStatus { $allAccounts = @($mskAccount, $cmkAccount, $scopeAccount)
Write-Host "=== ENCRYPTION STATUS REPORT ===" Write-Host "Generated: $(Get-Date)" Write-Host ""
foreach ($accountName in $allAccounts) { $account = Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $accountName
Write-Host "Storage Account: $accountName" Write-Host " Encryption Source: $($account.Encryption.KeySource)"
if ($account.Encryption.KeySource -eq "Microsoft.Keyvault") { Write-Host " Key Vault: $($account.Encryption.KeyVaultProperties.KeyVaultUri)" Write-Host " Key Name: $($account.Encryption.KeyVaultProperties.KeyName)" Write-Host " Key Version: $($account.Encryption.KeyVaultProperties.KeyVersion)" }
Write-Host " Service Encryption Status:" Write-Host " Blob: $($account.Encryption.Services.Blob.Enabled)" Write-Host " File: $($account.Encryption.Services.File.Enabled)" Write-Host " Table: $($account.Encryption.Services.Table.Enabled)" Write-Host " Queue: $($account.Encryption.Services.Queue.Enabled)"
# Check for encryption scopes try { $scopes = Get-AzStorageEncryptionScope -ResourceGroupName $resourceGroup -StorageAccountName $accountName if ($scopes) { Write-Host " Encryption Scopes: $($scopes.Count)" $scopes | ForEach-Object { Write-Host " - $($_.Name): $($_.Source)" } } } catch { Write-Host " Encryption Scopes: None or not accessible" }
Write-Host "---" }}
Get-EncryptionStatus
Step 2: Audit Key Usage and Access
# Check Key Vault access logs (requires diagnostic settings in production)Write-Host "Key Vault Audit Information:"Write-Host "Key Vault: $keyVaultName"
# List all keys and their versions$allKeys = Get-AzKeyVaultKey -VaultName $keyVaultName$allKeys | ForEach-Object { Write-Host "Key: $($_.Name)"
# Get all versions $versions = Get-AzKeyVaultKey -VaultName $keyVaultName -Name $_.Name -IncludeVersions Write-Host " Total Versions: $($versions.Count)"
$versions | ForEach-Object { $status = if ($_.Enabled) { "Active" } else { "Disabled" } Write-Host " Version: $($_.Version) - Created: $($_.Created) - Status: $status" } Write-Host "---"}
# Check storage accounts using each keyWrite-Host "Key Usage Analysis:"$storageAccounts = Get-AzStorageAccount -ResourceGroupName $resourceGroup$storageAccounts | Where-Object { $_.Encryption.KeySource -eq "Microsoft.Keyvault" } | ForEach-Object { Write-Host "Storage Account: $($_.StorageAccountName)" Write-Host " Uses Key: $($_.Encryption.KeyVaultProperties.KeyName)" Write-Host " Key Version: $($_.Encryption.KeyVaultProperties.KeyVersion)"}
Step 3: Test Compliance Scenarios
# Simulate compliance audit scenariosWrite-Host "=== COMPLIANCE AUDIT SCENARIOS ==="
# Scenario 1: Verify all sensitive data uses CMKWrite-Host "1. Checking sensitive data encryption compliance..."$scopeContext = (Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $scopeAccount).Context
$sensitiveBlobs = Get-AzStorageBlob -Container "sensitive-encrypted" -Context $scopeContext$sensitiveBlobs | ForEach-Object { $encryptionScope = $_.BlobProperties.EncryptionScope if ($encryptionScope -eq "SensitiveScope") { Write-Host " ✓ COMPLIANT: $($_.Name) - Encrypted with customer-managed key" } else { Write-Host " ✗ NON-COMPLIANT: $($_.Name) - Using incorrect encryption scope: $encryptionScope" }}
# Scenario 2: Verify key rotation recencyWrite-Host "2. Checking key rotation compliance (keys should be less than 90 days old)..."$keyAge = (Get-Date) - $newPrimaryKey.Createdif ($keyAge.Days -le 90) { Write-Host " ✓ COMPLIANT: Key rotated $($keyAge.Days) days ago"} else { Write-Host " ✗ NON-COMPLIANT: Key is $($keyAge.Days) days old, exceeds 90-day policy"}
# Scenario 3: Verify key access restrictionsWrite-Host "3. Checking key access permissions..."$keyVaultDetails = Get-AzKeyVault -VaultName $keyVaultName -ResourceGroupName $resourceGroupWrite-Host " Key Vault Access Model: $($keyVaultDetails.EnableRbacAuthorization)"Write-Host " Soft Delete: $($keyVaultDetails.EnableSoftDelete)"Write-Host " Purge Protection: $($keyVaultDetails.EnablePurgeProtection)"
if ($keyVaultDetails.EnableSoftDelete -and $keyVaultDetails.EnablePurgeProtection) { Write-Host " ✓ COMPLIANT: Key protection features enabled"} else { Write-Host " ✗ NON-COMPLIANT: Missing key protection features"}
Part 6: Disaster Recovery and Key Management
Step 1: Create Key Backup Strategy
# Create backup of encryption keysWrite-Host "Creating key backup strategy..."
$backupPath = "C:\KeyBackups"New-Item -ItemType Directory -Path $backupPath -Force
# Backup all encryption keys$allKeys = Get-AzKeyVaultKey -VaultName $keyVaultName$allKeys | ForEach-Object { $keyName = $_.Name $backupFile = "$backupPath\$keyName-backup.blob"
try { $backup = Backup-AzKeyVaultKey -VaultName $keyVaultName -Name $keyName -OutputFile $backupFile -Force Write-Host "✓ Backed up key: $keyName to $backupFile" } catch { Write-Host "✗ Failed to backup key: $keyName - $($_.Exception.Message)" }}
Write-Host "Key backup completed. Files stored in: $backupPath"Get-ChildItem $backupPath | Select-Object Name, Length, LastWriteTime
Step 2: Test Key Recovery Scenario
# Simulate key recovery scenarioWrite-Host "Testing key recovery scenario..."
# Create a test key for recovery simulation$testKey = Add-AzKeyVaultKey -VaultName $keyVaultName -Name "TestRecoveryKey" -Destination "Software" -KeyType "RSA" -Size 2048Write-Host "Created test key: $($testKey.Name)"
# Backup the test key$testBackupFile = "$backupPath\TestRecoveryKey-backup.blob"Backup-AzKeyVaultKey -VaultName $keyVaultName -Name "TestRecoveryKey" -OutputFile $testBackupFile -ForceWrite-Host "Backed up test key"
# Delete the test key (simulate disaster)Remove-AzKeyVaultKey -VaultName $keyVaultName -Name "TestRecoveryKey" -Force -Confirm:$falseWrite-Host "Deleted test key (simulating disaster)"
# Verify key is gonetry { Get-AzKeyVaultKey -VaultName $keyVaultName -Name "TestRecoveryKey" Write-Host "Key still exists (unexpected)"} catch { Write-Host "✓ Confirmed: Key is deleted"}
# Restore the key from backuptry { $restoredKey = Restore-AzKeyVaultKey -VaultName $keyVaultName -InputFile $testBackupFile Write-Host "✓ Successfully restored key: $($restoredKey.Name)" Write-Host " Restored Version: $($restoredKey.Version)"} catch { Write-Host "✗ Failed to restore key: $($_.Exception.Message)"}
# Clean up test keyRemove-AzKeyVaultKey -VaultName $keyVaultName -Name "TestRecoveryKey" -Force -Confirm:$falseWrite-Host "Cleaned up test key"
Step 3: Document Recovery Procedures
# Generate disaster recovery documentation$drDocument = @"=== ENCRYPTION KEY DISASTER RECOVERY PROCEDURES ===
Generated: $(Get-Date)Key Vault: $keyVaultNameResource Group: $resourceGroup
BACKUP LOCATIONS:- Key Vault Backups: $backupPath- Keys backed up: $($allKeys.Count)
RECOVERY STEPS:1. Ensure Key Vault is accessible and operational2. Restore keys from backup files using: Restore-AzKeyVaultKey -VaultName $keyVaultName -InputFile <backup-file>3. Update storage accounts to use restored keys4. Verify encryption/decryption functionality5. Test data access across all storage accounts
STORAGE ACCOUNTS AFFECTED:- $cmkAccount (Customer-managed keys)- $scopeAccount (Multiple encryption scopes)
EMERGENCY CONTACTS:- Azure Support: [Your support plan details]- Key Vault Administrator: [Admin contact]- Security Team: [Security team contact]
TESTING REQUIREMENTS:- Test key recovery monthly- Verify storage account access after recovery- Document any access issues or delays
"@
$drDocument | Out-File -FilePath "$backupPath\DisasterRecoveryProcedures.txt" -Encoding UTF8Write-Host "Disaster recovery documentation created: $backupPath\DisasterRecoveryProcedures.txt"
Troubleshooting Guide
Common Encryption Issues
Issue | Symptoms | Possible Cause | Solution |
---|---|---|---|
CMK setup fails | Configuration errors | Missing permissions | Verify managed identity has Key Vault access |
Data access denied | 403 errors accessing blobs | Key disabled or deleted | Check key status in Key Vault |
Encryption scope errors | Cannot upload with scope | Scope not configured properly | Verify scope exists and key is accessible |
Key rotation fails | Storage account not updated | Network or permission issues | Check Key Vault connectivity and permissions |
Backup restore fails | Key restoration errors | Corrupted backup or permissions | Verify backup file integrity and permissions |
Encryption Configuration Checklist
Component | Requirement | Status | Notes |
---|---|---|---|
Key Vault | Soft delete enabled | ✅ | Required for production |
Key Vault | Purge protection enabled | ✅ | Prevents permanent key deletion |
Managed Identity | Key Vault permissions | ✅ | Crypto Officer or custom permissions |
Storage Account | Identity assigned | ✅ | System or user-assigned |
Keys | RSA 2048+ or HSM | ✅ | Minimum key strength |
Backup | Regular key backups | ✅ | Monthly backup recommended |
Performance Considerations
Scenario | Impact | Mitigation |
---|---|---|
CMK vs MSK | Slightly higher latency | Use for sensitive data only |
Key rotation | Temporary access delays | Perform during maintenance windows |
Cross-region keys | Network latency | Use regional Key Vaults |
Multiple scopes | Management complexity | Document scope usage policies |
HSM keys | Higher costs | Use only for highest sensitivity data |
Additional Experiments
Try these optional exercises to deepen your understanding:
- HSM-Protected Keys: Configure HSM-protected keys for highest security
- Cross-Tenant Scenarios: Set up encryption across different Azure tenants
- Automated Key Rotation: Implement automated key rotation using Azure Functions
- Compliance Reporting: Create automated compliance reports for encryption status
- Multi-Region DR: Test disaster recovery across multiple Azure regions
Key Takeaways
After completing this lab, you should understand:
- Default encryption uses Microsoft-managed keys with no additional configuration
- Customer-managed keys provide additional control but require Key Vault setup
- Encryption scopes enable granular encryption policies within storage accounts
- Managed identities are essential for secure Key Vault integration
- Key rotation is crucial for security but requires careful planning
- Backup and recovery procedures are critical for business continuity
- Compliance monitoring requires regular auditing of encryption configurations
Encryption Decision Matrix
When to Use Each Encryption Type
Data Type | Recommended Encryption | Justification |
---|---|---|
Public data | Microsoft-managed | Cost-effective, adequate protection |
Internal documents | Microsoft-managed or Default scope | Standard protection, low management overhead |
Sensitive customer data | Customer-managed keys | Full control, compliance requirements |
Financial records | CMK with HSM | Highest security, regulatory compliance |
Archive data | Separate encryption scope | Cost optimization, long-term management |
Development/test | Microsoft-managed | Simple setup, non-production data |
Cost Considerations
Encryption Type | Additional Costs | Management Overhead |
---|---|---|
Microsoft-managed | None | Minimal |
Customer-managed | Key Vault operations | Medium |
Multiple scopes | Key Vault + management | High |
HSM-protected | HSM usage fees | High |
Cross-region | Data transfer costs | Medium |