name: keytos-ezmonitor
description: A package for Keytos EZMonitor (Certificate Transparency log monitoring) SIEM logs.
testCases:
  - event:
      rawString: '{"VulnerabilityID":18,"Domain":"app.contoso.com","VulnerabilityFound":"Your domain is vulnerable to domain takeover","CertThumbprint":"A1B2C3D4E5F600112233445566778899AABBCCDD","Details":"Your DNS record is pointing to a not used Azure resource contoso-app.azurewebsites.net please remove the CNAME record pointing to this resource to avoid a bad actor taking over your sub domain.","ExtraDomain":"","InternalDomain":false,"DateFound":"2026-07-24T18:22:41.1234567Z"}'
    assertions:
      - fieldsHaveValues:
          "#Vendor": "keytos"
          "#event.module": "ezmonitor"
          "#event.kind": "event"
          "#event.dataset": "ezmonitor"
          "event.category[0]": "vulnerability"
          "event.type[0]": "info"
          "keytos.vulnerability.id": "18"
          "event.reason": "Your domain is vulnerable to domain takeover"
          "url.domain": "app.contoso.com"
          "tls.server.hash.sha1": "A1B2C3D4E5F600112233445566778899AABBCCDD"
  - event:
      rawString: '{"VulnerabilityID":68,"Domain":"www.contoso.com","VulnerabilityFound":"Certificate in web server expiring soon","CertThumbprint":"0011223344556677889900AABBCCDDEEFF001122","Details":"The certificate installed on www.contoso.com is expiring soon.","ExtraDomain":"","InternalDomain":false,"DateFound":"2026-07-24T19:00:00.000Z"}'
    assertions:
      - fieldsHaveValues:
          "#event.module": "ezmonitor"
          "event.category[0]": "vulnerability"
          "event.type[0]": "info"
          "keytos.vulnerability.id": "68"
          "event.reason": "Certificate in web server expiring soon"
          "url.domain": "www.contoso.com"
          "tls.server.hash.sha1": "0011223344556677889900AABBCCDDEEFF001122"
fieldsToBeRemovedBeforeParsing: []
$schema: https://schemas.humio.com/parser/v0.3.0
script: |-
  // #region PREPARSE
  /************************************************************
  ****** Parse timestamp and log headers
  ****** Extract message field for parsing
  ****** Parse structured data
  ************************************************************/

  // parseJson captures EVERY field EZMonitor emits into Vendor.* automatically.
  case {
      @rawstring = /^\s*\{/
        | parseJson(prefix="Vendor.", excludeEmpty=true, handleNull=discard);
      *;
  }
  | case {
      Vendor.DateFound = *
        | parseTimestamp(field=Vendor.DateFound);
      *;
  }

  // #endregion

  // #region METADATA
  /************************************************************
  ****** Static Metadata Definitions
  ************************************************************/

  | Parser.version := "1.2.0"
  | Cps.version := "1.2.0"
  | ecs.version := "9.3.0"
  | Vendor := "keytos"
  | event.module := "ezmonitor"
  | event.kind := "event"

  // #endregion

  // #region NORMALIZATION
  /************************************************************
  ****** Parse unstructured data (i.e. message field)
  ****** Normalize fields to data model
  ************************************************************/

  // Write EZMonitor values straight through — passthrough, no lookups.
  // VulnerabilityID is a Keytos-internal taxonomy code (e.g. 18 = domain takeover),
  // not a CVE, so it lives in a custom keytos.* field rather than ECS vulnerability.id.
  | keytos.vulnerability.id := Vendor.VulnerabilityID
  | event.reason := Vendor.VulnerabilityFound
  | message := Vendor.Details
  | event.dataset := "ezmonitor"

  // CPS requires at least one event.category and event.type. All EZMonitor
  // records are vulnerability findings.
  | array:append(array="event.category[]", values=["vulnerability"])
  | array:append(array="event.type[]", values=["info"])

  // Monitored domain and certificate
  | url.domain := lower(Vendor.Domain)
  // Only a valid 40-char SHA-1 goes into the typed hash field (CPS validates length).
  | case {
      Vendor.CertThumbprint = /^[0-9A-Fa-f]{40}$/
        | tls.server.hash.sha1 := Vendor.CertThumbprint;
      *;
  }

  // #endregion

  // #region POST-NORMALIZATION
  /************************************************************
  ****** Post Normalization
  ****** Custom parser logic needed after normalization
  ************************************************************/

  // #endregion
tagFields:
  - Vendor
  - Cps.version
  - ecs.version
  - event.dataset
  - event.kind
  - event.module
  - observer.type
