# Wazuh Office 365 - Microsoft 365 Audit Monitoring

> Configure Office 365 monitoring in Wazuh 4.14 - Management Activity API, Azure AD app registration, office365 wodle configuration, and content types

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


Wazuh provides security monitoring for Microsoft 365 through the `office365` module, which collects audit logs from the Office 365 Management Activity API. The module tracks user actions across Exchange Online, SharePoint Online, Microsoft Teams, Azure Active Directory, and DLP events. This integration enables detection of suspicious sign-ins, unauthorized mailbox access, DLP policy violations, and administrative actions within a Microsoft 365 tenant.

## Office 365 Management Activity API

The Office 365 Management Activity API is a REST API that provides access to audit and activity logs from various Microsoft 365 services. The API uses a subscription model: the client subscribes to specific content types and periodically requests new events.

### Content Types

| Content Type | Description |
|-------------|-------------|
| `Audit.AzureActiveDirectory` | Authentication events, user and group management in Microsoft Entra ID |
| `Audit.Exchange` | Mailbox operations, transport rules, anti-spam actions |
| `Audit.SharePoint` | File operations, site management, permission changes in SharePoint and OneDrive |
| `Audit.General` | Workload events not covered by other categories (Teams, Power BI) |
| `DLP.All` | Data Loss Prevention policy triggers for Exchange, SharePoint, and OneDrive |

## Azure AD Application Registration

The module requires a registered application in Microsoft Entra ID with permissions to access the Management Activity API.

### Registration Procedure

1. Navigate to [portal.azure.com](https://portal.azure.com) and open **Microsoft Entra ID - App registrations**
2. Select **New registration**
3. Provide a name (for example, `Wazuh-Office365-Monitor`)
4. Select **Accounts in this organizational directory only** (Single tenant)
5. Record the values from the Overview section:
   - **Application (client) ID**
   - **Directory (tenant) ID**

### Creating a Client Secret

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

### Assigning API Permissions

1. Navigate to **API permissions - Add a permission**
2. Select **Office 365 Management APIs**
3. Select **Application permissions**
4. Add the following permissions:

| Permission | Description |
|-----------|-------------|
| `ActivityFeed.Read` | Read activity data for your organization |
| `ActivityFeed.ReadDlp` | Read DLP policy events including detected sensitive data |

5. Select **Grant admin consent for [Your Organization]**

## Module Configuration (office365)

The module is configured in `ossec.conf` on the Wazuh server.

### Basic Configuration

```xml
<office365>
  <enabled>yes</enabled>
  <interval>1m</interval>
  <curl_max_size>1M</curl_max_size>
  <only_future_events>yes</only_future_events>
  <api_auth>
    <tenant_id>YOUR_TENANT_ID</tenant_id>
    <client_id>YOUR_CLIENT_ID</client_id>
    <client_secret>YOUR_CLIENT_SECRET</client_secret>
    <api_type>commercial</api_type>
  </api_auth>
  <subscriptions>
    <subscription>Audit.AzureActiveDirectory</subscription>
    <subscription>Audit.Exchange</subscription>
    <subscription>Audit.SharePoint</subscription>
    <subscription>Audit.General</subscription>
    <subscription>DLP.All</subscription>
  </subscriptions>
</office365>
```

### Government Cloud Configuration (GCC)

```xml
<office365>
  <enabled>yes</enabled>
  <interval>5m</interval>
  <curl_max_size>1M</curl_max_size>
  <only_future_events>yes</only_future_events>
  <api_auth>
    <tenant_id>YOUR_TENANT_ID</tenant_id>
    <client_id>YOUR_CLIENT_ID</client_id>
    <client_secret>YOUR_CLIENT_SECRET</client_secret>
    <api_type>gcc-high</api_type>
  </api_auth>
  <subscriptions>
    <subscription>Audit.AzureActiveDirectory</subscription>
    <subscription>Audit.Exchange</subscription>
  </subscriptions>
</office365>
```

### Multi-Tenant Configuration

When monitoring multiple Microsoft 365 tenants, add multiple `api_auth` blocks:

```xml
<office365>
  <enabled>yes</enabled>
  <interval>1m</interval>
  <curl_max_size>1M</curl_max_size>
  <only_future_events>yes</only_future_events>
  <api_auth>
    <tenant_id>TENANT_ID_1</tenant_id>
    <client_id>CLIENT_ID_1</client_id>
    <client_secret>CLIENT_SECRET_1</client_secret>
    <api_type>commercial</api_type>
  </api_auth>
  <api_auth>
    <tenant_id>TENANT_ID_2</tenant_id>
    <client_id>CLIENT_ID_2</client_id>
    <client_secret>CLIENT_SECRET_2</client_secret>
    <api_type>commercial</api_type>
  </api_auth>
  <subscriptions>
    <subscription>Audit.AzureActiveDirectory</subscription>
    <subscription>Audit.General</subscription>
  </subscriptions>
</office365>
```

### Module Parameters

| Parameter | Default | Description |
|-----------|---------|-------------|
| `enabled` | yes | Enable or disable the module |
| `interval` | 10m | API polling interval (s/m/h/d) |
| `curl_max_size` | 1M | Maximum API response size |
| `only_future_events` | yes | Collect only new events after the first run |
| `tenant_id` | - | Azure AD tenant identifier |
| `client_id` | - | Application (client) identifier |
| `client_secret` | - | Client secret value |
| `api_type` | commercial | Subscription type (commercial, gcc, gcc-high) |

### API Endpoints by Subscription Type

| Type | URL |
|------|-----|
| Enterprise | `https://manage.office.com/api/v1.0/{tenant_id}/activity/feed/{operation}` |
| GCC | `https://manage-gcc.office.com/api/v1.0/{tenant_id}/activity/feed/{operation}` |
| GCC High | `https://manage.office365.us/api/v1.0/{tenant_id}/activity/feed/{operation}` |
| DoD | `https://manage.protection.apps.mil/api/v1.0/{tenant_id}/activity/feed/{operation}` |

## Alert Examples

### Suspicious Sign-In Activity

```json
{
  "rule": {
    "id": "91545",
    "level": 6,
    "description": "Office 365: Suspicious sign-in activity detected"
  },
  "data": {
    "office365": {
      "Workload": "AzureActiveDirectory",
      "Operation": "UserLoginFailed",
      "UserId": "user@company.com",
      "ClientIP": "198.51.100.42",
      "ResultStatus": "Failed",
      "LogonError": "InvalidUserNameOrPassword",
      "DeviceProperties": {
        "OS": "Windows 10",
        "BrowserType": "Chrome"
      }
    }
  }
}
```

### Non-Owner Mailbox Access

```json
{
  "rule": {
    "id": "91550",
    "level": 7,
    "description": "Office 365: Mailbox accessed by non-owner"
  },
  "data": {
    "office365": {
      "Workload": "Exchange",
      "Operation": "MailboxLogin",
      "UserId": "admin@company.com",
      "MailboxOwnerUPN": "ceo@company.com",
      "ClientIP": "10.0.1.50",
      "LogonType": 1,
      "ResultStatus": "Succeeded"
    }
  }
}
```

### DLP Policy Violation

```json
{
  "rule": {
    "id": "91560",
    "level": 10,
    "description": "Office 365: DLP policy violation detected"
  },
  "data": {
    "office365": {
      "Workload": "Exchange",
      "Operation": "DlpRuleMatch",
      "UserId": "user@company.com",
      "PolicyDetails": [{
        "PolicyName": "Credit Card Number Detection",
        "Rules": [{
          "RuleName": "Block external sharing of credit cards",
          "Severity": "High",
          "ConditionsMatched": {
            "SensitiveInformation": [{
              "SensitiveInformationTypeName": "Credit Card Number",
              "Count": 3
            }]
          }
        }]
      }]
    }
  }
}
```

### Administrative Action

```json
{
  "rule": {
    "id": "91570",
    "level": 8,
    "description": "Office 365: Admin role assigned to user"
  },
  "data": {
    "office365": {
      "Workload": "AzureActiveDirectory",
      "Operation": "Add member to role",
      "UserId": "globaladmin@company.com",
      "ObjectId": "user@company.com",
      "ModifiedProperties": [{
        "Name": "Role.DisplayName",
        "NewValue": "Global Administrator"
      }]
    }
  }
}
```

## Use Cases

### Detecting Suspicious Sign-Ins

- Multiple failed login attempts (brute force)
- Sign-ins from geographically distant locations within a short period (impossible travel)
- Sign-ins from anonymous IP addresses
- Successful login following a series of failures (password spraying)

### Monitoring Mailbox Access

- Delegate access to another user's mailbox
- Creation of mail forwarding rules to external addresses
- Bulk message deletion
- Calendar permission changes

### Detecting DLP Violations

- Sending documents containing credit card numbers
- Forwarding files with personal data to external addresses
- Uploading sensitive documents to SharePoint with open access
- Detection of sensitive data patterns in Teams

### Monitoring Administrative Actions

- Assignment of privileged roles (Global Admin, Exchange Admin)
- Modification of conditional access policies
- Creation or modification of Exchange transport rules
- Disabling audit logging or multi-factor authentication

## Troubleshooting

### Module Not Receiving Events

- Verify that `tenant_id`, `client_id`, and `client_secret` are correct
- Confirm that `ActivityFeed.Read` and `ActivityFeed.ReadDlp` permissions are assigned
- Check that admin consent has been granted
- Allow up to 24 hours after initial activation, as the API may need time to prepare subscriptions

### Authentication Error

- Verify the client secret has not expired
- Confirm that `api_type` matches your subscription (commercial, gcc, gcc-high)
- Check that the application is not blocked in Azure AD
- Review `/var/ossec/logs/ossec.log` for HTTP 401/403 errors

### Empty API Responses

- Confirm that auditing is enabled in the Microsoft 365 admin center
- Verify that subscriptions for the required content types are active
- For the initial run, set `only_future_events` to `no` to retrieve historical data
- Check that the tenant has activity for the requested period

### High Event Volume

- Limit subscriptions to only the required content types
- Increase the `interval` value to reduce polling frequency
- Create Wazuh rules to filter noisy events
- Use `curl_max_size` to limit the data volume per request

## Related Sections

- [Cloud Security Monitoring](/docs/wazuh/cloud-security/) - overview of cloud integrations
- [Azure Monitoring](/docs/wazuh/cloud-security/wazuh-azure-monitoring/) - Microsoft Azure integration (shared Azure AD)
- [Wazuh Capabilities](/docs/wazuh/capabilities/) - platform security modules

