# Map to CIM

This guide shows you how to map events to Splunk Common Information Model (CIM) fields in TQL. You’ll learn how to choose a CIM data model and dataset, apply dataset tags, populate normalized fields, set Splunk HEC metadata, and preserve source-specific details.

CIM is organized around data models and datasets rather than a single event record hierarchy. For Splunk searches and accelerated data models to find your events, the mapping must produce the right tags and normalized fields for the chosen dataset.

## Use the CIM skill

Install the `tenzir-cim` skill when you want an agent to help with CIM schema decisions. See [Use agent skills](https://preview.docs.tenzir.com/407/guides/ai-workbench/use-agent-skills.md#use-the-cim-skill) for installation and usage examples.

Ask the agent to choose the data model and dataset before it maps fields. The skill can inspect tags, constraints, recommended fields, calculated fields, and lookup-backed values for the selected dataset.

## Choose the CIM dataset

Start from the event semantics, then choose the closest CIM data model and dataset. For a firewall connection event, choose the `Network_Traffic` data model and the `All_Traffic` dataset.

For `Network_Traffic / All_Traffic`, start with these fields and tags:

* `tag`: Include `network` and `communicate`.
* `_time`: The event timestamp.
* `src`, `src_ip`, and `src_port`: The source endpoint.
* `dest`, `dest_ip`, and `dest_port`: The destination endpoint.
* `transport`: The layer 4 protocol, such as `tcp`, `udp`, or `icmp`.
* `action`: The normalized traffic action, such as `allowed`, `blocked`, or `teardown`.
* `bytes`, `bytes_in`, and `bytes_out`: Traffic volume fields.
* `dvc` and `vendor_product`: The reporting product context.

## Write a small mapping

The following example shows a package mapper that maps a parsed firewall connection event to CIM Network Traffic fields. It keeps all mapping work inside the `event` argument, puts the source data under `fw`, applies the dataset tags, normalizes action and transport values, maps endpoint fields, and preserves unmapped residue for review.

```tql
---
args:
  named:
    - name: event
      description: The field that holds the event to map.
      type: field
      default: this
---


$event = {...$event, fw: $event, cim: {}}


let $actions = {
  allow: "allowed",
  allowed: "allowed",
  block: "blocked",
  blocked: "blocked",
  deny: "blocked",
  denied: "blocked",
  drop: "blocked",
  dropped: "blocked",
  teardown: "teardown",
}


$event.cim._time = move $event.fw.ts
$event.cim.tag = ["network", "communicate"]
$event.cim.host = $event.fw.device
$event.cim.source = "example-firewall"
$event.cim.sourcetype = "example:firewall"
$event.cim.vendor_product = "Example Networks Example Firewall"
$event.cim.action = $actions[$event.fw.action.to_lower()]? else $event.fw.action.to_lower()
$event.cim.src = $event.fw.src_ip
$event.cim.src_ip = move $event.fw.src_ip
$event.cim.src_port = move $event.fw.src_port
$event.cim.dest = $event.fw.dst_ip
$event.cim.dest_ip = move $event.fw.dst_ip
$event.cim.dest_port = move $event.fw.dst_port
$event.cim.transport = (move $event.fw.proto).to_lower()
$event.cim.bytes_out = move $event.fw.bytes_out
$event.cim.bytes_in = move $event.fw.bytes_in
$event.cim.bytes = $event.cim.bytes_in + $event.cim.bytes_out
$event.cim.dvc = move $event.fw.device


drop $event.fw.action


$event = {...$event.cim, unmapped: $event.fw}
```

A call with a firewall event such as `{ts: 2024-01-15T10:30:45Z, action: "allowed", src_ip: "10.0.0.5", src_port: 51544, dst_ip: "203.0.113.10", dst_port: 443, proto: "tcp", bytes_out: 1280, bytes_in: 8192, device: "edge-fw-01"}` produces a CIM event like this:

```tql
{
  _time: 2024-01-15T10:30:45Z,
  tag: [
    "network",
    "communicate",
  ],
  host: "edge-fw-01",
  source: "example-firewall",
  sourcetype: "example:firewall",
  vendor_product: "Example Networks Example Firewall",
  action: "allowed",
  src: "10.0.0.5",
  src_ip: "10.0.0.5",
  src_port: 51544,
  dest: "203.0.113.10",
  dest_ip: "203.0.113.10",
  dest_port: 443,
  transport: "tcp",
  bytes_out: 1280,
  bytes_in: 8192,
  bytes: 9472,
  dvc: "edge-fw-01",
  unmapped: {},
}
```

## Apply the mapping pattern

Use the same structure for larger mappings:

* **Use the event scope**: Package mappers accept a named `event` field argument with `default: this`, create source and target namespaces with an initial spread, and mutate only fields below `$event`.
* **Keep a source namespace**: Keep the parsed event under a short namespace such as `fw`, `dns`, `edr`, or `event` before you create CIM fields.
* **Choose the dataset first**: Let the CIM data model, dataset tags, and constraints drive the mapping.
* **Apply dataset tags**: Include the tags from the selected dataset and its parent chain so Splunk data model searches can find the event.
* **Populate recommended fields**: Map recommended fields such as `src`, `dest`, `action`, `transport`, `dvc`, and `vendor_product` when the source provides them.
* **Use lookup-backed values**: Normalize values such as `action` and `transport` to the values documented by CIM lookups.
* **Preserve unmapped fields**: Keep source fields that don’t have a deliberate CIM target in `unmapped` so reviewers can audit the mapping.

## Send CIM events to Splunk

When you send CIM-shaped events to Splunk HEC, pass Splunk metadata through the dedicated [`to_splunk`](https://preview.docs.tenzir.com/407/reference/operators/to_splunk.md) options:

```tql
my_source::cim::map
to_splunk "https://splunk.example.com:8088",
  hec_token=secret("splunk-hec-token"),
  time=_time,
  host=host,
  source=source,
  sourcetype=sourcetype
```

If the parsed source event lives in a nested field, pass that field explicitly and promote the mapped CIM event before the sink reads top-level metadata:

```tql
my_source::cim::map event=parsed
this = parsed
to_splunk "https://splunk.example.com:8088",
  hec_token=secret("splunk-hec-token"),
  time=_time,
  host=host,
  source=source,
  sourcetype=sourcetype
```

Use the `index` option when the destination index differs per event.

## See Also

* [`to_splunk`](https://preview.docs.tenzir.com/407/reference/operators/to_splunk.md)
* [Clean up values](https://preview.docs.tenzir.com/407/guides/normalization/clean-up-values.md)
* [Use agent skills](https://preview.docs.tenzir.com/407/guides/ai-workbench/use-agent-skills.md#use-the-cim-skill)
* [Map to ASIM](https://preview.docs.tenzir.com/407/guides/normalization/map-to-asim.md)
* [Map to ECS](https://preview.docs.tenzir.com/407/guides/normalization/map-to-ecs.md)
* [Map to OCSF](https://preview.docs.tenzir.com/407/guides/normalization/map-to-ocsf.md)
* [Map to UDM](https://preview.docs.tenzir.com/407/guides/normalization/map-to-udm.md)
* [Create a package](https://preview.docs.tenzir.com/407/guides/packages/create-a-package.md)
* [Write tests](https://preview.docs.tenzir.com/407/guides/testing/write-tests.md)
* [Splunk](https://preview.docs.tenzir.com/407/integrations/splunk.md)