MENU
    Mac Unified Logging
    • 12 Jun 2025
    • 4 Minutes to read
    • Dark

    Mac Unified Logging

    • Dark

    Article summary

    Overview

    This Adapter allows you to collect events from MacOS Unified Logging.

    Deployment Configurations

    All adapters support the same client_options, which you should always specify if using the binary adapter or creating a webhook adapter. If you use any of the Adapter helpers in the web app, you will not need to specify these values.

    • client_options.identity.oid: the LimaCharlie Organization ID (OID) this adapter is used with.
    • client_options.identity.installation_key: the LimaCharlie Installation Key this adapter should use to identify with LimaCharlie.
    • client_options.platform: the type of data ingested through this adapter, like text, json, gcp, carbon_black, etc.
    • client_options.sensor_seed_key: an arbitrary name for this adapter which Sensor IDs (SID) are generated from, see below.

    Optional Arguments:

    • predicate: example, predicate='subsystem=="com.apple.TimeMachine"'

    CLI Deployment

    Adapter downloads can be found here.

    chmod +x /path/to/lc_adapter
    
    /path/to/lc_adapter mac_unified_logging client_options.identity.installation_key=$INSTALLATION_KEY \
    client_options.identity.oid=$OID \
    client_options.platform=json \
    client_options.sensor_seed_key=$SENSOR_NAME \
    client_options.hostname=$SENSOR_NAME
    Bash

    Infrastructure as Code Deployment

    # macOS Unified Logging Specific Docs: https://docs.limacharlie.io/docs/adapter-types-macos-unified-logging
    
    sensor_type: "mac_unified_logging"
    mac_unified_logging:
      write_timeout_sec: 10 # (optional) Timeout in seconds for writing data. e.g., 10 or null.
      # (optional) An NSPredicate string for filtering logs collected.
      # Example: Collect logs from sshd or specific security subsystem events.
      predicate: 'processImagePath endswith "/usr/sbin/sshd" OR (subsystem == "com.apple.security" AND eventType == eventMessage)'
      client_options:
        identity:
          oid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # (required) Organization ID from LimaCharlie.
          installation_key: "YOUR_LC_INSTALLATION_KEY_MACOSUL" # (required) Installation key associated with the OID.
        # For macOS Unified Logging, hostname is critical as it identifies the source Mac.
        # It's often derived from the actual host the adapter runs on but can be overridden.
        hostname: "user-macbook-pro.example.com" # (required) A unique hostname for this sensor instance (e.g., the actual macOS hostname).
        platform: "darwin" # (required) The platform of the sensor must be "darwin" for macOS.
        architecture: "arm64" # (optional) The architecture of the macOS host. e.g., "arm64" (Apple Silicon), "x86_64" (Intel).
        mapping:
          # macOS Unified Logs are structured and typically converted to JSON by LimaCharlie, so parsing_re is usually null.
          parsing_re: null
          # (optional) Unified Logs have 'traceID', 'activityID', or other unique identifiers within the event structure.
          sensor_key_path: "event.traceID" # Example using traceID if present and unique.
          # (optional) If client_options.hostname is NOT static or needs to be derived differently (rare for this adapter).
          sensor_hostname_path: null # Typically, client_options.hostname is the authority.
          # (optional) Example: "MACOS_UL_SECURITY_AUTH", "MACOS_UL_SYSTEM_BOOT".
          event_type_path: "MACOS_UL_{{ .event.subsystem | token | upper | replace \".\" \"_\" }}_{{ .event.category | token | upper | default \"LOG\" }}"
          # (optional) JSON path to the field representing the event's occurrence time. Unified Logs have precise 'timestamp'.
          event_time_path: "event.timestamp"
          # (optional) JSON path for a field to populate LimaCharlie's investigation_id.
          investigation_id_path: "event.activityID" # activityID can be useful for correlating related logs.
          # (optional) Use +/- syntax for transforms.
          transform:
            "+log_source_type": "MacOSUnifiedLogging"
            "+process_executable_path": "{{ .event.processImagePath }}"
            "+event_summary_message": "{{ .event.message }}"
            "-event.machTimestamp": null # If 'event.timestamp' is preferred and machTimestamp is redundant or different format
            # Example: Extract just the process name from the full path
            # "+process_name_only": "{{ .event.processImagePath | base }}" # Assuming 'base' is a supported template function for path basename
            # (optional) A list of field paths to drop from the event.
          drop_fields:
          - "event.ttl" # Time To Live for the log entry, may not be needed
          - "event.formatString" # If the rendered 'message' is sufficient
          sid_replication_path: null # (optional) Not applicable for macOS Unified Logs.
        # mappings: null # Deprecated or less common for field manipulation than client_options.mapping.transform
        indexing:
          enabled: true
          # Example: index by subsystem and org
          default_index: "macos-ul-{{ .event.subsystem | lower | replace \".\" \"-\" | default \"general\" }}-{{ .identity.oid | substr 0 8 }}"
        is_compressed: false # (optional) Data is collected locally, not typically compressed before ingestion by this adapter.
        sensor_seed_key: "SEED_KEY_MACOSUL_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

    Service Creation

    If you want this adapter to run as a service, you can run the following script to add a plist file to the endpoint with your variables replaced. Please note that this example also has an example predicate, so if you do not wish to use a predicate, remove that line.

    sudo -i
    
    curl https://downloads.limacharlie.io/adapter/mac/64 -o /usr/local/bin/lc_adapter
    chmod +x /usr/local/bin/lc_adapter
    
    tee -a /Library/LaunchDaemons/io.limacharlie.adapter.macunifiedlogging.plist <<EOF
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
      <dict>
        <key>Label</key>
        <string>io.limacharlie.adapter.macunifiedlogging</string>
        <key>UserName</key>
    	<string>root</string>
        <key>RunAtLoad</key>
        <true/>
        <key>WorkingDirectory</key>
        <string>/usr/local/bin</string>
        <key>KeepAlive</key>
        <true/>
        <key>EnvironmentVariables</key>
        <dict>
          <key>PATH</key>
          <string>/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin</string>
        </dict>
        <key>Program</key>
        <string>/usr/local/bin/lc_adapter</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/local/bin/lc_adapter</string>
            <string>mac_unified_logging</string>
            <string>client_options.identity.installation_key=$INSTALLATION_KEY</string>
            <string>client_options.identity.oid=$OID</string>
            <string>client_options.hostname=$SENSOR_NAME</string>
            <string>client_options.platform=json</string>
            <string>client_options.sensor_seed_key=$SENSOR_NAME</string>
            <string>predicate=eventMessage CONTAINS[c] "corp.sap.privileges"</string>
        </array>
      </dict>
    </plist>
    EOF
    
    launchctl load -w /Library/LaunchDaemons/io.limacharlie.adapter.macunifiedlogging.plist
    Bash


    Was this article helpful?