Securing Your Cloud Infrastructure with Azure Defender for Cloud
Azure Defender for Cloud (formerly Azure Security Center with Azure Defender) is Microsoft’s cloud-native security solution that provides unified security management and advanced threat protection across hybrid cloud workloads. It helps you prevent, detect, and respond to security threats.
Understanding Azure Defender
Azure Defender extends the capabilities of Azure Security Center by adding:
- Advanced threat detection using machine learning and behavioral analytics
- Vulnerability assessment for VMs, container registries, and SQL databases
- Just-in-time VM access to reduce attack surface
- Adaptive application controls to block malicious applications
- Regulatory compliance dashboards for standards like PCI-DSS, SOC, and ISO
Enabling Azure Defender
Enable Azure Defender for your subscription:
# Enable Azure Defender for all resource types
az security pricing create \
--name VirtualMachines \
--tier Standard
az security pricing create \
--name SqlServers \
--tier Standard
az security pricing create \
--name AppServices \
--tier Standard
az security pricing create \
--name StorageAccounts \
--tier Standard
az security pricing create \
--name KeyVaults \
--tier Standard
az security pricing create \
--name ContainerRegistry \
--tier Standard
az security pricing create \
--name KubernetesService \
--tier Standard
# View current pricing tiers
az security pricing list --output table
Security Posture Management
Secure Score
Azure Defender calculates a secure score based on your security posture. Query your score programmatically:
import requests
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
token = credential.get_token("https://management.azure.com/.default")
subscription_id = "your-subscription-id"
url = f"https://management.azure.com/subscriptions/{subscription_id}/providers/Microsoft.Security/secureScores/ascScore?api-version=2020-01-01"
headers = {
"Authorization": f"Bearer {token.token}",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
score_data = response.json()
print(f"Current Score: {score_data['properties']['score']['current']}")
print(f"Maximum Score: {score_data['properties']['score']['max']}")
print(f"Percentage: {score_data['properties']['score']['percentage']}%")
Security Recommendations
Get and process security recommendations:
def get_security_recommendations(subscription_id, token):
"""Retrieve all security recommendations."""
url = f"https://management.azure.com/subscriptions/{subscription_id}/providers/Microsoft.Security/assessments?api-version=2020-01-01"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
assessments = response.json()
recommendations = []
for assessment in assessments.get("value", []):
props = assessment.get("properties", {})
status = props.get("status", {})
if status.get("code") == "Unhealthy":
recommendations.append({
"name": assessment.get("name"),
"displayName": props.get("displayName"),
"severity": props.get("metadata", {}).get("severity"),
"resourceId": assessment.get("id"),
"remediation": props.get("metadata", {}).get("remediationDescription")
})
return recommendations
# Usage
recommendations = get_security_recommendations(subscription_id, token.token)
print("Unhealthy Assessments:")
for rec in recommendations:
print(f"\n[{rec['severity']}] {rec['displayName']}")
print(f"Remediation: {rec['remediation'][:200]}...")
Just-in-Time VM Access
JIT VM access reduces exposure to attacks by enabling access only when needed:
# Enable JIT on a VM
az security jit-policy create \
--resource-group myResourceGroup \
--location eastus \
--name default \
--virtual-machines '[{
"id": "/subscriptions/{sub-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM",
"ports": [{
"number": 22,
"protocol": "TCP",
"allowedSourceAddressPrefix": "*",
"maxRequestAccessDuration": "PT3H"
}, {
"number": 3389,
"protocol": "TCP",
"allowedSourceAddressPrefix": "*",
"maxRequestAccessDuration": "PT3H"
}]
}]'
# Request JIT access
az security jit-request create \
--resource-group myResourceGroup \
--location eastus \
--name default \
--vm-name myVM \
--port 22 \
--duration PT1H \
--source-ip "203.0.113.10"
Adaptive Application Controls
Configure adaptive application controls using PowerShell:
# Get recommended application control groups
$recommendations = Get-AzSecurityAdaptiveApplicationControl
foreach ($group in $recommendations) {
Write-Host "Group: $($group.GroupName)"
Write-Host "VMs: $($group.VmRecommendations.Count)"
foreach ($rule in $group.PathRecommendations) {
Write-Host " Path: $($rule.Path)"
Write-Host " Publisher: $($rule.Publisher)"
Write-Host " Action: $($rule.Action)"
}
}
# Apply recommended rules
$group = $recommendations[0]
$group.EnforcementMode = "Enforce"
Set-AzSecurityAdaptiveApplicationControl -AdaptiveApplicationControlGroup $group
Container Security
Azure Defender for Container Registries scans images for vulnerabilities:
# Enable scanning for a container registry
az acr update \
--name myContainerRegistry \
--resource-group myResourceGroup \
--enable-security-scanning true
# View scan results
az acr repository show-manifests \
--name myContainerRegistry \
--repository myapp \
--detail
# Query vulnerability findings
az security sub-assessment list \
--assessed-resource-id "/subscriptions/{sub-id}/resourceGroups/myResourceGroup/providers/Microsoft.ContainerRegistry/registries/myContainerRegistry" \
--output table
Integrate vulnerability scanning into your CI/CD pipeline:
# azure-pipelines.yml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Docker@2
inputs:
containerRegistry: 'myACRConnection'
repository: 'myapp'
command: 'buildAndPush'
Dockerfile: '**/Dockerfile'
tags: '$(Build.BuildId)'
- task: AzureCLI@2
displayName: 'Wait for vulnerability scan'
inputs:
azureSubscription: 'MyAzureSubscription'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
# Wait for scan to complete
sleep 60
# Get scan results
VULNERABILITIES=$(az security sub-assessment list \
--assessed-resource-id "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME" \
--query "[?contains(id, '$(Build.BuildId)')].properties.status.severity" \
-o tsv)
# Fail if high severity vulnerabilities found
if echo "$VULNERABILITIES" | grep -q "High"; then
echo "High severity vulnerabilities found!"
exit 1
fi
Security Alerts and Automation
Set up automated responses to security alerts:
# Azure Function to handle security alerts
import logging
import azure.functions as func
from azure.mgmt.compute import ComputeManagementClient
from azure.identity import DefaultAzureCredential
def main(event: func.EventGridEvent):
"""Handle Azure Defender security alerts."""
alert_data = event.get_json()
alert_name = alert_data.get("alertName")
severity = alert_data.get("severity")
resource_id = alert_data.get("resourceIdentifiers", [{}])[0].get("azureResourceId")
logging.info(f"Security Alert: {alert_name}")
logging.info(f"Severity: {severity}")
logging.info(f"Resource: {resource_id}")
# Auto-remediation for specific alerts
if severity == "High":
if "Suspicious process executed" in alert_name:
# Isolate the VM
isolate_vm(resource_id)
elif "Brute force attack" in alert_name:
# Enable JIT access
enable_jit_access(resource_id)
# Send notification
send_teams_notification(alert_data)
def isolate_vm(resource_id):
"""Isolate a VM by removing network connectivity."""
credential = DefaultAzureCredential()
# Parse resource ID
parts = resource_id.split("/")
subscription_id = parts[2]
resource_group = parts[4]
vm_name = parts[8]
compute_client = ComputeManagementClient(credential, subscription_id)
# Get VM
vm = compute_client.virtual_machines.get(resource_group, vm_name)
# Remove all NICs (emergency isolation)
logging.warning(f"Isolating VM: {vm_name}")
# In production, you'd want to:
# 1. Apply NSG rules to block traffic
# 2. Take a snapshot for forensics
# 3. Create incident ticket
def enable_jit_access(resource_id):
"""Enable JIT access policy for a VM."""
logging.info(f"Enabling JIT for: {resource_id}")
# Implementation using Azure Security Center API
def send_teams_notification(alert_data):
"""Send alert to Microsoft Teams."""
import requests
webhook_url = "https://outlook.office.com/webhook/..."
message = {
"@type": "MessageCard",
"themeColor": "FF0000" if alert_data.get("severity") == "High" else "FFA500",
"summary": f"Security Alert: {alert_data.get('alertName')}",
"sections": [{
"activityTitle": alert_data.get("alertName"),
"facts": [
{"name": "Severity", "value": alert_data.get("severity")},
{"name": "Status", "value": alert_data.get("status")},
{"name": "Time", "value": alert_data.get("startTimeUtc")}
]
}]
}
requests.post(webhook_url, json=message)
Regulatory Compliance
Monitor compliance against regulatory standards:
# View available compliance standards
az security regulatory-compliance-standards list --output table
# Get compliance state for a specific standard
az security regulatory-compliance-assessments list \
--standard-name "Azure-CIS-1.1.0" \
--output table
# Export compliance report
az security regulatory-compliance-standards show \
--name "PCI-DSS-3.2.1" \
--query "{
Standard: name,
State: properties.state,
PassedControls: properties.passedControls,
FailedControls: properties.failedControls
}"
Log Analytics Integration
Query security data in Log Analytics:
// High severity security alerts in last 24 hours
SecurityAlert
| where TimeGenerated > ago(24h)
| where AlertSeverity == "High"
| summarize Count = count() by AlertName, ResourceId
| order by Count desc
// Failed login attempts
SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == 4625 // Failed logon
| summarize FailedAttempts = count() by Account, Computer, IpAddress
| where FailedAttempts > 10
| order by FailedAttempts desc
// Suspicious process executions
SecurityAlert
| where AlertName contains "process"
| extend ProcessName = tostring(parse_json(ExtendedProperties).["Process Name"])
| extend CommandLine = tostring(parse_json(ExtendedProperties).["Command Line"])
| project TimeGenerated, Computer, ProcessName, CommandLine, AlertSeverity
Conclusion
Azure Defender for Cloud provides comprehensive security for your Azure and hybrid environments. Key takeaways:
- Enable Azure Defender on critical workloads
- Regularly review and act on security recommendations
- Implement JIT access for VMs
- Integrate container scanning into CI/CD
- Automate response to high-severity alerts
- Monitor compliance continuously
Security is a journey, not a destination. Use Azure Defender as your foundation for a robust cloud security posture.