# Wazuh Azure - Microsoft Azure Security Monitoring

> Configure Microsoft Azure monitoring in Wazuh 4.14 - Activity Logs, Log Analytics, Microsoft Graph API, app registration, and azure-logs wodle setup

Source: https://opennix.org/en/docs/wazuh/cloud-security/wazuh-azure-monitoring/


Wazuh provides security monitoring for Microsoft Azure through the `azure-logs` module, which collects activity logs, Log Analytics data, and Microsoft Graph API events. The module tracks user actions within Azure subscriptions, resource changes, Microsoft Entra ID authentication events, and data from Azure Blob Storage. This integration delivers a single point of analysis for cloud threats in hybrid environments.

## Supported Data Sources

The `azure-logs` module collects data from three primary sources:

| Source | Data Type | Purpose |
|--------|-----------|---------|
| Activity Logs | Subscription logs | Resource operations, management actions, diagnostics |
| Log Analytics | Analytical queries | Event aggregation from various Azure sources |
| Microsoft Graph API | Microsoft Entra ID API | Authentication audit, user management, policies |

The module additionally supports:

- **Azure Blob Storage** - log collection from Blob Storage containers
- **Microsoft Intune** - device management and compliance policy monitoring

## Azure AD Application Registration

The module requires a registered application in Microsoft Entra ID (Azure Active Directory) with credentials for API access.

### Registration Procedure

1. Navigate to **Microsoft Entra ID - App registrations - New registration**
2. Enter the application name (for example, `Wazuh-Azure-Monitor`)
3. Select the supported account types (Single tenant for a single tenant)
4. Record the following values:
   - **Application (client) ID** - the application identifier
   - **Directory (tenant) ID** - the tenant identifier

### Creating a Client Secret

1. Navigate to **Certificates & Secrets - New client secret**
2. Provide a description and expiration period
3. Copy the secret value (displayed only once)

### Assigning Permissions

For Log Analytics and Activity Logs:
- Assign the **Reader** role at the Azure subscription level

For Microsoft Graph API:
- Navigate to **API permissions - Add a permission - Microsoft Graph**
- Add `AuditLog.Read.All` and `Directory.Read.All` permissions (Application type)
- Grant admin consent

## Module Configuration (azure-logs)

The module is configured in `ossec.conf` on the Wazuh server or agent. Credentials are stored in separate files.

### Credential File

Create the file `/var/ossec/wodles/credentials/azure_credentials`:

```
application_id = YOUR_APPLICATION_ID
application_key = YOUR_CLIENT_SECRET
```

For Azure Storage, create a separate file `/var/ossec/wodles/credentials/storage_credentials`:

```
account_name = YOUR_STORAGE_ACCOUNT
account_key = YOUR_STORAGE_KEY
```

Set permissions:

```bash
sudo chown root:wazuh /var/ossec/wodles/credentials/azure_credentials
sudo chmod 640 /var/ossec/wodles/credentials/azure_credentials
```

### Log Analytics Configuration

```xml
<wodle name="azure-logs">
  <disabled>no</disabled>
  <run_on_start>yes</run_on_start>

  <log_analytics>
    <auth_path>/var/ossec/wodles/credentials/azure_credentials</auth_path>
    <tenantdomain>mycompany.onmicrosoft.com</tenantdomain>
    <request>
      <query>AzureActivity</query>
      <workspace>12345678-90ab-cdef-1234-567890abcdef</workspace>
      <time_offset>1d</time_offset>
    </request>
  </log_analytics>
</wodle>
```

### Microsoft Graph API Configuration

```xml
<wodle name="azure-logs">
  <disabled>no</disabled>
  <run_on_start>yes</run_on_start>

  <graph>
    <auth_path>/var/ossec/wodles/credentials/azure_credentials</auth_path>
    <tenantdomain>mycompany.onmicrosoft.com</tenantdomain>
    <request>
      <query>auditLogs/directoryAudits</query>
      <time_offset>1d</time_offset>
    </request>
    <request>
      <query>auditLogs/signIns</query>
      <time_offset>1d</time_offset>
    </request>
  </graph>
</wodle>
```

### Azure Storage Configuration

```xml
<wodle name="azure-logs">
  <disabled>no</disabled>
  <run_on_start>yes</run_on_start>

  <storage>
    <auth_path>/var/ossec/wodles/credentials/storage_credentials</auth_path>
    <container name="insights-activity-logs">
      <blobs>.json</blobs>
      <content_type>json_inline</content_type>
      <time_offset>24h</time_offset>
    </container>
  </storage>
</wodle>
```

### Combined Configuration

```xml
<wodle name="azure-logs">
  <disabled>no</disabled>
  <run_on_start>yes</run_on_start>

  <log_analytics>
    <auth_path>/var/ossec/wodles/credentials/azure_credentials</auth_path>
    <tenantdomain>mycompany.onmicrosoft.com</tenantdomain>
    <request>
      <query>AzureActivity | where Level == "Error"</query>
      <workspace>12345678-90ab-cdef-1234-567890abcdef</workspace>
      <time_offset>12h</time_offset>
    </request>
  </log_analytics>

  <graph>
    <auth_path>/var/ossec/wodles/credentials/azure_credentials</auth_path>
    <tenantdomain>mycompany.onmicrosoft.com</tenantdomain>
    <request>
      <query>auditLogs/signIns</query>
      <time_offset>1d</time_offset>
    </request>
  </graph>
</wodle>
```

### Module Parameters

| Parameter | Description |
|-----------|-------------|
| `disabled` | Enable or disable the module (no/yes) |
| `run_on_start` | Execute on service startup (yes/no) |
| `auth_path` | Path to the credential file |
| `tenantdomain` | Azure AD tenant domain name |
| `query` | Log Analytics query (KQL) or Graph API resource |
| `workspace` | Log Analytics workspace identifier |
| `time_offset` | Time window for the query (1d, 12h, 1h) |
| `content_type` | Data format in Blob Storage (json_inline, json_file) |

## Log Analytics Integration

Azure Log Analytics Workspace aggregates data from various Azure sources. The Wazuh module executes KQL (Kusto Query Language) queries against the workspace to extract events.

### Obtaining the Workspace ID

1. Navigate to **Log Analytics workspaces** in the Azure portal
2. Select the workspace
3. Copy the **Workspace ID** from the Overview section

### Useful KQL Queries

Activity errors query:

```
AzureActivity | where Level == "Error"
```

Security events query:

```
SecurityEvent | where EventID == 4625
```

Resource changes query:

```
AzureActivity | where OperationNameValue contains "write" or OperationNameValue contains "delete"
```

## Alert Examples

### Suspicious Azure AD Sign-In

```json
{
  "rule": {
    "id": "62503",
    "level": 5,
    "description": "Azure AD: Sign-in from unusual location"
  },
  "data": {
    "azure": {
      "category": "SignInLogs",
      "operationName": "Sign-in activity",
      "properties": {
        "userPrincipalName": "user@company.com",
        "ipAddress": "198.51.100.42",
        "location": {
          "countryOrRegion": "CN"
        },
        "status": {
          "errorCode": 0,
          "additionalDetails": "MFA completed"
        }
      }
    }
  }
}
```

### Critical Resource Modification

```json
{
  "rule": {
    "id": "62510",
    "level": 7,
    "description": "Azure: Critical resource modification detected"
  },
  "data": {
    "azure": {
      "operationName": "Microsoft.Network/networkSecurityGroups/write",
      "category": "Administrative",
      "caller": "admin@company.com",
      "properties": {
        "statusCode": "Created",
        "resource": "production-nsg"
      }
    }
  }
}
```

### Compliance Policy Violation

```json
{
  "rule": {
    "id": "62520",
    "level": 6,
    "description": "Azure Policy: Non-compliant resource detected"
  },
  "data": {
    "azure": {
      "operationName": "Microsoft.Authorization/policyAssignments/write",
      "category": "Policy",
      "properties": {
        "complianceState": "NonCompliant",
        "policyDefinitionName": "require-tag-on-resources"
      }
    }
  }
}
```

## Use Cases

### Detecting Suspicious Sign-Ins

- Sign-ins from atypical geographic locations
- Multiple failed authentication attempts
- Sign-ins from anonymous IP addresses (Tor, VPN)
- Sign-ins from devices without MFA when an MFA policy is active

### Monitoring Resource Changes

- Virtual machine creation or deletion
- Network Security Group rule modifications
- Key Vault access policy changes
- Subscription setting modifications

### Compliance Control

- Tracking resources missing mandatory tags
- Monitoring unencrypted data stores
- Controlling privileged Azure RBAC role assignments
- Tracking Azure Policy deviations

## Troubleshooting

### Module Cannot Connect to Azure

- Verify that the Application ID and Client Secret are correct
- Confirm the secret has not expired
- Check that the required permissions are assigned to the application
- Ensure admin consent has been granted

### Empty Log Analytics Results

- Verify the Workspace ID is correct
- Confirm the workspace contains data for the requested period
- Test the KQL query in the Azure Portal (Log Analytics - Logs)
- Check the `time_offset` value to ensure it covers a period with data

### Microsoft Graph Authentication Errors

- Verify that API permissions are assigned as Application type, not Delegated
- Confirm admin consent has been granted
- Check that the tenant domain is specified correctly
- Review `/var/ossec/logs/ossec.log` for HTTP error details

### Python Dependencies

The module requires Python 3.8-3.13 and additional libraries:

```bash
/var/ossec/framework/python/bin/pip3 install azure-storage-blob azure-identity
```

## Related Sections

- [Cloud Security Monitoring](/docs/wazuh/cloud-security/) - overview of cloud integrations
- [Office 365](/docs/wazuh/cloud-security/wazuh-office365-monitoring/) - Microsoft 365 monitoring (uses Azure AD)
- [Wazuh Capabilities](/docs/wazuh/capabilities/) - platform security modules

