Skip to main content

enrich-ontology

Map a Cartography node into the Ontology system using semantic labels (UserAccount, DeviceInstance, Tenant, Database, ObjectStorage, FileStorage) or canonical nodes (User, Device). Use when the user asks to add ontology mapping, expose a node as a semantic label, normalise identity / device data across providers, enable cross-module queries, or wire `_ont_*` properties. Use when this capability is needed.

Ir para a instalação

Informações da origem

Repositório
tomevault-io/tomes
Última atividade na origem
23 de julho de 2026 às 21:48
Idioma detectado do SKILL.md
inglês
Estrelas
1
Forks
0

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
enrich-ontology
description
Map a Cartography node into the Ontology system using semantic labels (UserAccount, DeviceInstance, Tenant, Database, ObjectStorage, FileStorage) or canonical nodes (User, Device). Use when the user asks to add ontology mapping, expose a node as a semantic label, normalise identity / device data across providers, enable cross-module queries, or wire `_ont_*` properties. Use when this capability is needed.
metadata
{"author":"cartography-cncf"}
# enrich-ontology Cartography's Ontology system unifies data from multiple sources via two mechanisms: 1. **Semantic labels (recommended)** — adds labels (e.g. `UserAccount`) and prefixed properties (`_ont_*`) directly to source nodes during ingestion. 2. **Canonical nodes** — separate `(:User:Ontology)` / `(:Device:Ontology)` nodes that aggregate data from multiple sources. Most modules only need semantic labels. ## Critical rules 1. **Mark primary identifiers `required=True`** in `OntologyFieldMapping` (e.g. `email` for `User`, `hostname` for `Device`). Records missing these are excluded from ontology node creation. 2. **For semantic labels, just add `ExtraNodeLabels(["UserAccount"])`** to your node schema. The ontology system handles the `_ont_*` properties automatically. 3. **`special_handling` values are strings**: `invert_boolean`, `to_boolean`, `or_boolean`, `nor_boolean`, `equal_boolean`, `static_value`, `coalesce`. Boolean conditions inside `extra={"values": ...}` must also be strings (`"true"`, not `True`). 4. **Document ontology mapping** in your schema doc using the standard blockquote phrase. 5. **Module name `microsoft`** is the canonical source for Microsoft Graph. `entra` is still accepted as a backward-compatible alias during migration. ## Instructions ### Step 1 — Decide: semantic label or canonical node? | Need | Use | | ------------------------------------------------------------------------------------- | ------------------ | | Cross-module queries on existing source nodes (e.g. all `UserAccount` across systems) | Semantic label | | Aggregate one entity from many sources into a single canonical record | Canonical node | When in doubt, start with semantic label. ### Step 2 — Author the mapping Add the mapping in `cartography/models/ontology/mapping/data/`. For users: ```python # cartography/models/ontology/mapping/data/useraccounts.py from cartography.models.ontology.mapping.specs import ( OntologyFieldMapping, OntologyMapping, OntologyNodeMapping, ) your_service_mapping = OntologyMapping( module_name="your_service", nodes=[ OntologyNodeMapping( node_label="YourServiceUser", fields=[ OntologyFieldMapping(ontology_field="email", node_field="email", required=True), OntologyFieldMapping(ontology_field="username", node_field="username"), OntologyFieldMapping(ontology_field="fullname", node_field="display_name"), OntologyFieldMapping(ontology_field="firstname", node_field="first_name"), OntologyFieldMapping(ontology_field="lastname", node_field="last_name"), OntologyFieldMapping( ontology_field="inactive", node_field="account_enabled", special_handling="invert_boolean", ), OntologyFieldMapping( ontology_field="has_mfa", node_field="multifactor", special_handling="to_boolean", ), OntologyFieldMapping( ontology_field="inactive", node_field="suspended", special_handling="or_boolean", extra={"fields": ["archived"]}, ), ], ), ], ) ``` For devices the pattern is the same with `OntologyNodeMapping(node_label="YourServiceDevice", ...)`. ### Step 3 — Register the mapping Add it to the dictionary at the bottom of the file: ```python # Example: bottom of useraccounts.py USERACCOUNTS_ONTOLOGY_MAPPING: dict[str, OntologyMapping] = { # ... existing mappings ... "your_service": your_service_mapping, } ``` The mappings are auto-imported via `cartography/models/ontology/mapping/__init__.py`. ### Step 4 — Wire the semantic label on your node schema For semantic labels, the node schema simply gains the extra label — Cartography injects `_ont_*` and `_ont_source` automatically at ingestion: ```python from cartography.models.core.nodes import ExtraNodeLabels @dataclass(frozen=True) class YourServiceUserSchema(CartographyNodeSchema): label: str = "YourServiceUser" extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(["UserAccount"]) properties: YourServiceUserNodeProperties = YourServiceUserNodeProperties() sub_resource_relationship: YourServiceTenantToUserRel = YourServiceTenantToUserRel() ``` For canonical nodes, define a separate schema with `extra_node_labels=ExtraNodeLabels(["Ontology"])` and a relationship to the semantic-labelled source nodes. See `references/semantic-labels.md` for the full template. ### Step 5 — `required` and `eligible_for_source` `required=True` means: source records lacking this field are **excluded** from ontology node creation. Always mark the primary identifier required: ```python OntologyFieldMapping(ontology_field="email", node_field="email", required=True) OntologyFieldMapping(ontology_field="hostname", node_field="device_name", required=True) ``` `OntologyNodeMapping.eligible_for_source=False` means: this mapping links existing ontology nodes but cannot **create** new ones. Use it when the source lacks the required identifier: ```python # AWS IAM users have no email, so they cannot create new User ontology nodes. OntologyNodeMapping( node_label="AWSUser", eligible_for_source=False, fields=[ OntologyFieldMapping(ontology_field="username", node_field="name"), ], ), ``` ### Step 6 — Cross-entity relationships (e.g. user owns device) For services that link users to devices, add a statement to the appropriate ontology analysis JSON file (e.g. `cartography/data/jobs/analysis/ontology_devices_linking.json`): ```json { "__comment": "Connect users to their devices via YourService", "query": "MATCH (u:User)-[:HAS_ACCOUNT]->(:YourServiceUser)-[:OWNS]->(:YourServiceDevice)<-[:OBSERVED_AS]-(d:Device) MERGE (u)-[r:OWNS]->(d) ON CREATE SET r.firstseen = timestamp() SET r.lastupdated = $UPDATE_TAG", "iterative": false } ``` See the `analysis-jobs` skill for the JSON job format. ### Step 7 — Test For semantic labels — assert `_ont_*` properties land on your nodes: ```python def test_ontology_properties(neo4j_session): # after running your sync row = neo4j_session.run( "MATCH (n:YourServiceUser) RETURN n._ont_email, n._ont_source LIMIT 1" ).single() assert row["n._ont_email"] is not None assert row["n._ont_source"] == "your_service" ``` For canonical nodes — assert the ontology intel module produces them: ```python def test_canonical_user_created(neo4j_session): row = neo4j_session.run( """ MATCH (u:User:Ontology)-[:HAS_ACCOUNT]->(ua:YourServiceUser) RETURN count(u) AS user_count """ ).single() assert row["user_count"] > 0 ``` ### Step 8 — Document the integration In `docs/root/modules/your_service/schema.md`, add the standard blockquote phrase under the node title: ```markdown ### YourServiceUser Represents a user in Your Service. > **Ontology Mapping**: This node has the extra label `UserAccount` to enable cross-platform queries for user accounts across different systems (e.g., OktaUser, EntraUser, GSuiteUser). ``` Standard phrases by semantic label: | Semantic label | Standard phrase | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `UserAccount` | This node has the extra label `UserAccount` to enable cross-platform queries for user accounts across different systems (e.g., OktaUser, EntraUser, GSuiteUser). | | `DeviceInstance` | This node has the extra label `DeviceInstance` to enable cross-platform queries for device instances across different systems (e.g., CrowdStrikeDevice, KandjiDevice, JamfComputer). | | `Tenant` | This node has the extra label `Tenant` to enable cross-platform queries for organizational tenants across different systems (e.g., OktaOrganization, AzureTenant, GCPOrganization). | | `Database` | This node has the extra label `Database` to enable cross-platform queries for databases across different systems (e.g., RDSInstance, DynamoDBTable, BigQueryDataset). | | `ObjectStorage` | This node has the extra label `ObjectStorage` to enable cross-platform queries for object storage across different systems (e.g., S3Bucket, GCPBucket, AzureStorageBlobContainer). | | `FileStorage` | This node has the extra label `FileStorage` to enable cross-platform queries for network file systems and shares across different systems (e.g., EfsFileSystem, AzureStorageFileShare). | ## `special_handling` quick reference | Value | Description | Extra params | | ----------------- | ---------------------------------------------------------- | ----------------------------------------- | | `invert_boolean` | Inverts the boolean value (`true` -> `false`) | None | | `to_boolean` | Converts to boolean, treating non-null as `true` | None | | `or_boolean` | Logical OR over multiple boolean fields | `extra={"fields": [...]}` | | `nor_boolean` | Logical NOR over multiple boolean fields | `extra={"fields": [...]}` | | `equal_boolean` | `true` if value matches any of the specified strings | `extra={"values": ["active", "bypass"]}` | | `static_value` | Sets a static value, ignoring `node_field` | `extra={"value": "dynamodb"}` | | `coalesce` | Sets the first non-null value from multiple fields | `extra={"fields": [...]}` | ## Canonical node configuration (CLI) ```bash cartography --ontology-users-source "okta,microsoft,gsuite" cartography --ontology-devices-source "crowdstrike,kandji,duo" ``` ## References (load on demand) - `references/semantic-labels.md` — execution flow, available labels/fields, full canonical-node schema example, `eligible_for_source` deep dive. --- > Source: [cartography-cncf/cartography](https://github.com/cartography-cncf/cartography) — distributed by [TomeVault](https://tomevault.io). <!-- tomevault:4.0:skill_md:2026-06-26 -->
Ver no GitHub