Pide tu presupuesto ya!
Su auditoría SOC 2 es en ocho semanas. Abres el panel de cumplimiento en Microsoft Defender para la nubey muestra 214 recursos no conformes en tres suscripciones. Nadie sabe quién posee la mitad de ellos. La hoja de cálculo que su equipo utilizó para rastrear la evidencia el año pasado está obsoleta, el informe MFA que alguien realizó en enero ya expiró y su auditor quiere 12 meses de datos, no 90 días. ¿Esa sensación de hundimiento? Así es como se siente el cumplimiento por hoja de cálculo a escala.
La buena noticia: no es necesario vivir allí. Política de Azureel Marco de política empresarial como código (EPAC)y un puñado de scripts de PowerShell pueden cambiar su postura de cumplimiento de una lucha reactiva contra incendios a una línea de base que se aplica continuamente. Este tutorial le muestra cómo construir ese sistema, desde asignar la iniciativa SOC 2 hasta automatizar la recopilación de evidencia antes de que se abra la próxima ventana de auditoría.
SOC 2desarrollado por el Instituto Americano de Contadores Públicos Certificados (AICPA)es un estándar de certificación de seguridad y disponibilidad. Un informe SOC 2 Tipo 2 (la versión que interesa a los auditores) no se limita a verificar que existen controles. Verifica que los controles operaron eficazmente durante un período de observación definido, generalmente de seis a doce meses. Esa distinción importa. Las capturas de pantalla únicas no son suficientes. Necesita evidencia continua, fechada y reproducible.
SOC 2 organiza los requisitos en torno a Criterios de Servicios de Confianza (TSC)que se asignan a áreas como acceso lógico, monitoreo del sistema y gestión de cambios. Para su entorno de Azure, los criterios más relevantes tienen este aspecto:
| Criterios SOC 2 | Qué cubre | Característica de Azure que lo soluciona |
|---|---|---|
| CC6.1 — Acceso lógico | ¿Quién puede acceder a qué? ¿Se aplica la MFA? | ID de entrada de Microsoft, Control de acceso basado en roles (RBAC), Gestión de identidad privilegiada |
| CC7.1 — Gestión de configuración | Recursos configurados según los estándares básicos | Política de Azure |
| CC7.2 — Monitoreo | Alertas, detección de anomalías y revisión continua | Microsoft Defender para la nube, monitor azul |
| CC6.8 — Gestión del cambio | Implementaciones controladas con pistas de auditoría | EPAC a través de canales de CI/CD |
| A1.2 — Disponibilidad | Configuraciones de respaldo y recuperación | Copia de seguridad de Azure políticas a través de Azure Policy |
Esto es lo fundamental que su auditor no dirá abiertamente: el propio informe SOC 2 de Microsoft cubre el centro de datos físico, la capa de red y el hipervisor. No cubre lo que construyes encima. La gestión de identidades, la configuración de cifrado y los grupos de seguridad de red son su responsabilidad. Mostrar al auditor el informe de Microsoft y esperar que cierre un hallazgo no funcionará. Su auditor sabe exactamente dónde termina el alcance de Microsoft y comienza el suyo.
Verificación de la realidad: el estado de cumplimiento de Azure Policy solo refleja la configuración técnica. Un recurso marcado como “Cumple” significa que la definición de política fue aprobada; no significa que su aplicación tenga la certificación SOC 2. La política maneja la capa de infraestructura. Los controles de procedimiento, como el proceso de baja de empleados, aún necesitan documentación por separado.
Azure proporciona una iniciativa incorporada denominada “Cumplimiento normativo SOC 2 Tipo 2” que asigna docenas de definiciones de políticas individuales a los controles de TSC. Este es tu punto de partida.
Antes de asignarlo, confirme que tiene el módulo Az instalado y una conexión a su suscripción de Azure:
Install-Module -Name Az -Scope CurrentUser -Force Connect-AzAccount
Para asignar la iniciativa SOC 2 a una suscripción, busque la definición integrada y cree la asignación:
# Get the built-in SOC 2 Type 2 initiative
$initiative = Get-AzPolicySetDefinition |
Where-Object { $_.Properties.DisplayName -like "*SOC 2*" }
# Assign to the current subscription
$scope = "/subscriptions/$($(Get-AzContext).Subscription.Id)"
New-AzPolicyAssignment `
-Name "soc2-compliance-assignment" `
-DisplayName "SOC 2 Type 2 Compliance" `
-Scope $scope `
-PolicySetDefinition $initiative
Después de la asignación, Azure Policy ejecuta un análisis de cumplimiento en todos los recursos existentes. Un problema importante: el escaneo inicial tarda aproximadamente 24 horas en completarse. No entre en pánico cuando el panel muestre “No iniciado” durante la primera mitad del día.
Una vez finalizado el escaneo, el Panel de cumplimiento normativo en Microsoft Defender para la nube muestra su estado de cumplimiento organizado por control TSC. Puede exportar los resultados como PDF o CSV, lo cual es útil como instantánea, pero no sustituye a la recopilación continua automatizada.
Consejo profesional: si asigna esta iniciativa a varias suscripciones, hágalo desde el alcance del grupo de administración en lugar de por suscripción. Esa única tarea cubre todo lo que hay debajo y le brinda una vista de cumplimiento en toda su jerarquía.
Hacer clic en Azure Portal para asignar políticas funciona bien para una suscripción. Todo se desmorona cuando tienes cinco suscripciones, un entorno de prueba y un equipo de seguridad que quiere saber qué cambió y por qué. Ahí es donde Política empresarial como código (EPAC) entra.
EPAC es un módulo de PowerShell de código abierto que trata a Azure Policy como código de infraestructura. Todas las políticas, asignaciones y exenciones se encuentran en archivos JSON en un repositorio de Git. Los cambios pasan por solicitudes de extracción. Las canalizaciones de CI/CD las implementan. Si alguien ajusta manualmente una política en el portal, la siguiente ejecución del canal detecta la desviación y la revierte.
Instale el módulo y cree la estructura del directorio:
Install-Module -Name EnterprisePolicyAsCode -Scope CurrentUser -Force New-EPACDefinitionFolder -DefinitionsRootFolder "./Definitions"
Eso genera una estructura de carpetas como esta:
“`texto sin formato
Definiciones/
├── global-settings.jsonc # Ámbitos y entornos de inquilinos
├── PolicyDefinitions/ # Definiciones de políticas personalizadas
├── PolicySetDefinitions/# Iniciativas (incluido su mapeo SOC 2)
├── PolicyAssignments/ # Dónde se asignan políticas a grupos de administración o suscripciones
└── PolicyExemptions/# Excepciones documentadas con motivos
The `global-settings.jsonc` file is where you define which tenants and management group scopes EPAC manages. The `policyAssignments/` folder contains JSON files that describe which initiatives are assigned to which scopes — including the SOC 2 initiative you applied earlier. EPAC follows a two-step deployment model. First, build the plan:
Planes de implementación de compilación -Carpeta raíz de definiciones “./Definiciones” -Carpeta de salida “./Salida”
This analyzes your JSON files against the live Azure environment and generates a plan showing what will be created, updated, or deleted — similar to `terraform plan`. Review it before you apply anything. Second, deploy:
Implementar-Plan de políticas -Carpeta de salida “./Salida”
Implementar-Plan de roles -Carpeta de salida “./Salida”
`Deploy-RolesPlan` handles one of EPAC's more useful features: when a policy uses `DeployIfNotExists` effects (like automatically enabling Azure Backup), it calculates and assigns the Managed Identity roles that policy needs. Without this step, those policies would fail silently. | EPAC Command | What It Does | When to Run | | --- | --- | --- | | `Build-DeploymentPlans` | Compares JSON definitions to live Azure state, generates a plan | Every PR, before any deployment | | `Deploy-PolicyPlan` | Applies policy definitions, set definitions, and assignments | After plan review and approval | | `Deploy-RolesPlan` | Assigns roles needed by DeployIfNotExists policies | After `Deploy-PolicyPlan`, same pipeline | The exemptions feature is worth noting specifically for SOC 2. Your auditor will ask why certain resources show non-compliant. With EPAC, the answer lives in your `policyExemptions/` folder — a JSON file with the exemption reason, who approved it, and when it expires. That's the audit trail your auditor wants. "We turned it off in the portal" is not. ## Collecting Evidence with PowerShell Azure Policy tells you what's compliant or not. But auditors want evidence in a format they can review — typically CSV exports that show a point-in-time state for specific criteria. Not all compliance data maps cleanly to a policy definition. MFA status, for example, doesn't surface in Azure Policy at all. For that, you need the [Microsoft Graph PowerShell SDK](https://learn.microsoft.com/en-us/powershell/microsoftgraph/overview). ### Exporting Non-Compliant Resources For any TSC control backed by an Azure Policy definition, `Get-AzPolicyState` gives you the current compliance state across your subscription. Export non-compliant resources to CSV for your auditor packet:
Connect-AzAccount
Get-AzPolicyState -Filter “ComplianceState eq ‘No conforme’” |
Seleccionar objeto `
grupo de recursos,
@{N=’NombreRecurso’; mi={$.ResourceId.Split(‘/’)[-1] }},
Nombre de definición de política,
Estado de cumplimiento,
Marca de tiempo |
Exportar-Csv -Ruta “SOC2_NonCompliance$(Get-Date -Format ‘aaaaMMdd’).csv” -NoTypeInformation
Run this as part of a scheduled [Azure Automation](https://learn.microsoft.com/en-us/azure/automation/overview) runbook or a CI/CD pipeline step so the output is generated consistently throughout your observation period — not just the week before an audit. ### Auditing MFA Status for CC6.1 Logical access control (CC6.1) requires evidence that all users have multi-factor authentication enforced. The `Get-MsolUser` cmdlet is deprecated. The correct approach is the [Microsoft Graph PowerShell SDK](https://learn.microsoft.com/en-us/powershell/microsoftgraph/overview), querying the `authenticationMethods` endpoint:
Módulo de instalación -Nombre Microsoft.Graph -Alcance Usuario actual -Force
Connect-MgGraph -Ámbitos “User.Read.All”, “UserAuthenticationMethod.Read.All”
$informe = Get-MgUser -All | Para cada objeto {
$métodos = Get-MgUserAuthenticationMethod -UserId $.Identificación
$métodosfuertes = $métodos | Donde-Objeto {
$.Propiedades adicionales[‘@odata.type’] -no me gusta “contraseña“
}
[PSCustomObject]@{
Nombre para mostrar = $.Nombre para mostrar
Nombre principal de usuario = $.Nombre principal de usuario
MFARegistado = ($strongMethods.Count -gt 0)
MethodCount = $strongMethods.Count
}
}
$informe | Export-Csv -Ruta “MFA_Status_$(Get-Date -Format ‘yyyyMMdd’).csv” -NoTypeInformation
A Graph query with `User.Read.All` and `UserAuthenticationMethod.Read.All` scopes returns each user's registered authentication methods. If only `PasswordAuthentication` is present, MFA is not registered — that user shows up as a finding. --- ***Warning: The ******`Get-MgUser -All`****** call can be slow in large tenants. For tenants with thousands of users, consider filtering by a specific group or using the ******`$filter`****** parameter to scope the query. Running an unfiltered query against 50,000 accounts will time out.*** --- ### Querying Infrastructure with Azure Resource Graph For broader infrastructure evidence — like "list all SQL servers with public network access enabled" — [Azure Resource Graph](https://learn.microsoft.com/en-us/azure/governance/resource-graph/overview) is faster than looping through `Get-AzResource` across subscriptions. The `Search-AzGraph` cmdlet queries the Resource Graph API directly:
$consulta = @”
Recursos
| donde escriba =~ ‘microsoft.sql/servers’
| donde properties.publicNetworkAccess =~ ‘Habilitado’
| nombre del proyecto, grupo de recursos, ID de suscripción, ubicación
“@
$resultados = Search-AzGraph -Consulta $consulta -Primeros 1000
mientras ($resultados.SkipToken) {
$nextPage = Search-AzGraph -Consulta $consulta -Primeros 1000 -SkipToken $resultados.SkipToken
$resultados += $páginasiguiente
}
$resultados | Export-Csv -Ruta “SQL_PublicAccess_$(Get-Date -Format ‘yyyyMMdd’).csv” -NoTypeInformation
Note the explicit pagination handling. By default, `Search-AzGraph` returns up to 1,000 records. In an enterprise environment with hundreds of SQL servers across dozens of subscriptions, you will hit that limit and silently miss resources without the `SkipToken` loop. | Evidence Script | TSC Criteria | PowerShell Module Required | | --- | --- | --- | | `Get-AzPolicyState` export | CC7.1, CC7.2, A1.2 | Az.PolicyInsights | | MFA status report | CC6.1 | Microsoft.Graph | | Resource Graph queries | CC6.1, CC7.1 | Az.ResourceGraph | ## Retaining Evidence for the Full Observation Period Default Activity Log retention in Azure is 90 days. SOC 2 Type 2 auditors want 6-12 months of data. Those two facts in combination have ended more than a few audits badly. [Microsoft Defender for Cloud's Continuous Export feature](https://learn.microsoft.com/en-us/azure/defender-for-cloud/continuous-export) streams security alerts, compliance recommendations, and secure score data to an Azure Log Analytics Workspace or Event Hub. That data persists as long as your workspace retention policy allows — which you should set to at least 365 days for any workspace receiving compliance evidence. Configure Continuous Export via Azure Policy so it can't be accidentally disabled:
$continuousExportPolicy = Get-AzPolicyDefinition |
Donde-Objeto { $_.Properties.DisplayName -like “Exportación continuaAnálisis de registros*” }
Nueva asignación de política Az -Name "enforce-continuous-export"
-DisplayName “Enforce Defender para exportación continua a la nube” -Scope $scope
-PolicyDefinition $continuousExportPolicy `
-PolicyParameterObject @{
workspaceResourceId = “/suscripciones/
}
“`
Con la exportación continua en ejecución, su espacio de trabajo de Log Analytics acumula un registro consultable e inmutable de los cambios en el estado de cumplimiento a lo largo del tiempo. Cuando su auditor le pregunta “muéstreme que la MFA se aplicó durante todo el período de observación”, usted tiene Lenguaje de consulta Kusto (KQL) resultados de la consulta, no una hoja de cálculo del martes pasado.
Una consideración de costos sobre la que vale la pena ser sincero: la ingesta de datos de Log Analytics y la retención a largo plazo son facturables. El nivel CSPM fundamental de Defender for Cloud es gratuito, pero la transmisión de datos de registro de gran volumen a un espacio de trabajo suma. Revisa el Precios de análisis de registros antes de habilitar esto en todos los espacios de trabajo en un entorno grande.
Desarrolle esto por etapas en lugar de intentar configurar todo a la vez. Una secuencia razonable:
Asigne la iniciativa SOC 2 al alcance de su grupo de administración y deje que se complete el primer análisis.
Instale EPAC y migre la asignación al código para que esté controlada por versiones
Configure la exportación continua a Log Analytics con una política de retención de 365 días
Agregar los scripts de evidencia de PowerShell a un runbook de Azure Automation según una programación semanal
Conecte la implementación de EPAC a su canal de CI/CD para que la desviación de políticas se detecte automáticamente
Para cuando se abra su próxima ventana de auditoría, tendrá meses de registros de evidencia limpios, un historial de git que muestra quién cambió qué política y cuándo, y un panel de cumplimiento que refleja el estado real de la infraestructura; no es una suposición esperanzadora. Su auditor recibe un paquete de exportaciones CSV fechadas y un registro de exención bien documentado. Puedes saltarte la lucha de ocho semanas.
La hoja de cálculo que rastreó todo el año pasado finalmente puede retirarse.
Leave a comment