MENU
    Microsoft 365
    • 06 Jun 2025
    • 6 Minutes to read
    • Dark

    Microsoft 365

    • Dark

    Article summary

    Microsoft 365, formerly Office 365, is a product family of productivity software, collaboration and cloud-based services owned by Microsoft. This Adapter allows you to ingest audit events from the Office 365 Management Activity API.

    Microsoft 365 events can be ingested in LimaCharlie and observed as the office365 platform.

    Adapter Deployment

    Microsoft 365 events are ingested via a cloud-to-cloud Adapter configured specifically to review M365 events. When creating an Adapter, the following data points are required:

    • domain: Office 365 domain

    • tenant_id: Office 365 tenant ID

    • publisher_id: Office 365 publisher ID (for single-tenant Apps, the PublisherID is the same as the Tenant ID)

    • client_id: Office 365 client ID

    • client_secret: Office 365 client secret

    • endpoint: Office 365 API endpoint

    • content_types: content types of events to ingest.

      • Options include:

        • Audit.AzureActiveDirectory

        • Audit.Exchange

        • Audit.SharePoint

        • Audit.General

        • DLP.All

      • Default is all of the above

    If creating a Microsoft 365 Adapter via the Web UI, the helper form will navigate you through providing these values.

    Establishing a cloud-to-cloud connector between LimaCharlie and Office 365 requires a few steps to provide the correct permissions for the Office 365 Management Activity API.

    Infrastructure as Code Deployment

    # Office 365 Management Activity API Specific Docs: https://docs.limacharlie.io/docs/adapter-types-office-365-management-activity-api
    
    office365:
      domain: "yourcompany.onmicrosoft.com" # (optional) Your Office 365 domain, e.g., contoso.onmicrosoft.com. Only needed for specific GCC High environments.
      tenant_id: "YOUR_AZURE_O365_TENANT_ID" # (required) Your Office 365 Azure AD Tenant ID (UUID).
      publisher_id: "YOUR_O365_PUBLISHER_ID" # (optional) Office 365 publisher ID. For single-tenant Apps, this is often the same as the Tenant ID. This is not always required.
      client_id: "YOUR_AZURE_APP_REG_O365_CLIENT_ID" # (required) The Application (client) ID of an Azure App Registration with permissions for Office 365 Management APIs (e.g., ActivityFeed.Read).
      client_secret: "YOUR_AZURE_APP_REG_O365_CLIENT_SECRET" # (required) The client secret for the App Registration. Store securely.
      endpoint: "enterprise" # (optional) Office 365 API endpoint type. Options include: "enterprise" (default), "gcc", "gcchigh", "dod".
      content_types:
      # (required) List of content types to ingest.
      - "Audit.AzureActiveDirectory"
      - "Audit.Exchange"
      - "Audit.SharePoint"
      - "Audit.General" # Includes Teams and other general logs
      - "DLP.All"
      # - "Audit.Teams" # Can be listed explicitly if Audit.General is not used or for clarity
      start_time: "2024-01-01T00:00:00Z" # (optional) ISO 8601 UTC timestamp to start ingesting logs from. If null or omitted, starts with new data.
      client_options:
        identity:
          oid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # (required) Organization ID from LimaCharlie.
          installation_key: "YOUR_LC_INSTALLATION_KEY_O365" # (required) Installation key associated with the OID.
        # Option 1: Static hostname for this sensor
        hostname: "ms-o365-adapter-prod-01.example.com" # (required if not using sensor_hostname_path) A unique, static hostname for this sensor instance.
        # Option 2: Dynamic hostname (see client_options.mapping.sensor_hostname_path below)
        platform: "saas_api_microsoft_office365" # (required) Indicates the source is a Microsoft Office 365 API.
        architecture: null # (optional) Not typically applicable for SaaS API integrations.
        mapping:
          # O365 Management API returns JSON blobs, so parsing_re is usually null.
          parsing_re: null
          # (optional) O365 audit records often have an 'Id' field which can serve as a unique key for the event.
          sensor_key_path: "Id"
          # (optional) If client_options.hostname is NOT set, use this to dynamically extract hostname from event. (Less common for O365 general logs).
          sensor_hostname_path: null
          # (optional) Example: "O365_AZUREAD_USERLOGGEDIN", "O365_EXCHANGE_MAILBOXACCESS" based on 'Workload' and 'Operation'.
          event_type_path: "O365_{{ .Workload | token | upper }}_{{ .Operation | token | upper | default \"GENERIC_ACTIVITY\" }}"
          # (optional) JSON path to the field representing the event's occurrence time. O365 records typically use 'CreationTime'.
          event_time_path: "CreationTime"
          # (optional) JSON path for a field to populate LimaCharlie's investigation_id. O365 records often have 'CorrelationId'.
          investigation_id_path: "CorrelationId"
          # (optional) Use +/- syntax for transforms.
          transform:
            "+data_source_suite": "MicrosoftOffice365"
            "+actor_user_id": "{{ .UserId }}" # User performing the action
            "+target_object_details": "{{ .ObjectId }}" # Object being acted upon
            # Example to extract IP address if ClientIP field contains IP:Port
            "+actor_client_ip": "{{ .ClientIP | split \":\" | index 0 }}"
            "-EffectiveOrganization": null # Remove a potentially redundant field
          # (optional) A list of field paths to drop from the event.
          drop_fields:
          - "OriginatingServer" # Can be verbose or internal
          - "UserKey" # If UserId is already being used
          sid_replication_path: null # (optional) Not typically relevant for O365 logs unless specific Azure AD SIDs are being mapped.
        # mappings: null # Deprecated or less common for field manipulation than client_options.mapping.transform
        indexing:
          enabled: true
          default_index: "office365-audit-{{ .identity.oid | substr 0 8 }}" # Example: index by org prefix
        is_compressed: true # (optional) O365 content blobs fetched by the adapter might be gzipped; adapter usually handles this.
        sensor_seed_key: "SEED_KEY_O365_ADAPTER_001" # (required) A unique key for this sensor to register with LimaCharlie.
        dest_url: "https://input.limacharlie.io" # (optional) The destination URL. Usually defaults correctly.
    YAML

    Configuring a Microsoft 365 Adapter in the Web UI

    Preparing Office 365 details

    To establish an Office 365 adapter, we will need to complete a few steps within the Azure portal. Ensure that you have the correct permissions to set up a new App registration.

    • Within the Microsoft Azure portal, create a new App registration. You can follow Microsoft's Quickstart guide here.

    • The LimaCharlie connector requires a secret for Office 365 data. You can create one under Certificates & secrets. Be sure to copy this value and save it somewhere - you can only view it once.

    image.png

    • Additionally, you'll need to ensure that the app has the correct permissions to view Office 365 data via the Management API. Within API Permissions, configure the following permissions:

      • ActivityFeed.Read (Delegated & Application)

      • ActivityFeed.ReadDlp (Delegated & Application) [if you want DLP permissions]

    image.png

    Additionally, you may need to grant admin consent to the above permissions.

    At this point, you should have all the details you need to configure the Adapter.

    Setting Up the Adapter

    Within the LimaCharlie web application, select + Add Sensor, and then select Office 365:

    You can select a pre-existing Installation Key or create a new one, unique for this adapter. Once an Installation Key is selected, you will be prompted with a form to finish setting up the adapter. Choose your desired adapter name, and provide the following values:

    Item

    Azure Portal Location

    Domain

    Home

    Tenant ID

    App Registration Overview

    Publisher ID

    App Registration Overview

    Client ID

    App Registration Overview

    Client Secret

    Created during creation in Certificates & secrets

    API Endpoint

    enterprise, gcc-gov, gcc-high-gov, or dod-gov

    Finally, you will also need to select a "Content Type" to import. This is the type of events you want to bring in to LimaCharlie. The options are as follows:

    • Audit.AzureActiveDirectory

    • Audit.Exchange

    • Audit.SharePoint

    • Audit.General

    • DLP.All

    Without a value, the default is all of the above.

    Click Complete Cloud Installation, and LimaCharlie will attempt to connect to the Microsoft Office 365 Management API and pull events.

    Sample Rule

    When ingested into LimaCharlie, Office 365 data can be referenced directly in your D&R rules. You could do this via a platform operator:

    op: is platform
    name: office365
    YAML

    We can also reference Office 365 events directly. The following sample rule looks at FileAccessed events from anonymous user names, and reports accordingly.

    # Detection
    event: FileAccessed
    path: event/UserId
    op: contains
    value: anon
    
    
    # Response
    - action: report
      name: OneDrive File Accessed by Anonymous User
    YAML

    Note that in the detection above, we pivot on the FileAccessed event, which is associated with SharePoint activity. Available event types will depend on source activity and events ingested. More information on audit log activities can be found here.


    Was this article helpful?


    What's Next