Identity & Security

Identity & Security Baselines

Identity is the control plane of cloud security. Entra ID provides the authentication foundation, Defender for Cloud monitors your security posture, and Sentinel serves as your SIEM. These services don't just have baselines — they enforce baselines for everything else.

Identity & Security Platform Architecture

graph LR subgraph Identity["Identity Foundation"] PIM[PIM and JIT] ENTRA[Entra ID] CA[Conditional Access] end subgraph Access["Access Surfaces"] ADMIN[Admin Portals] APPS[User and App Access] end subgraph Security["Security Platform"] DFC[Defender for Cloud] MDE[Defender for Endpoint] SENT[Microsoft Sentinel] end subgraph Workloads["Protected Workloads"] W1[Compute] W2[Data] W3[Networking] W4[Messaging] end PIM --> ENTRA ENTRA --> CA CA --> ADMIN CA --> APPS DFC -->|CSPM| W1 DFC -->|CSPM| W2 DFC -->|CSPM| W3 DFC -->|CSPM| W4 MDE -->|EDR| W1 ENTRA -->|Sign-in and Audit Logs| SENT DFC -->|Alerts and Recommendations| SENT style Identity stroke:#4ade80,stroke-width:2px style Access stroke:#22d3ee,stroke-width:2px style Security stroke:#a855f7,stroke-width:2px style Workloads stroke:#22d3ee,stroke-width:2px

Microsoft Entra ID

Cloud identity and access management. Entra ID is unique because it's both a service with its own baseline and the foundation every other service's IM controls depend on. Hardening Entra ID is the single highest-impact security action for any Azure environment.

Baseline Controls

IM✓ Supported

Authentication Methods

○ ManualCustomer
IM✓ Supported

Conditional Access Baseline

○ ManualCustomer
PA✓ Supported

Admin Account Separation

○ ManualCustomer
PA✓ Supported

PIM for Privileged Roles

○ ManualCustomer
PA✓ Supported

Emergency Access

○ ManualCustomer
IM✓ Supported

Identity Protection

○ ManualCustomer
GS✓ Supported

Access Reviews

○ ManualCustomer
LT✓ Supported

Sign-in Logs to SIEM

○ ManualCustomer

Core Security Configuration

DomainConfigurationTarget StateImpact
IM-6Authentication MethodsPhishing-resistant MFA (FIDO2, WHfB, Cert)Critical
IM-7Conditional Access BaselineBlock legacy auth, require MFA all users, device complianceCritical
PA-1Admin Account SeparationDedicated cloud-only admin accounts; no hybrid syncHigh
PA-2PIM for Privileged RolesJIT activation; max 4-hour window; approval required for GACritical
PA-5Emergency Access2+ break-glass accounts; excluded from CA; monitoredCritical
IM-2Identity ProtectionSign-in risk: MFA. User risk: password change. High risk: block.High
GS-6Access ReviewsQuarterly access reviews for privileged roles and group membershipsMedium
LT-2Sign-in Logs to SIEMEntra ID sign-in and audit logs → SentinelHigh

Azure Portal Instructions

Entra ID Baseline Configuration Workflow
  1. Navigate to the Microsoft Entra admin center in the Azure Portal.
  2. Under Protection and Authentication methods, require phishing-resistant MFA such as FIDO2 or Windows Hello for Business.
  3. Create baseline Conditional Access policies to block legacy authentication, require MFA, and protect admin access.
  4. Use Privileged Identity Management to make privileged roles just-in-time and approval-based.
  5. Create and monitor emergency access accounts that are excluded from Conditional Access.
  6. Send sign-in and audit logs to Sentinel or Log Analytics for monitoring and detections.

Terraform: Conditional Access Baseline Policies

hcl
# Note: Conditional Access requires Microsoft Graph provider (azuread)
# These represent the minimum CA policy set for any Azure environment

# Policy 1: Block Legacy Authentication
resource "azuread_conditional_access_policy" "block_legacy" {
  display_name = "CA001 - Block Legacy Authentication"
  state        = "enabled"

  conditions {
    client_app_types = ["exchangeActiveSync", "other"]
    applications { included_applications = ["All"] }
    users { included_users = ["All"] }
  }

  grant_controls {
    built_in_controls = ["block"]
    operator          = "OR"
  }
}

# Policy 2: Require MFA for All Users
resource "azuread_conditional_access_policy" "require_mfa" {
  display_name = "CA002 - Require MFA for All Users"
  state        = "enabled"

  conditions {
    client_app_types = ["browser", "mobileAppsAndDesktopClients"]
    applications { included_applications = ["All"] }
    users {
      included_users  = ["All"]
      excluded_groups = [azuread_group.break_glass.object_id]
    }
  }

  grant_controls {
    built_in_controls = ["mfa"]
    operator          = "OR"
  }
}

# Policy 3: Require Compliant Device for Admin Portals
resource "azuread_conditional_access_policy" "admin_compliant" {
  display_name = "CA003 - Require Compliant Device for Admin Portals"
  state        = "enabled"

  conditions {
    client_app_types = ["browser", "mobileAppsAndDesktopClients"]
    applications {
      included_applications = [
        "797f4846-ba00-4fd7-ba43-dac1f8f63013",  # Azure Portal
        "0000000a-0000-0000-c000-000000000000",  # Intune
      ]
    }
    users { included_roles = ["62e90394-69f5-4237-9190-012177145e10"] }  # Global Admin
  }

  grant_controls {
    built_in_controls = ["compliantDevice", "mfa"]
    operator          = "AND"
  }
}

# Policy 4: Block Access from Untrusted Locations for Privileged Roles
resource "azuread_conditional_access_policy" "block_untrusted_admins" {
  display_name = "CA004 - Block Admins from Untrusted Locations"
  state        = "enabled"

  conditions {
    client_app_types = ["browser", "mobileAppsAndDesktopClients"]
    applications { included_applications = ["All"] }
    users {
      included_roles = [
        "62e90394-69f5-4237-9190-012177145e10",   # Global Admin
        "e8611ab8-c189-46e8-94e1-60213ab1f814",   # Privileged Role Admin
      ]
    }
    locations {
      included_locations = ["All"]
      excluded_locations = [azuread_named_location.trusted.id]
    }
  }

  grant_controls {
    built_in_controls = ["block"]
    operator          = "OR"
  }
}
# Note: Conditional Access requires Microsoft Graph provider (azuread)
# These represent the minimum CA policy set for any Azure environment

# Policy 1: Block Legacy Authentication
resource "azuread_conditional_access_policy" "block_legacy" {
  display_name = "CA001 - Block Legacy Authentication"
  state        = "enabled"

  conditions {
    client_app_types = ["exchangeActiveSync", "other"]
    applications { included_applications = ["All"] }
    users { included_users = ["All"] }
  }

  grant_controls {
    built_in_controls = ["block"]
    operator          = "OR"
  }
}

# Policy 2: Require MFA for All Users
resource "azuread_conditional_access_policy" "require_mfa" {
  display_name = "CA002 - Require MFA for All Users"
  state        = "enabled"

  conditions {
    client_app_types = ["browser", "mobileAppsAndDesktopClients"]
    applications { included_applications = ["All"] }
    users {
      included_users  = ["All"]
      excluded_groups = [azuread_group.break_glass.object_id]
    }
  }

  grant_controls {
    built_in_controls = ["mfa"]
    operator          = "OR"
  }
}

# Policy 3: Require Compliant Device for Admin Portals
resource "azuread_conditional_access_policy" "admin_compliant" {
  display_name = "CA003 - Require Compliant Device for Admin Portals"
  state        = "enabled"

  conditions {
    client_app_types = ["browser", "mobileAppsAndDesktopClients"]
    applications {
      included_applications = [
        "797f4846-ba00-4fd7-ba43-dac1f8f63013",  # Azure Portal
        "0000000a-0000-0000-c000-000000000000",  # Intune
      ]
    }
    users { included_roles = ["62e90394-69f5-4237-9190-012177145e10"] }  # Global Admin
  }

  grant_controls {
    built_in_controls = ["compliantDevice", "mfa"]
    operator          = "AND"
  }
}

# Policy 4: Block Access from Untrusted Locations for Privileged Roles
resource "azuread_conditional_access_policy" "block_untrusted_admins" {
  display_name = "CA004 - Block Admins from Untrusted Locations"
  state        = "enabled"

  conditions {
    client_app_types = ["browser", "mobileAppsAndDesktopClients"]
    applications { included_applications = ["All"] }
    users {
      included_roles = [
        "62e90394-69f5-4237-9190-012177145e10",   # Global Admin
        "e8611ab8-c189-46e8-94e1-60213ab1f814",   # Privileged Role Admin
      ]
    }
    locations {
      included_locations = ["All"]
      excluded_locations = [azuread_named_location.trusted.id]
    }
  }

  grant_controls {
    built_in_controls = ["block"]
    operator          = "OR"
  }
}

Break-Glass Before Lockout

Always create and test emergency access accounts (break-glass) BEFORE enabling Conditional Access policies that block all users. These accounts must be cloud-only, excluded from all CA policies, have long random passwords stored in a physical safe, and be monitored with Sentinel alerts.

Microsoft Defender for Cloud

Cloud Security Posture Management (CSPM) and Cloud Workload Protection (CWP) platform. Defender for Cloud is how you measure and enforce all the baselines in this section — it maps directly to MCSB and provides the secure score, recommendations, and auto-remediation capabilities.

Baseline Controls

GS✓ Supported

CSPM (Free)

● DefaultMicrosoft
PV✓ Supported

Defender CSPM

○ ManualCustomer
ES✓ Supported

Defender for Servers P2

○ ManualCustomer
LT✓ Supported

Defender for SQL

○ ManualCustomer
LT✓ Supported

Defender for Storage

○ ManualCustomer
ES✓ Supported

Defender for Containers

○ ManualCustomer
LT✓ Supported

Defender for App Service

○ ManualCustomer
LT✓ Supported

Defender for Key Vault

○ ManualCustomer
LT✓ Supported

Defender for Cosmos DB

○ ManualCustomer
PlanProtectsKey CapabilitiesPriority
CSPM (Free)All resourcesSecure score, basic recommendations, Azure PolicyAlways On
Defender CSPMAll resourcesAttack path analysis, governance, agentless scanningCritical
Defender for Servers P2VMs, Arc serversMDE, VA, JIT, file integrity monitoringCritical
Defender for SQLSQL DB, MI, on-premThreat protection, vulnerability assessmentCritical
Defender for StorageStorage AccountsMalware scanning, anomalous access detectionHigh
Defender for ContainersAKS, ACR, Arc K8sImage VA, runtime protection, admission controlHigh
Defender for App ServiceApp Service, FunctionsThreat detection, dangling DNS, anomalous callsHigh
Defender for Key VaultKey VaultUnusual access patterns, suspicious operationsHigh
Defender for Cosmos DBCosmos DBInjection detection, anomalous queriesMedium

Azure Portal Instructions

Defender for Cloud Baseline Configuration Workflow
  1. Navigate to Microsoft Defender for Cloud in the Azure Portal.
  2. Open Environment settings and select the subscription or management group you want to secure.
  3. Enable Defender CSPM and the workload protection plans you need, such as Servers, SQL, Storage, Containers, App Service, Key Vault, and Cosmos DB.
  4. Review Recommendations and Secure score to prioritize remediation of baseline gaps.
  5. Configure auto-provisioning, security contacts, and any required monitoring extensions.
  6. Use Azure Policy assignments exposed through Defender for Cloud to enforce baseline settings at scale.

Terraform: Enable All Defender Plans

hcl
# Enable Defender for Cloud plans at subscription level
locals {
  defender_plans = [
    "CloudPosture",        # Defender CSPM
    "VirtualMachines",     # Defender for Servers
    "SqlServers",          # Defender for SQL
    "StorageAccounts",     # Defender for Storage
    "Containers",          # Defender for Containers
    "AppServices",         # Defender for App Service
    "KeyVaults",           # Defender for Key Vault
    "CosmosDbs",          # Defender for Cosmos DB
    "Arm",                 # Defender for Resource Manager
    "Dns",                 # Defender for DNS
  ]
}

resource "azurerm_security_center_subscription_pricing" "plans" {
  for_each      = toset(local.defender_plans)
  tier          = "Standard"
  resource_type = each.value

  # Servers Plan 2 with sub-plan
  dynamic "extension" {
    for_each = each.value == "VirtualMachines" ? ["MdeDesignatedSubscription"] : []
    content {
      name = "MdeDesignatedSubscription"
    }
  }
}

# Auto-provisioning: AMA agent for VMs
resource "azurerm_security_center_auto_provisioning" "ama" {
  auto_provision = "On"
}

# Security contact for alerts
resource "azurerm_security_center_contact" "main" {
  email               = "security-team@company.com"
  phone               = "+1-555-0100"
  alert_notifications = true
  alerts_to_admins    = true
}

# Assign MCSB initiative as default policy
resource "azurerm_subscription_policy_assignment" "mcsb" {
  name                 = "mcsb-default"
  subscription_id      = data.azurerm_subscription.current.id
  policy_definition_id = "/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8"
  display_name         = "Microsoft Cloud Security Benchmark"
}
# Enable Defender for Cloud plans at subscription level
locals {
  defender_plans = [
    "CloudPosture",        # Defender CSPM
    "VirtualMachines",     # Defender for Servers
    "SqlServers",          # Defender for SQL
    "StorageAccounts",     # Defender for Storage
    "Containers",          # Defender for Containers
    "AppServices",         # Defender for App Service
    "KeyVaults",           # Defender for Key Vault
    "CosmosDbs",          # Defender for Cosmos DB
    "Arm",                 # Defender for Resource Manager
    "Dns",                 # Defender for DNS
  ]
}

resource "azurerm_security_center_subscription_pricing" "plans" {
  for_each      = toset(local.defender_plans)
  tier          = "Standard"
  resource_type = each.value

  # Servers Plan 2 with sub-plan
  dynamic "extension" {
    for_each = each.value == "VirtualMachines" ? ["MdeDesignatedSubscription"] : []
    content {
      name = "MdeDesignatedSubscription"
    }
  }
}

# Auto-provisioning: AMA agent for VMs
resource "azurerm_security_center_auto_provisioning" "ama" {
  auto_provision = "On"
}

# Security contact for alerts
resource "azurerm_security_center_contact" "main" {
  email               = "security-team@company.com"
  phone               = "+1-555-0100"
  alert_notifications = true
  alerts_to_admins    = true
}

# Assign MCSB initiative as default policy
resource "azurerm_subscription_policy_assignment" "mcsb" {
  name                 = "mcsb-default"
  subscription_id      = data.azurerm_subscription.current.id
  policy_definition_id = "/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8"
  display_name         = "Microsoft Cloud Security Benchmark"
}

Microsoft Sentinel

Cloud-native SIEM and SOAR platform built on Log Analytics. Sentinel collects all the diagnostic logs from every other baseline, correlates them, applies detection analytics, and orchestrates automated responses. It's the central nervous system of your security operations.

Baseline Controls

LT✓ Supported

Entra ID Connector

○ ManualCustomer
LT✓ Supported

Azure Activity Connector

○ ManualCustomer
LT✓ Supported

Defender for Cloud Connector

○ ManualCustomer
LT✓ Supported

Azure Firewall Connector

○ ManualCustomer
LT✓ Supported

Azure WAF Connector

○ ManualCustomer
LT✓ Supported

Key Vault Connector

○ ManualCustomer
LT✓ Supported

SQL Database Connector

○ ManualCustomer
LT✓ Supported

MDE Connector

○ ManualCustomer
Data ConnectorSourceKey TablesPriority
Entra IDIdentitySigninLogs, AuditLogs, AADRiskyUsersCritical
Azure ActivitySubscriptionAzureActivityCritical
Defender for CloudAll resourcesSecurityAlert, SecurityRecommendationCritical
Azure FirewallNetworkAZFWNetworkRule, AZFWApplicationRuleHigh
Azure WAFEdgeAzureDiagnostics (WAF logs)High
Key VaultSecretsAzureDiagnostics (AuditEvent)High
SQL DatabaseDataSQLSecurityAuditEventsHigh
MDEEndpointsDeviceEvents, DeviceProcessEventsHigh

Azure Portal Instructions

Sentinel Baseline Configuration Workflow
  1. Navigate to Microsoft Sentinel in the Azure Portal and select the target Log Analytics workspace.
  2. Under Data connectors, connect Entra ID, Azure Activity, Defender for Cloud, Azure Firewall, WAF, Key Vault, SQL, and Defender for Endpoint as needed.
  3. Enable the analytics rules, workbooks, and content-hub packages that match your security operations requirements.
  4. Create or tune incidents, automation rules, and playbooks for escalation and response.
  5. Verify that the key log tables are populating before relying on detections.
  6. Review incidents and hunting queries regularly to validate data quality and detection coverage.

Terraform: Sentinel Workspace with Key Connectors

hcl
resource "azurerm_log_analytics_workspace" "sentinel" {
  name                = "law-sentinel-prod"
  resource_group_name = azurerm_resource_group.security.name
  location            = azurerm_resource_group.security.location
  sku                 = "PerGB2018"
  retention_in_days   = 90                    # LT-6: Interactive retention

  # Archive tier for long-term compliance
  # Configure via workspace data export or table-level retention
}

resource "azurerm_sentinel_log_analytics_workspace_onboarding" "main" {
  workspace_id                 = azurerm_log_analytics_workspace.sentinel.id
  customer_managed_key_enabled = false
}

# Data connector: Entra ID (critical)
resource "azurerm_sentinel_data_connector_azure_active_directory" "entra" {
  name                       = "entra-id"
  log_analytics_workspace_id = azurerm_sentinel_log_analytics_workspace_onboarding.main.workspace_id
}

# Data connector: Azure Activity
resource "azurerm_sentinel_data_connector_azure_activity" "activity" {
  name                       = "azure-activity"
  log_analytics_workspace_id = azurerm_sentinel_log_analytics_workspace_onboarding.main.workspace_id
}

# Data connector: Defender for Cloud
resource "azurerm_sentinel_data_connector_azure_security_center" "defender" {
  name                       = "defender-for-cloud"
  log_analytics_workspace_id = azurerm_sentinel_log_analytics_workspace_onboarding.main.workspace_id
}

# Analytics rule: Detect break-glass account usage
resource "azurerm_sentinel_alert_rule_scheduled" "break_glass" {
  name                       = "break-glass-usage"
  display_name               = "Break Glass Account Sign-In Detected"
  log_analytics_workspace_id = azurerm_sentinel_log_analytics_workspace_onboarding.main.workspace_id
  severity                   = "High"
  query_frequency            = "PT5M"
  query_period               = "PT5M"
  trigger_operator           = "GreaterThan"
  trigger_threshold          = 0

  query = <<-QUERY
    SigninLogs
    | where UserPrincipalName in ("breakglass1@company.onmicrosoft.com", "breakglass2@company.onmicrosoft.com")
    | project TimeGenerated, UserPrincipalName, IPAddress, Location, AppDisplayName, ResultType
  QUERY

  entity_mapping {
    entity_type = "Account"
    field_mapping {
      identifier  = "FullName"
      column_name = "UserPrincipalName"
    }
  }

  entity_mapping {
    entity_type = "IP"
    field_mapping {
      identifier  = "Address"
      column_name = "IPAddress"
    }
  }
}
resource "azurerm_log_analytics_workspace" "sentinel" {
  name                = "law-sentinel-prod"
  resource_group_name = azurerm_resource_group.security.name
  location            = azurerm_resource_group.security.location
  sku                 = "PerGB2018"
  retention_in_days   = 90                    # LT-6: Interactive retention

  # Archive tier for long-term compliance
  # Configure via workspace data export or table-level retention
}

resource "azurerm_sentinel_log_analytics_workspace_onboarding" "main" {
  workspace_id                 = azurerm_log_analytics_workspace.sentinel.id
  customer_managed_key_enabled = false
}

# Data connector: Entra ID (critical)
resource "azurerm_sentinel_data_connector_azure_active_directory" "entra" {
  name                       = "entra-id"
  log_analytics_workspace_id = azurerm_sentinel_log_analytics_workspace_onboarding.main.workspace_id
}

# Data connector: Azure Activity
resource "azurerm_sentinel_data_connector_azure_activity" "activity" {
  name                       = "azure-activity"
  log_analytics_workspace_id = azurerm_sentinel_log_analytics_workspace_onboarding.main.workspace_id
}

# Data connector: Defender for Cloud
resource "azurerm_sentinel_data_connector_azure_security_center" "defender" {
  name                       = "defender-for-cloud"
  log_analytics_workspace_id = azurerm_sentinel_log_analytics_workspace_onboarding.main.workspace_id
}

# Analytics rule: Detect break-glass account usage
resource "azurerm_sentinel_alert_rule_scheduled" "break_glass" {
  name                       = "break-glass-usage"
  display_name               = "Break Glass Account Sign-In Detected"
  log_analytics_workspace_id = azurerm_sentinel_log_analytics_workspace_onboarding.main.workspace_id
  severity                   = "High"
  query_frequency            = "PT5M"
  query_period               = "PT5M"
  trigger_operator           = "GreaterThan"
  trigger_threshold          = 0

  query = <<-QUERY
    SigninLogs
    | where UserPrincipalName in ("breakglass1@company.onmicrosoft.com", "breakglass2@company.onmicrosoft.com")
    | project TimeGenerated, UserPrincipalName, IPAddress, Location, AppDisplayName, ResultType
  QUERY

  entity_mapping {
    entity_type = "Account"
    field_mapping {
      identifier  = "FullName"
      column_name = "UserPrincipalName"
    }
  }

  entity_mapping {
    entity_type = "IP"
    field_mapping {
      identifier  = "Address"
      column_name = "IPAddress"
    }
  }
}

Sentinel Content Hub

Don't build detection rules from scratch. Install Sentinel Content Hub solutions for Azure, Entra ID, Microsoft 365, and Defender XDR. These include pre-built analytics rules, hunting queries, workbooks, and playbooks maintained by Microsoft and the community.