name: keytos-ezssh
description: A package for Keytos EZSSH (just-in-time SSH access) SIEM logs.
testCases:
  - event:
      rawString: '{"ActionPerformed":"Approved","RequestDate":"2026-07-24T15:04:21.123Z","RequestorFriendlyName":"Jane Admin","RequestorOId":"8f14e45f-ceea-467a-9575-0e2f0f6b3a11","LinuxPrincipal":"jadmin","EndpointsRequested":"prod-web-01.contoso.com","EndpointsGrantedAccess":"prod-web-01.contoso.com","GrandparentPolicyID":"d47b647b-ed31-46ef-829c-57e53b4b7cdd","ParentPolicyID":"a288acbf-718f-4c4d-ae28-60728df9ca54","PolicyName":"Production Linux Servers","PolicyType":"AzurePolicy","HoursRequested":4,"AditionalCert":false,"CertificateSerialNumber":123456789012345,"UserPublicKey":"ssh-rsa AAAAB3NzaC1yc2E...","Certificate":"ssh-rsa-cert-v01@openssh.com AAAAHHNz...","Approver":"John Approver","DateApproved":"2026-07-24T15:06:00.000Z","Approved":true}'
    assertions:
      - fieldsHaveValues:
          "#Vendor": "keytos"
          "#event.module": "ezssh"
          "#event.kind": "event"
          "#event.dataset": "ezssh"
          "event.category[0]": "session"
          "event.type[0]": "info"
          "event.action": "Approved"
          "user.full_name": "Jane Admin"
          "user.id": "8f14e45f-ceea-467a-9575-0e2f0f6b3a11"
          "user.target.name": "jadmin"
          "rule.name": "Production Linux Servers"
          "rule.id": "a288acbf-718f-4c4d-ae28-60728df9ca54"
  - event:
      rawString: '{"TenantId":"d47b647b-ed31-46ef-829c-57e53b4b7cdd","RequestDate":"2026-07-24T16:20:00.000Z","RequestorFriendlyName":"Dev User","RequestorOId":"1c3c6cea-fcbd-4681-85e1-74fb74b6863e","Certificate":"ssh-rsa-cert-v01@openssh.com AAAAHHNz...","UserPublicKey":"ssh-rsa AAAAB3NzaC1yc2E...","CertificateSerialNumber":9988776655}'
    assertions:
      - fieldsHaveValues:
          "#Vendor": "keytos"
          "#event.module": "ezssh"
          "#event.dataset": "ezssh"
          "event.category[0]": "session"
          "event.type[0]": "info"
          "user.full_name": "Dev User"
          "user.id": "1c3c6cea-fcbd-4681-85e1-74fb74b6863e"
          "Vendor.TenantId": "d47b647b-ed31-46ef-829c-57e53b4b7cdd"
        fieldsNotPresent:
          - "event.action"
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 EZSSH emits into Vendor.* automatically.
  parseJson(prefix="Vendor.", excludeEmpty=true, handleNull=discard)
  | case {
      Vendor.RequestDate = *
        | parseTimestamp(field=Vendor.RequestDate);
      *;
  }

  // #endregion

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

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

  // #endregion

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

  // Write EZSSH values straight through — passthrough, no per-action lookups.
  | event.action := Vendor.ActionPerformed
  | event.dataset := "ezssh"

  // CPS requires at least one event.category and event.type. EZSSH grants
  // just-in-time access sessions to hosts.
  | array:append(array="event.category[]", values=["session"])
  | array:append(array="event.type[]", values=["info"])

  // Requester identity
  | user.full_name := Vendor.RequestorFriendlyName
  | user.id := Vendor.RequestorOId

  // Target Linux account being accessed
  | user.target.name := Vendor.LinuxPrincipal

  // Access policy -> rule
  | rule.id := Vendor.ParentPolicyID
  | rule.name := Vendor.PolicyName

  // #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
