cartography 0.105.0__py3-none-any.whl → 0.106.0rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cartography might be problematic. Click here for more details.
- cartography/_version.py +2 -2
- cartography/client/core/tx.py +62 -0
- cartography/data/indexes.cypher +0 -34
- cartography/graph/cleanupbuilder.py +47 -0
- cartography/graph/job.py +42 -0
- cartography/graph/querybuilder.py +136 -2
- cartography/graph/statement.py +1 -1
- cartography/intel/aws/ecs.py +228 -380
- cartography/intel/aws/efs.py +261 -0
- cartography/intel/aws/identitycenter.py +14 -3
- cartography/intel/aws/inspector.py +96 -53
- cartography/intel/aws/rds.py +2 -1
- cartography/intel/aws/resources.py +2 -0
- cartography/intel/entra/__init__.py +11 -0
- cartography/intel/entra/applications.py +366 -0
- cartography/intel/kubernetes/__init__.py +30 -14
- cartography/intel/kubernetes/clusters.py +86 -0
- cartography/intel/kubernetes/namespaces.py +59 -57
- cartography/intel/kubernetes/pods.py +140 -77
- cartography/intel/kubernetes/secrets.py +95 -45
- cartography/intel/kubernetes/services.py +131 -67
- cartography/intel/kubernetes/util.py +125 -14
- cartography/models/aws/ecs/__init__.py +0 -0
- cartography/models/aws/ecs/clusters.py +64 -0
- cartography/models/aws/ecs/container_definitions.py +93 -0
- cartography/models/aws/ecs/container_instances.py +84 -0
- cartography/models/aws/ecs/containers.py +80 -0
- cartography/models/aws/ecs/services.py +117 -0
- cartography/models/aws/ecs/task_definitions.py +97 -0
- cartography/models/aws/ecs/tasks.py +110 -0
- cartography/models/aws/efs/__init__.py +0 -0
- cartography/models/aws/efs/access_point.py +77 -0
- cartography/models/aws/efs/file_system.py +60 -0
- cartography/models/aws/efs/mount_target.py +79 -0
- cartography/models/core/common.py +1 -0
- cartography/models/core/relationships.py +44 -0
- cartography/models/entra/app_role_assignment.py +115 -0
- cartography/models/entra/application.py +47 -0
- cartography/models/kubernetes/__init__.py +0 -0
- cartography/models/kubernetes/clusters.py +26 -0
- cartography/models/kubernetes/containers.py +108 -0
- cartography/models/kubernetes/namespaces.py +51 -0
- cartography/models/kubernetes/pods.py +80 -0
- cartography/models/kubernetes/secrets.py +79 -0
- cartography/models/kubernetes/services.py +108 -0
- cartography/util.py +15 -10
- {cartography-0.105.0.dist-info → cartography-0.106.0rc2.dist-info}/METADATA +1 -1
- {cartography-0.105.0.dist-info → cartography-0.106.0rc2.dist-info}/RECORD +52 -29
- cartography/data/jobs/cleanup/kubernetes_import_cleanup.json +0 -70
- {cartography-0.105.0.dist-info → cartography-0.106.0rc2.dist-info}/WHEEL +0 -0
- {cartography-0.105.0.dist-info → cartography-0.106.0rc2.dist-info}/entry_points.txt +0 -0
- {cartography-0.105.0.dist-info → cartography-0.106.0rc2.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.105.0.dist-info → cartography-0.106.0rc2.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from datetime import datetime
|
|
2
|
-
from typing import
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Any
|
|
4
|
+
from typing import Callable
|
|
4
5
|
|
|
5
6
|
from kubernetes import config
|
|
6
7
|
from kubernetes.client import ApiClient
|
|
7
8
|
from kubernetes.client import CoreV1Api
|
|
8
9
|
from kubernetes.client import NetworkingV1Api
|
|
10
|
+
from kubernetes.client import VersionApi
|
|
11
|
+
from kubernetes.client.exceptions import ApiException
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
9
14
|
|
|
10
15
|
|
|
11
16
|
class KubernetesContextNotFound(Exception):
|
|
@@ -13,39 +18,145 @@ class KubernetesContextNotFound(Exception):
|
|
|
13
18
|
|
|
14
19
|
|
|
15
20
|
class K8CoreApiClient(CoreV1Api):
|
|
16
|
-
def __init__(
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
name: str,
|
|
24
|
+
config_file: str,
|
|
25
|
+
api_client: ApiClient | None = None,
|
|
26
|
+
) -> None:
|
|
17
27
|
self.name = name
|
|
18
28
|
if not api_client:
|
|
19
|
-
api_client = config.new_client_from_config(
|
|
29
|
+
api_client = config.new_client_from_config(
|
|
30
|
+
context=name, config_file=config_file
|
|
31
|
+
)
|
|
20
32
|
super().__init__(api_client=api_client)
|
|
21
33
|
|
|
22
34
|
|
|
23
35
|
class K8NetworkingApiClient(NetworkingV1Api):
|
|
24
|
-
def __init__(
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
name: str,
|
|
39
|
+
config_file: str,
|
|
40
|
+
api_client: ApiClient | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
self.name = name
|
|
43
|
+
if not api_client:
|
|
44
|
+
api_client = config.new_client_from_config(
|
|
45
|
+
context=name, config_file=config_file
|
|
46
|
+
)
|
|
47
|
+
super().__init__(api_client=api_client)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class K8VersionApiClient(VersionApi):
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
name: str,
|
|
54
|
+
config_file: str,
|
|
55
|
+
api_client: ApiClient | None = None,
|
|
56
|
+
) -> None:
|
|
25
57
|
self.name = name
|
|
26
58
|
if not api_client:
|
|
27
|
-
api_client = config.new_client_from_config(
|
|
59
|
+
api_client = config.new_client_from_config(
|
|
60
|
+
context=name, config_file=config_file
|
|
61
|
+
)
|
|
28
62
|
super().__init__(api_client=api_client)
|
|
29
63
|
|
|
30
64
|
|
|
31
65
|
class K8sClient:
|
|
32
|
-
def __init__(
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
name: str,
|
|
69
|
+
config_file: str,
|
|
70
|
+
external_id: str | None = None,
|
|
71
|
+
) -> None:
|
|
33
72
|
self.name = name
|
|
34
|
-
self.
|
|
35
|
-
self.
|
|
73
|
+
self.config_file = config_file
|
|
74
|
+
self.external_id = external_id
|
|
75
|
+
self.core = K8CoreApiClient(self.name, self.config_file)
|
|
76
|
+
self.networking = K8NetworkingApiClient(self.name, self.config_file)
|
|
77
|
+
self.version = K8VersionApiClient(self.name, self.config_file)
|
|
36
78
|
|
|
37
79
|
|
|
38
|
-
def get_k8s_clients(kubeconfig: str) ->
|
|
80
|
+
def get_k8s_clients(kubeconfig: str) -> list[K8sClient]:
|
|
81
|
+
# returns a tuple of (all contexts, current context)
|
|
39
82
|
contexts, _ = config.list_kube_config_contexts(kubeconfig)
|
|
40
83
|
if not contexts:
|
|
41
84
|
raise KubernetesContextNotFound("No context found in kubeconfig.")
|
|
42
|
-
|
|
85
|
+
|
|
86
|
+
clients = []
|
|
43
87
|
for context in contexts:
|
|
44
|
-
clients.append(
|
|
88
|
+
clients.append(
|
|
89
|
+
K8sClient(
|
|
90
|
+
context["name"],
|
|
91
|
+
kubeconfig,
|
|
92
|
+
external_id=context["context"].get("cluster"),
|
|
93
|
+
),
|
|
94
|
+
)
|
|
45
95
|
return clients
|
|
46
96
|
|
|
47
97
|
|
|
48
|
-
def get_epoch(date: datetime) ->
|
|
98
|
+
def get_epoch(date: datetime | None) -> int | None:
|
|
49
99
|
if date:
|
|
50
|
-
return int(date.
|
|
100
|
+
return int(date.timestamp())
|
|
51
101
|
return None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def k8s_paginate(
|
|
105
|
+
list_func: Callable,
|
|
106
|
+
**kwargs: Any,
|
|
107
|
+
) -> list[dict[str, Any]]:
|
|
108
|
+
"""
|
|
109
|
+
Handles pagination for a Kubernetes API call.
|
|
110
|
+
|
|
111
|
+
:param list_func: The list function to call (e.g. client.core.list_pod_for_all_namespaces)
|
|
112
|
+
:param kwargs: Keyword arguments to pass to the list function (e.g. limit=100)
|
|
113
|
+
:return: A list of all resources returned by the list function
|
|
114
|
+
"""
|
|
115
|
+
all_resources = []
|
|
116
|
+
continue_token = None
|
|
117
|
+
limit = kwargs.pop("limit", 100)
|
|
118
|
+
function_name = list_func.__name__
|
|
119
|
+
|
|
120
|
+
logger.debug(f"Starting pagination for {function_name} with limit {limit}.")
|
|
121
|
+
|
|
122
|
+
while True:
|
|
123
|
+
try:
|
|
124
|
+
if continue_token:
|
|
125
|
+
response = list_func(limit=limit, _continue=continue_token, **kwargs)
|
|
126
|
+
else:
|
|
127
|
+
response = list_func(limit=limit, **kwargs)
|
|
128
|
+
|
|
129
|
+
# Check if items exists on the response
|
|
130
|
+
if not hasattr(response, "items"):
|
|
131
|
+
logger.warning(
|
|
132
|
+
f"Response from {function_name} does not contain 'items' attribute."
|
|
133
|
+
)
|
|
134
|
+
break
|
|
135
|
+
|
|
136
|
+
items_count = len(response.items)
|
|
137
|
+
all_resources.extend(response.items)
|
|
138
|
+
|
|
139
|
+
logger.debug(f"Retrieved {items_count} {function_name} resources")
|
|
140
|
+
|
|
141
|
+
# Check if metadata exists on the response
|
|
142
|
+
if not hasattr(response, "metadata"):
|
|
143
|
+
logger.warning(
|
|
144
|
+
f"Response from {function_name} does not contain 'metadata' attribute."
|
|
145
|
+
)
|
|
146
|
+
break
|
|
147
|
+
|
|
148
|
+
continue_token = response.metadata._continue
|
|
149
|
+
if not continue_token:
|
|
150
|
+
logger.debug(f"No more {function_name} resources to retrieve.")
|
|
151
|
+
break
|
|
152
|
+
|
|
153
|
+
except ApiException as e:
|
|
154
|
+
logger.error(
|
|
155
|
+
f"Kubernetes API error retrieving {function_name} resources. {e}: {e.status} - {e.reason}"
|
|
156
|
+
)
|
|
157
|
+
break
|
|
158
|
+
|
|
159
|
+
logger.debug(
|
|
160
|
+
f"Completed pagination for {function_name}: retrieved {len(all_resources)} resources"
|
|
161
|
+
)
|
|
162
|
+
return all_resources
|
|
File without changes
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cartography.models.core.common import PropertyRef
|
|
4
|
+
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
+
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
+
from cartography.models.core.relationships import LinkDirection
|
|
9
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class ECSClusterNodeProperties(CartographyNodeProperties):
|
|
15
|
+
id: PropertyRef = PropertyRef("clusterArn")
|
|
16
|
+
arn: PropertyRef = PropertyRef("clusterArn", extra_index=True)
|
|
17
|
+
name: PropertyRef = PropertyRef("clusterName")
|
|
18
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
19
|
+
status: PropertyRef = PropertyRef("status")
|
|
20
|
+
ecc_kms_key_id: PropertyRef = PropertyRef("ecc_kms_key_id")
|
|
21
|
+
ecc_logging: PropertyRef = PropertyRef("ecc_logging")
|
|
22
|
+
ecc_log_configuration_cloud_watch_log_group_name: PropertyRef = PropertyRef(
|
|
23
|
+
"ecc_log_configuration_cloud_watch_log_group_name"
|
|
24
|
+
)
|
|
25
|
+
ecc_log_configuration_cloud_watch_encryption_enabled: PropertyRef = PropertyRef(
|
|
26
|
+
"ecc_log_configuration_cloud_watch_encryption_enabled"
|
|
27
|
+
)
|
|
28
|
+
ecc_log_configuration_s3_bucket_name: PropertyRef = PropertyRef(
|
|
29
|
+
"ecc_log_configuration_s3_bucket_name"
|
|
30
|
+
)
|
|
31
|
+
ecc_log_configuration_s3_encryption_enabled: PropertyRef = PropertyRef(
|
|
32
|
+
"ecc_log_configuration_s3_encryption_enabled"
|
|
33
|
+
)
|
|
34
|
+
ecc_log_configuration_s3_key_prefix: PropertyRef = PropertyRef(
|
|
35
|
+
"ecc_log_configuration_s3_key_prefix"
|
|
36
|
+
)
|
|
37
|
+
capacity_providers: PropertyRef = PropertyRef("capacityProviders")
|
|
38
|
+
attachments_status: PropertyRef = PropertyRef("attachmentsStatus")
|
|
39
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True)
|
|
43
|
+
class ECSClusterToAWSAccountRelProperties(CartographyRelProperties):
|
|
44
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class ECSClusterToAWSAccountRel(CartographyRelSchema):
|
|
49
|
+
target_node_label: str = "AWSAccount"
|
|
50
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
51
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
|
|
52
|
+
)
|
|
53
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
54
|
+
rel_label: str = "RESOURCE"
|
|
55
|
+
properties: ECSClusterToAWSAccountRelProperties = (
|
|
56
|
+
ECSClusterToAWSAccountRelProperties()
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(frozen=True)
|
|
61
|
+
class ECSClusterSchema(CartographyNodeSchema):
|
|
62
|
+
label: str = "ECSCluster"
|
|
63
|
+
properties: ECSClusterNodeProperties = ECSClusterNodeProperties()
|
|
64
|
+
sub_resource_relationship: ECSClusterToAWSAccountRel = ECSClusterToAWSAccountRel()
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cartography.models.core.common import PropertyRef
|
|
4
|
+
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
+
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
+
from cartography.models.core.relationships import LinkDirection
|
|
9
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
+
from cartography.models.core.relationships import OtherRelationships
|
|
11
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class ECSContainerDefinitionNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef("id")
|
|
17
|
+
task_definition_arn: PropertyRef = PropertyRef("_taskDefinitionArn")
|
|
18
|
+
name: PropertyRef = PropertyRef("name")
|
|
19
|
+
image: PropertyRef = PropertyRef("image")
|
|
20
|
+
cpu: PropertyRef = PropertyRef("cpu")
|
|
21
|
+
memory: PropertyRef = PropertyRef("memory")
|
|
22
|
+
memory_reservation: PropertyRef = PropertyRef("memoryReservation")
|
|
23
|
+
links: PropertyRef = PropertyRef("links")
|
|
24
|
+
essential: PropertyRef = PropertyRef("essential")
|
|
25
|
+
entry_point: PropertyRef = PropertyRef("entryPoint")
|
|
26
|
+
command: PropertyRef = PropertyRef("command")
|
|
27
|
+
start_timeout: PropertyRef = PropertyRef("startTimeout")
|
|
28
|
+
stop_timeout: PropertyRef = PropertyRef("stop_timeout")
|
|
29
|
+
hostname: PropertyRef = PropertyRef("hostname")
|
|
30
|
+
user: PropertyRef = PropertyRef("user")
|
|
31
|
+
working_directory: PropertyRef = PropertyRef("workingDirectory")
|
|
32
|
+
disable_networking: PropertyRef = PropertyRef("disableNetworking")
|
|
33
|
+
privileged: PropertyRef = PropertyRef("privileged")
|
|
34
|
+
readonly_root_filesystem: PropertyRef = PropertyRef("readonlyRootFilesystem")
|
|
35
|
+
dns_servers: PropertyRef = PropertyRef("dnsServers")
|
|
36
|
+
dns_search_domains: PropertyRef = PropertyRef("dnsSearchDomains")
|
|
37
|
+
docker_security_options: PropertyRef = PropertyRef("dockerSecurityOptions")
|
|
38
|
+
interactive: PropertyRef = PropertyRef("interactive")
|
|
39
|
+
pseudo_terminal: PropertyRef = PropertyRef("pseudoTerminal")
|
|
40
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
41
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class ECSContainerDefinitionToAWSAccountRelProperties(CartographyRelProperties):
|
|
46
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True)
|
|
50
|
+
class ECSContainerDefinitionToAWSAccountRel(CartographyRelSchema):
|
|
51
|
+
target_node_label: str = "AWSAccount"
|
|
52
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
53
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
|
|
54
|
+
)
|
|
55
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
56
|
+
rel_label: str = "RESOURCE"
|
|
57
|
+
properties: ECSContainerDefinitionToAWSAccountRelProperties = (
|
|
58
|
+
ECSContainerDefinitionToAWSAccountRelProperties()
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(frozen=True)
|
|
63
|
+
class ECSContainerDefinitionToTaskDefinitionRelProperties(CartographyRelProperties):
|
|
64
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass(frozen=True)
|
|
68
|
+
class ECSContainerDefinitionToTaskDefinitionRel(CartographyRelSchema):
|
|
69
|
+
target_node_label: str = "ECSTaskDefinition"
|
|
70
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
71
|
+
{"id": PropertyRef("_taskDefinitionArn")}
|
|
72
|
+
)
|
|
73
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
74
|
+
rel_label: str = "HAS_CONTAINER_DEFINITION"
|
|
75
|
+
properties: ECSContainerDefinitionToTaskDefinitionRelProperties = (
|
|
76
|
+
ECSContainerDefinitionToTaskDefinitionRelProperties()
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass(frozen=True)
|
|
81
|
+
class ECSContainerDefinitionSchema(CartographyNodeSchema):
|
|
82
|
+
label: str = "ECSContainerDefinition"
|
|
83
|
+
properties: ECSContainerDefinitionNodeProperties = (
|
|
84
|
+
ECSContainerDefinitionNodeProperties()
|
|
85
|
+
)
|
|
86
|
+
sub_resource_relationship: ECSContainerDefinitionToAWSAccountRel = (
|
|
87
|
+
ECSContainerDefinitionToAWSAccountRel()
|
|
88
|
+
)
|
|
89
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
90
|
+
[
|
|
91
|
+
ECSContainerDefinitionToTaskDefinitionRel(),
|
|
92
|
+
]
|
|
93
|
+
)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cartography.models.core.common import PropertyRef
|
|
4
|
+
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
+
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
+
from cartography.models.core.relationships import LinkDirection
|
|
9
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
+
from cartography.models.core.relationships import OtherRelationships
|
|
11
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class ECSContainerInstanceNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef("containerInstanceArn")
|
|
17
|
+
arn: PropertyRef = PropertyRef("containerInstanceArn", extra_index=True)
|
|
18
|
+
ec2_instance_id: PropertyRef = PropertyRef("ec2InstanceId")
|
|
19
|
+
capacity_provider_name: PropertyRef = PropertyRef("capacityProviderName")
|
|
20
|
+
version: PropertyRef = PropertyRef("version")
|
|
21
|
+
version_info_agent_version: PropertyRef = PropertyRef("versionInfo.agentVersion")
|
|
22
|
+
version_info_agent_hash: PropertyRef = PropertyRef("versionInfo.agentHash")
|
|
23
|
+
version_info_agent_docker_version: PropertyRef = PropertyRef(
|
|
24
|
+
"versionInfo.dockerVersion"
|
|
25
|
+
)
|
|
26
|
+
status: PropertyRef = PropertyRef("status")
|
|
27
|
+
status_reason: PropertyRef = PropertyRef("statusReason")
|
|
28
|
+
agent_connected: PropertyRef = PropertyRef("agentConnected")
|
|
29
|
+
agent_update_status: PropertyRef = PropertyRef("agentUpdateStatus")
|
|
30
|
+
registered_at: PropertyRef = PropertyRef("registeredAt")
|
|
31
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
32
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class ECSContainerInstanceToAWSAccountRelProperties(CartographyRelProperties):
|
|
37
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True)
|
|
41
|
+
class ECSContainerInstanceToAWSAccountRel(CartographyRelSchema):
|
|
42
|
+
target_node_label: str = "AWSAccount"
|
|
43
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
44
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
|
|
45
|
+
)
|
|
46
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
47
|
+
rel_label: str = "RESOURCE"
|
|
48
|
+
properties: ECSContainerInstanceToAWSAccountRelProperties = (
|
|
49
|
+
ECSContainerInstanceToAWSAccountRelProperties()
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass(frozen=True)
|
|
54
|
+
class ECSContainerInstanceToECSClusterRelProperties(CartographyRelProperties):
|
|
55
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True)
|
|
59
|
+
class ECSContainerInstanceToECSClusterRel(CartographyRelSchema):
|
|
60
|
+
target_node_label: str = "ECSCluster"
|
|
61
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
62
|
+
{"id": PropertyRef("ClusterArn", set_in_kwargs=True)}
|
|
63
|
+
)
|
|
64
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
65
|
+
rel_label: str = "HAS_CONTAINER_INSTANCE"
|
|
66
|
+
properties: ECSContainerInstanceToECSClusterRelProperties = (
|
|
67
|
+
ECSContainerInstanceToECSClusterRelProperties()
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class ECSContainerInstanceSchema(CartographyNodeSchema):
|
|
73
|
+
label: str = "ECSContainerInstance"
|
|
74
|
+
properties: ECSContainerInstanceNodeProperties = (
|
|
75
|
+
ECSContainerInstanceNodeProperties()
|
|
76
|
+
)
|
|
77
|
+
sub_resource_relationship: ECSContainerInstanceToAWSAccountRel = (
|
|
78
|
+
ECSContainerInstanceToAWSAccountRel()
|
|
79
|
+
)
|
|
80
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
81
|
+
[
|
|
82
|
+
ECSContainerInstanceToECSClusterRel(),
|
|
83
|
+
]
|
|
84
|
+
)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cartography.models.core.common import PropertyRef
|
|
4
|
+
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
+
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
+
from cartography.models.core.relationships import LinkDirection
|
|
9
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
+
from cartography.models.core.relationships import OtherRelationships
|
|
11
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class ECSContainerNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef("containerArn")
|
|
17
|
+
arn: PropertyRef = PropertyRef("containerArn", extra_index=True)
|
|
18
|
+
task_arn: PropertyRef = PropertyRef("taskArn")
|
|
19
|
+
name: PropertyRef = PropertyRef("name")
|
|
20
|
+
image: PropertyRef = PropertyRef("image")
|
|
21
|
+
image_digest: PropertyRef = PropertyRef("imageDigest")
|
|
22
|
+
runtime_id: PropertyRef = PropertyRef("runtimeId")
|
|
23
|
+
last_status: PropertyRef = PropertyRef("lastStatus")
|
|
24
|
+
exit_code: PropertyRef = PropertyRef("exitCode")
|
|
25
|
+
reason: PropertyRef = PropertyRef("reason")
|
|
26
|
+
health_status: PropertyRef = PropertyRef("healthStatus")
|
|
27
|
+
cpu: PropertyRef = PropertyRef("cpu")
|
|
28
|
+
memory: PropertyRef = PropertyRef("memory")
|
|
29
|
+
memory_reservation: PropertyRef = PropertyRef("memoryReservation")
|
|
30
|
+
gpu_ids: PropertyRef = PropertyRef("gpuIds")
|
|
31
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
32
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class ECSContainerToAWSAccountRelProperties(CartographyRelProperties):
|
|
37
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True)
|
|
41
|
+
class ECSContainerToAWSAccountRel(CartographyRelSchema):
|
|
42
|
+
target_node_label: str = "AWSAccount"
|
|
43
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
44
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
|
|
45
|
+
)
|
|
46
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
47
|
+
rel_label: str = "RESOURCE"
|
|
48
|
+
properties: ECSContainerToAWSAccountRelProperties = (
|
|
49
|
+
ECSContainerToAWSAccountRelProperties()
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass(frozen=True)
|
|
54
|
+
class ECSContainerToTaskRelProperties(CartographyRelProperties):
|
|
55
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True)
|
|
59
|
+
class ECSContainerToTaskRel(CartographyRelSchema):
|
|
60
|
+
target_node_label: str = "ECSTask"
|
|
61
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
62
|
+
{"id": PropertyRef("taskArn")}
|
|
63
|
+
)
|
|
64
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
65
|
+
rel_label: str = "HAS_CONTAINER"
|
|
66
|
+
properties: ECSContainerToTaskRelProperties = ECSContainerToTaskRelProperties()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass(frozen=True)
|
|
70
|
+
class ECSContainerSchema(CartographyNodeSchema):
|
|
71
|
+
label: str = "ECSContainer"
|
|
72
|
+
properties: ECSContainerNodeProperties = ECSContainerNodeProperties()
|
|
73
|
+
sub_resource_relationship: ECSContainerToAWSAccountRel = (
|
|
74
|
+
ECSContainerToAWSAccountRel()
|
|
75
|
+
)
|
|
76
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
77
|
+
[
|
|
78
|
+
ECSContainerToTaskRel(),
|
|
79
|
+
]
|
|
80
|
+
)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cartography.models.core.common import PropertyRef
|
|
4
|
+
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
+
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
+
from cartography.models.core.relationships import LinkDirection
|
|
9
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
+
from cartography.models.core.relationships import OtherRelationships
|
|
11
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class ECSServiceNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef("serviceArn")
|
|
17
|
+
arn: PropertyRef = PropertyRef("serviceArn", extra_index=True)
|
|
18
|
+
name: PropertyRef = PropertyRef("serviceName")
|
|
19
|
+
cluster_arn: PropertyRef = PropertyRef("clusterArn")
|
|
20
|
+
status: PropertyRef = PropertyRef("status")
|
|
21
|
+
desired_count: PropertyRef = PropertyRef("desiredCount")
|
|
22
|
+
running_count: PropertyRef = PropertyRef("runningCount")
|
|
23
|
+
pending_count: PropertyRef = PropertyRef("pendingCount")
|
|
24
|
+
launch_type: PropertyRef = PropertyRef("launchType")
|
|
25
|
+
platform_version: PropertyRef = PropertyRef("platformVersion")
|
|
26
|
+
platform_family: PropertyRef = PropertyRef("platformFamily")
|
|
27
|
+
task_definition: PropertyRef = PropertyRef("taskDefinition")
|
|
28
|
+
deployment_config_circuit_breaker_enable: PropertyRef = PropertyRef(
|
|
29
|
+
"deploymentConfiguration.deploymentCircuitBreaker.enable"
|
|
30
|
+
)
|
|
31
|
+
deployment_config_circuit_breaker_rollback: PropertyRef = PropertyRef(
|
|
32
|
+
"deploymentConfiguration.deploymentCircuitBreaker.rollback"
|
|
33
|
+
)
|
|
34
|
+
deployment_config_maximum_percent: PropertyRef = PropertyRef(
|
|
35
|
+
"deploymentConfiguration.maximumPercent"
|
|
36
|
+
)
|
|
37
|
+
deployment_config_minimum_healthy_percent: PropertyRef = PropertyRef(
|
|
38
|
+
"deploymentConfiguration.minimumHealthyPercent"
|
|
39
|
+
)
|
|
40
|
+
role_arn: PropertyRef = PropertyRef("roleArn")
|
|
41
|
+
created_at: PropertyRef = PropertyRef("createdAt")
|
|
42
|
+
health_check_grace_period_seconds: PropertyRef = PropertyRef(
|
|
43
|
+
"healthCheckGracePeriodSeconds"
|
|
44
|
+
)
|
|
45
|
+
created_by: PropertyRef = PropertyRef("createdBy")
|
|
46
|
+
enable_ecs_managed_tags: PropertyRef = PropertyRef("enableECSManagedTags")
|
|
47
|
+
propagate_tags: PropertyRef = PropertyRef("propagateTags")
|
|
48
|
+
enable_execute_command: PropertyRef = PropertyRef("enableExecuteCommand")
|
|
49
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
50
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass(frozen=True)
|
|
54
|
+
class ECSServiceToECSClusterRelProperties(CartographyRelProperties):
|
|
55
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True)
|
|
59
|
+
class ECSServiceToECSClusterRel(CartographyRelSchema):
|
|
60
|
+
target_node_label: str = "ECSCluster"
|
|
61
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
62
|
+
{"id": PropertyRef("ClusterArn", set_in_kwargs=True)}
|
|
63
|
+
)
|
|
64
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
65
|
+
rel_label: str = "HAS_SERVICE"
|
|
66
|
+
properties: ECSServiceToECSClusterRelProperties = (
|
|
67
|
+
ECSServiceToECSClusterRelProperties()
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class ECSServiceToTaskDefinitionRelProperties(CartographyRelProperties):
|
|
73
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class ECSServiceToTaskDefinitionRel(CartographyRelSchema):
|
|
78
|
+
target_node_label: str = "ECSTaskDefinition"
|
|
79
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
80
|
+
{"id": PropertyRef("taskDefinition")}
|
|
81
|
+
)
|
|
82
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
83
|
+
rel_label: str = "HAS_TASK_DEFINITION"
|
|
84
|
+
properties: ECSServiceToTaskDefinitionRelProperties = (
|
|
85
|
+
ECSServiceToTaskDefinitionRelProperties()
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass(frozen=True)
|
|
90
|
+
class ECSServiceToAWSAccountRelProperties(CartographyRelProperties):
|
|
91
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass(frozen=True)
|
|
95
|
+
class ECSServiceToAWSAccountRel(CartographyRelSchema):
|
|
96
|
+
target_node_label: str = "AWSAccount"
|
|
97
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
98
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
|
|
99
|
+
)
|
|
100
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
101
|
+
rel_label: str = "RESOURCE"
|
|
102
|
+
properties: ECSServiceToAWSAccountRelProperties = (
|
|
103
|
+
ECSServiceToAWSAccountRelProperties()
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@dataclass(frozen=True)
|
|
108
|
+
class ECSServiceSchema(CartographyNodeSchema):
|
|
109
|
+
label: str = "ECSService"
|
|
110
|
+
properties: ECSServiceNodeProperties = ECSServiceNodeProperties()
|
|
111
|
+
sub_resource_relationship: ECSServiceToAWSAccountRel = ECSServiceToAWSAccountRel()
|
|
112
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
113
|
+
[
|
|
114
|
+
ECSServiceToECSClusterRel(),
|
|
115
|
+
ECSServiceToTaskDefinitionRel(),
|
|
116
|
+
]
|
|
117
|
+
)
|