Model¶
Nodes¶
- class cartography.models.core.nodes.CartographyNodeProperties¶
Bases:
ABCAbstract 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:
- lastupdated¶
The timestamp of the last update, set automatically.
- Type:
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:
ABCAbstract 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:
- 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:
objectEncapsulates 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:
ABCAbstract 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.
- 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:
ABCAbstract 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:
EnumEnum 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:
objectEncapsulates 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.
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:
objectEncapsulates 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:
objectEncapsulates 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:
objectRepresents properties on cartography nodes and relationships.
PropertyRefs allow dynamically generated Neo4j ingestion queries to set values for node or relationship properties from either:
A field on the dict being processed (
set_in_kwargs=False; default)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
CONTAINSoperator. 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
Rolesfield 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
arnfield is in theRoleslist of the data dict.
Note
one_to_manyhas no effect on matchlinks.extra_indexis available for properties that will be queried frequently.The
idandlastupdatedproperties automatically have indexes created byensure_indexes().All properties included in target node matchers automatically have indexes created.
- Raises:
ValueError – If
ignore_caseis used together withfuzzy_and_ignore_case.ValueError – If
one_to_manyis used together withignore_caseorfuzzy_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 formUNWIND $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>ifset_in_kwargsis False, or $<property_name>ifset_in_kwargsis True.
- Either
- 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'