Model

Nodes

class cartography.models.core.nodes.CartographyNodeProperties

Bases: ABC

Abstract base dataclass that represents the properties on a CartographyNodeSchema.

This class is abstract to enforce that all subclasses have an id and a lastupdated field. These fields are assigned to the node in the SET clause during Neo4j ingestion.

id

The unique identifier for the node, set automatically.

Type:

PropertyRef

lastupdated

The timestamp of the last update, set automatically.

Type:

PropertyRef

Examples

>>> @dataclass(frozen=True)
... class AWSUserProperties(CartographyNodeProperties):
...     id: PropertyRef = PropertyRef('Arn')
...     lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
...     name: PropertyRef = PropertyRef('UserName')
...     path: PropertyRef = PropertyRef('Path')
>>> # Cannot instantiate abstract class directly
>>> CartographyNodeProperties()  # Raises TypeError
>>> # Cannot use reserved word 'firstseen'
>>> @dataclass(frozen=True)
... class BadProperties(CartographyNodeProperties):
...     firstseen: PropertyRef = PropertyRef('firstseen')  # Raises TypeError

Note

  • The firstseen attribute is reserved and automatically set by the querybuilder

  • All subclasses must define both id and lastupdated fields

  • This class cannot be instantiated directly

__init__() None
__post_init__()

Perform data validation on the CartographyNodeProperties instance.

This method enforces important constraints to ensure proper usage of the CartographyNodeProperties class and prevent common errors.

Raises:
  • TypeError – If attempting to instantiate the abstract class directly.

  • TypeError – If the reserved word ‘firstseen’ is used as an attribute name.

id: PropertyRef
lastupdated: PropertyRef
class cartography.models.core.nodes.CartographyNodeSchema

Bases: ABC

Abstract base dataclass that represents a graph node in cartography.

This class is used to dynamically generate graph ingestion queries for Neo4j. It defines the structure and relationships of nodes in the cartography graph, providing a declarative way to specify how data should be ingested.

Note

  • Subclasses must implement the abstract properties: label and properties

  • Optional properties can be overridden to specify relationships and labels

__init__() None
property extra_node_labels: ExtraNodeLabels | None

Optional extra labels to be applied to the node.

Allows specifying additional Neo4j labels beyond the primary label. This is useful for creating taxonomies or adding classification labels.

Returns:

The extra labels for the node,

or None if no extra labels are defined.

Return type:

Optional[ExtraNodeLabels]

abstract property label: str

Primary string label of the node.

This property defines the main Neo4j label that will be applied to nodes of this type. It’s used in the MERGE clause during ingestion.

Returns:

The primary label for the node (e.g., ‘AWSUser’, ‘EC2Instance’).

property other_relationships: OtherRelationships | None

Optional additional cartography relationships on the node.

Allows subclasses to specify additional relationships beyond the sub resource relationship. These relationships connect the node to other nodes in the graph.

Returns:

The additional relationships for the node,

or None if no additional relationships are defined.

Return type:

Optional[OtherRelationships]

abstract property properties: CartographyNodeProperties

Properties of the node.

This property defines all the properties that will be set on the node during ingestion, including how they map to the source data.

Returns:

The properties definition for the node.

Return type:

CartographyNodeProperties

property scoped_cleanup: bool

Whether cleanups of this node must be scoped to the sub resource relationship.

This property controls the cleanup behavior for nodes of this type during synchronization operations.

Returns:

True if cleanups should be scoped to the sub resource (default),

False if cleanups should be global.

Return type:

bool

Note

  • If True (default): Only delete stale nodes in the current sub resource (e.g., only clean up EC2 instances in the current AWS account)

  • If False: Delete all stale nodes globally (designed for resource types that don’t have a “tenant”-like entity)

  • This affects how the cleanup queries are generated

property sub_resource_relationship: CartographyRelSchema | None

The optional sub resource relationship for the node.

Allows subclasses to specify a subresource relationship for the given node. “Sub resource” is a cartography term for the billing or organizational unit that contains the resource.

Returns:

The sub resource relationship schema,

or None if no sub resource relationship is defined.

Return type:

Optional[CartographyRelSchema]

Examples

Sub resource examples by cloud provider: - AWS: AWSAccount - Azure: Subscription - GCP: GCPProject - Okta: OktaOrganization

class cartography.models.core.nodes.ExtraNodeLabels(labels: List[str])

Bases: object

Encapsulates a list of strings representing additional labels for the CartographyNodeSchema.

This wrapper class is used to ensure dataclass immutability for the CartographyNodeSchema while providing additional Neo4j labels beyond the primary node label.

labels

A list of string labels to be applied to the node.

Type:

List[str]

Examples

>>> # AWS resources with additional labels
>>> extra_labels = ExtraNodeLabels(['Resource', 'AWSResource'])
__init__(labels: List[str]) None
labels: List[str]

Relationships

class cartography.models.core.relationships.CartographyRelProperties

Bases: ABC

Abstract base class representing properties on a CartographyRelSchema.

This abstract class enforces that all subclasses will have a lastupdated field defined on their resulting relationships. These fields are assigned to the relationship in the Neo4j SET clause during graph operations.

lastupdated

A PropertyRef to the update tag of the relationship.

Type:

cartography.models.core.common.PropertyRef

Required Properties for MatchLink Usage:

When the CartographyRelSchema is used as a MatchLink, the following properties must be defined in subclasses:

  • lastupdated: A PropertyRef to the update tag of the relationship.

  • _sub_resource_label: A PropertyRef to the label of the sub-resource that the relationship is associated with.

  • _sub_resource_id: A PropertyRef to the id of the sub-resource that the relationship is associated with.

Examples

>>> @dataclass(frozen=True)
... class MyRelProperties(CartographyRelProperties):
...     lastupdated: PropertyRef = PropertyRef('lastupdated')
...     custom_field: PropertyRef = PropertyRef('custom_field')

Note

This class cannot be instantiated directly. It must be subclassed. The firstseen attribute is reserved and automatically set by the querybuilder, so it cannot be used as a custom attribute name.

__init__() None
__post_init__()

Perform data validation on CartographyRelProperties instances.

This method enforces two important validation rules: 1. Prevents direct instantiation of the abstract base class 2. Prevents use of reserved attribute names

Raises:

TypeError – If attempting to instantiate the abstract base class directly, or if using reserved attribute names like ‘firstseen’.

Note

This workaround is needed since this is both a dataclass and an abstract class without an abstract method defined. See https://stackoverflow.com/q/60590442.

The firstseen attribute is reserved because it’s automatically set by the querybuilder on cartography relationships.

lastupdated: PropertyRef
class cartography.models.core.relationships.CartographyRelSchema

Bases: ABC

Abstract base class representing a cartography relationship schema.

This class defines the structure and behavior of relationships in the cartography data model. It contains all the necessary properties to connect a CartographyNodeSchema to other existing nodes in the Neo4j graph database.

The CartographyRelSchema is used to define how nodes should be connected, including the direction of the relationship, the target node criteria, and the properties to be set on the relationship.

Note

This is an abstract base class and cannot be instantiated directly. All abstract properties must be implemented by concrete subclasses.

The dataclass is frozen to ensure immutability when used in CartographyNodeSchema objects.

__init__() None
abstract property direction: LinkDirection

Direction of the relationship.

This property defines the LinkDirection that determines whether the relationship arrow points toward the source node (INWARD) or away from the source node (OUTWARD).

Returns:

A LinkDirection enum value specifying the relationship direction.

Note

Please see the LinkDirection enum documentation for detailed explanations of how direction affects the resulting Neo4j relationship patterns.

abstract property properties: CartographyRelProperties

Properties to be set on the relationship.

This property defines the CartographyRelProperties instance that contains all the attributes to be assigned to the relationship in the Neo4j SET clause.

Returns:

A CartographyRelProperties instance containing the relationship properties.

abstract property rel_label: str

Label of the relationship.

This property defines the Neo4j relationship type that will be created between the source and target nodes. The label appears in the Neo4j relationship syntax as [:LABEL].

Returns:

The string label of the relationship type.

property source_node_label: str | None

Source node label for load_matchlinks() operations.

This optional property is only used with load_matchlinks() operations where relationships are created between existing nodes. It specifies the Neo4j node label of the source node for the relationship.

Returns:

The string label of the source node type, or None if not applicable. Default implementation returns None.

Note

This property does not affect CartographyRelSchema objects that are included in CartographyNodeSchema objects. It is only relevant for standalone relationship creation using load_matchlinks().

property source_node_matcher: SourceNodeMatcher | None

Source node matcher for load_matchlinks() operations.

This optional property is only used with load_matchlinks() operations where relationships are created between existing nodes. It specifies the SourceNodeMatcher that defines how to identify the source nodes for the relationship.

Note

This property does not affect CartographyRelSchema objects that are included in CartographyNodeSchema objects. It is only relevant for standalone relationship creation using load_matchlinks().

Use make_source_node_matcher() to create the matcher with the appropriate key-value pairs for your specific use case.

abstract property target_node_label: str

Label of the target node for this relationship.

This property defines the Neo4j node label that this relationship will connect to. The target node must already exist in the graph database.

Returns:

The string label of the target node type.

abstract property target_node_matcher: TargetNodeMatcher

Matcher used to identify target nodes for this relationship.

This property defines the TargetNodeMatcher that specifies how to find the target nodes that this relationship should connect to. The matcher contains the keys and PropertyRef values used to identify unique target nodes.

Returns:

A TargetNodeMatcher instance with the matching criteria.

Note

Use make_target_node_matcher() to create the matcher with the appropriate key-value pairs for your specific use case.

class cartography.models.core.relationships.LinkDirection(value)

Bases: Enum

Enum defining the direction of relationships in CartographyRelSchema.

Each CartographyRelSchema has a LinkDirection that determines whether the relationship points toward the original node (“INWARD”) or away from the original node (“OUTWARD”). This controls the directionality of the Neo4j relationship arrows.

INWARD

The relationship points toward the original node (incoming).

OUTWARD

The relationship points away from the original node (outgoing).

INWARD = 1
OUTWARD = 2
class cartography.models.core.relationships.OtherRelationships(rels: List[CartographyRelSchema])

Bases: object

Encapsulates a list of CartographyRelSchema objects for additional relationships.

This dataclass is used to group multiple CartographyRelSchema objects together while ensuring dataclass immutability when composed as part of a CartographyNodeSchema object. It allows a node schema to define multiple additional relationships beyond the primary sub_resource_relationship.

rels

A list of CartographyRelSchema objects representing additional relationships.

Type:

List[cartography.models.core.relationships.CartographyRelSchema]

Examples

Creating additional relationships for an EC2 instance: >>> other_rels = OtherRelationships(rels=[ … EC2InstanceToVPCRel(), … EC2InstanceToSecurityGroupRel(), … EC2InstanceToSubnetRel() … ])

Using in a CartographyNodeSchema: >>> class EC2InstanceSchema(CartographyNodeSchema): … other_relationships: OtherRelationships = other_rels

__init__(rels: List[CartographyRelSchema]) None
rels: List[CartographyRelSchema]
class cartography.models.core.relationships.SourceNodeMatcher

Bases: object

Encapsulates node matching criteria for source nodes in relationships.

This dataclass is identical to TargetNodeMatcher but specifically designed for matching source nodes. It is used exclusively with load_matchlinks() operations where relationships are created between existing nodes.

The class serves as a base template that is dynamically extended by make_source_node_matcher() to create specific matching criteria.

Examples

Creating a matcher for EC2 instance source nodes: >>> from cartography.models.core.common import PropertyRef >>> matcher = make_source_node_matcher({ … ‘instanceid’: PropertyRef(‘InstanceId’), … ‘account_id’: PropertyRef(‘AccountId’) … })

The resulting matcher will have instanceid and account_id attributes with the corresponding PropertyRef values.

Note

This class is only used for load_matchlinks() operations where we match on and connect existing nodes. It has no effect on CartographyRelSchema objects that are included in CartographyNodeSchema.

Use make_source_node_matcher() to create instances with the required attributes for specific use cases.

__init__() None
class cartography.models.core.relationships.TargetNodeMatcher

Bases: object

Encapsulates node matching criteria for target nodes in relationships.

This dataclass is used to define the mapping between attribute names on the target node and their corresponding PropertyRef values. It ensures immutability when composed as part of a CartographyNodeSchema object.

The class serves as a base template that is dynamically extended by make_target_node_matcher() to create specific matching criteria.

Dynamically created by `make_target_node_matcher()` based on the
key_ref_dict parameter. Each key becomes an attribute with a PropertyRef value.

Examples

Creating a matcher for AWS Account nodes: >>> from cartography.models.core.common import PropertyRef >>> matcher = make_target_node_matcher({ … ‘id’: PropertyRef(‘AccountId’), … ‘arn’: PropertyRef(‘Arn’) … })

The resulting matcher will have id and arn attributes with the corresponding PropertyRef values.

Note

This class is not meant to be instantiated directly. Use make_target_node_matcher() to create instances with the required attributes for specific use cases.

__init__() None
cartography.models.core.relationships.make_source_node_matcher(key_ref_dict: Dict[str, PropertyRef]) SourceNodeMatcher

Create a SourceNodeMatcher with dynamically generated attributes.

This function creates a specialized SourceNodeMatcher dataclass with attributes corresponding to the keys in the provided dictionary. Each attribute is initialized with its corresponding PropertyRef value.

Parameters:

key_ref_dict – A dictionary mapping attribute names to PropertyRef objects. The keys become attribute names on the source node, and the values are PropertyRef objects that define how to extract the matching values from the data.

Returns:

A SourceNodeMatcher instance with dynamically created attributes corresponding to the provided key_ref_dict.

cartography.models.core.relationships.make_target_node_matcher(key_ref_dict: Dict[str, PropertyRef]) TargetNodeMatcher

Create a TargetNodeMatcher with dynamically generated attributes.

This function creates a specialized TargetNodeMatcher dataclass with attributes corresponding to the keys in the provided dictionary. Each attribute is initialized with its corresponding PropertyRef value.

Parameters:

key_ref_dict – A dictionary mapping attribute names to PropertyRef objects. The keys become attribute names on the target node, and the values are PropertyRef objects that define how to extract the matching values from the data.

Returns:

A TargetNodeMatcher instance with dynamically created attributes corresponding to the provided key_ref_dict.

Examples

Creating a matcher for AWS EC2 instances: >>> from cartography.models.core.common import PropertyRef >>> matcher = make_target_node_matcher({ … ‘instanceid’: PropertyRef(‘InstanceId’), … ‘region’: PropertyRef(‘Region’) … }) >>> # The resulting matcher has instanceid and region attributes

Creating a matcher for a single key: >>> matcher = make_target_node_matcher({ … ‘id’: PropertyRef(‘Id’) … }) >>> # The resulting matcher has an id attribute

Common

class cartography.models.core.common.PropertyRef(name: str, set_in_kwargs=False, extra_index=False, ignore_case=False, fuzzy_and_ignore_case=False, one_to_many=False)

Bases: object

Represents properties on cartography nodes and relationships.

PropertyRefs allow dynamically generated Neo4j ingestion queries to set values for node or relationship properties from either:

  1. A field on the dict being processed (set_in_kwargs=False; default)

  2. A single variable provided by a keyword argument (set_in_kwargs=True)

Cartography takes lists of Python dicts and loads them to Neo4j using these property references to map data appropriately.

Examples

>>> # Basic property reference from data dict
>>> prop_ref = PropertyRef('name')
>>> str(prop_ref)  # Returns: 'item.name'
>>> # Property reference from kwargs
>>> prop_ref = PropertyRef('lastupdated', set_in_kwargs=True)
>>> str(prop_ref)  # Returns: '$lastupdated'
>>> # Property with extra index for frequent queries
>>> prop_ref = PropertyRef('arn', extra_index=True)
>>> # Case-insensitive matching
>>> prop_ref = PropertyRef('username', ignore_case=True)
>>> # One-to-many relationship
>>> prop_ref = PropertyRef('role_arns', one_to_many=True)

Note

PropertyRef instances are typically used within CartographyNodeSchema and CartographyRelSchema definitions to specify how data should be mapped from source dictionaries to Neo4j graph properties.

__init__(name: str, set_in_kwargs=False, extra_index=False, ignore_case=False, fuzzy_and_ignore_case=False, one_to_many=False)

Initialize a PropertyRef instance.

Parameters:
  • name (str) – The name of the property.

  • set_in_kwargs (bool, optional) – If True, the property is not defined on the data dict, and we expect to find the property in the kwargs. If False, looks for the property in the data dict. Defaults to False.

  • extra_index (bool, optional) – If True, creates an index for this property name. Available for properties that are queried frequently. Defaults to False.

  • ignore_case (bool, optional) – If True, performs a case-insensitive match when comparing the value of this property during relationship creation. Only has effect as part of a TargetNodeMatcher, and is not supported for sub resource relationships. Defaults to False.

  • fuzzy_and_ignore_case (bool, optional) – If True, performs a fuzzy + case-insensitive match when comparing the value of this property using the CONTAINS operator. Only has effect as part of a TargetNodeMatcher and is not supported for sub resource relationships. Defaults to False.

  • one_to_many (bool, optional) – Indicates that this property creates one-to-many associations. If True, this property ref points to a list stored on the data dict where each item is an ID. Only has effect as part of a TargetNodeMatcher and is not supported for sub resource relationships. Defaults to False.

Examples

Case-insensitive matching for GitHub usernames:

GitHub usernames can have both uppercase and lowercase characters, but GitHub treats usernames as case-insensitive. If your company’s internal personnel database stores GitHub usernames all as lowercase, you would need to perform a case-insensitive match between your company’s record and your cartography catalog of GitHubUser nodes:

PropertyRef('username', ignore_case=True)
One-to-many associations for AWS IAM instance profiles:

AWS IAM instance profiles can be associated with one or more roles. When calling describe-iam-instance-profiles, the Roles field contains a list of all roles that the profile is associated with:

class InstanceProfileSchema(Schema):
    target_node_label: str = 'AWSRole'
    target_node_matcher: TargetNodeMatcher = make_target_node_matcher({
        'arn': PropertyRef('Roles', one_to_many=True),
    })

This searches for AWSRoles to attach by checking if each role’s arn field is in the Roles list of the data dict.

Note

  • one_to_many has no effect on matchlinks.

  • extra_index is available for properties that will be queried frequently.

  • The id and lastupdated properties automatically have indexes created by ensure_indexes().

  • All properties included in target node matchers automatically have indexes created.

Raises:
  • ValueError – If ignore_case is used together with fuzzy_and_ignore_case.

  • ValueError – If one_to_many is used together with ignore_case or fuzzy_and_ignore_case.

__repr__() str

Return the string representation used in Neo4j query building.

The querybuilder.build_ingestion_query() generates a Neo4j batched ingestion query of the form UNWIND $DictList AS item [...]. This method provides the appropriate property reference format based on whether the property value comes from the data dictionary or from keyword arguments.

Returns:

Either item.<property_name> if set_in_kwargs is False, or

$<property_name> if set_in_kwargs is True.

Return type:

str

Examples

>>> # Property from data dictionary
>>> prop_ref = PropertyRef('name')
>>> str(prop_ref)
'item.name'
>>> # Property from keyword arguments
>>> prop_ref = PropertyRef('lastupdated', set_in_kwargs=True)
>>> str(prop_ref)
'$lastupdated'