cartography 0.102.0rc1__py3-none-any.whl → 0.103.0__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/__main__.py +1 -2
- cartography/_version.py +2 -2
- cartography/cli.py +376 -249
- cartography/client/core/tx.py +39 -18
- cartography/config.py +28 -0
- cartography/driftdetect/__main__.py +1 -2
- cartography/driftdetect/add_shortcut.py +10 -2
- cartography/driftdetect/cli.py +71 -75
- cartography/driftdetect/detect_deviations.py +7 -3
- cartography/driftdetect/get_states.py +20 -8
- cartography/driftdetect/model.py +5 -5
- cartography/driftdetect/serializers.py +8 -6
- cartography/driftdetect/storage.py +2 -2
- cartography/graph/cleanupbuilder.py +35 -15
- cartography/graph/job.py +46 -17
- cartography/graph/querybuilder.py +165 -80
- cartography/graph/statement.py +35 -26
- cartography/intel/analysis.py +4 -1
- cartography/intel/aws/__init__.py +114 -55
- cartography/intel/aws/apigateway.py +134 -63
- cartography/intel/aws/cloudtrail.py +127 -0
- cartography/intel/aws/cloudwatch.py +93 -0
- cartography/intel/aws/config.py +56 -20
- cartography/intel/aws/dynamodb.py +108 -40
- cartography/intel/aws/ec2/__init__.py +2 -2
- cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
- cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
- cartography/intel/aws/ec2/images.py +49 -20
- cartography/intel/aws/ec2/instances.py +234 -136
- cartography/intel/aws/ec2/internet_gateways.py +40 -11
- cartography/intel/aws/ec2/key_pairs.py +44 -20
- cartography/intel/aws/ec2/launch_templates.py +101 -59
- cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
- cartography/intel/aws/ec2/load_balancers.py +82 -42
- cartography/intel/aws/ec2/network_acls.py +89 -65
- cartography/intel/aws/ec2/network_interfaces.py +146 -87
- cartography/intel/aws/ec2/reserved_instances.py +45 -16
- cartography/intel/aws/ec2/route_tables.py +327 -0
- cartography/intel/aws/ec2/security_groups.py +71 -21
- cartography/intel/aws/ec2/snapshots.py +61 -22
- cartography/intel/aws/ec2/subnets.py +54 -18
- cartography/intel/aws/ec2/tgw.py +100 -34
- cartography/intel/aws/ec2/util.py +1 -1
- cartography/intel/aws/ec2/volumes.py +69 -41
- cartography/intel/aws/ec2/vpc.py +37 -12
- cartography/intel/aws/ec2/vpc_peerings.py +83 -24
- cartography/intel/aws/ecr.py +88 -32
- cartography/intel/aws/ecs.py +83 -47
- cartography/intel/aws/efs.py +93 -0
- cartography/intel/aws/eks.py +55 -29
- cartography/intel/aws/elasticache.py +42 -18
- cartography/intel/aws/elasticsearch.py +57 -20
- cartography/intel/aws/emr.py +61 -23
- cartography/intel/aws/iam.py +401 -145
- cartography/intel/aws/iam_instance_profiles.py +22 -22
- cartography/intel/aws/identitycenter.py +71 -37
- cartography/intel/aws/inspector.py +159 -89
- cartography/intel/aws/kms.py +92 -38
- cartography/intel/aws/lambda_function.py +103 -34
- cartography/intel/aws/organizations.py +30 -10
- cartography/intel/aws/permission_relationships.py +133 -51
- cartography/intel/aws/rds.py +249 -85
- cartography/intel/aws/redshift.py +107 -46
- cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
- cartography/intel/aws/resources.py +57 -44
- cartography/intel/aws/route53.py +108 -61
- cartography/intel/aws/s3.py +168 -83
- cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
- cartography/intel/aws/secretsmanager.py +24 -12
- cartography/intel/aws/securityhub.py +20 -9
- cartography/intel/aws/sns.py +166 -0
- cartography/intel/aws/sqs.py +60 -28
- cartography/intel/aws/ssm.py +70 -30
- cartography/intel/aws/util/arns.py +7 -7
- cartography/intel/aws/util/common.py +31 -4
- cartography/intel/azure/__init__.py +78 -19
- cartography/intel/azure/compute.py +101 -27
- cartography/intel/azure/cosmosdb.py +496 -170
- cartography/intel/azure/sql.py +296 -105
- cartography/intel/azure/storage.py +322 -113
- cartography/intel/azure/subscription.py +39 -23
- cartography/intel/azure/tenant.py +13 -4
- cartography/intel/azure/util/credentials.py +95 -55
- cartography/intel/bigfix/__init__.py +2 -2
- cartography/intel/bigfix/computers.py +93 -65
- cartography/intel/cloudflare/__init__.py +74 -0
- cartography/intel/cloudflare/accounts.py +57 -0
- cartography/intel/cloudflare/dnsrecords.py +64 -0
- cartography/intel/cloudflare/members.py +75 -0
- cartography/intel/cloudflare/roles.py +65 -0
- cartography/intel/cloudflare/zones.py +64 -0
- cartography/intel/create_indexes.py +3 -2
- cartography/intel/crowdstrike/__init__.py +11 -9
- cartography/intel/crowdstrike/endpoints.py +5 -1
- cartography/intel/crowdstrike/spotlight.py +8 -3
- cartography/intel/cve/__init__.py +46 -13
- cartography/intel/cve/feed.py +48 -12
- cartography/intel/digitalocean/__init__.py +22 -13
- cartography/intel/digitalocean/compute.py +75 -108
- cartography/intel/digitalocean/management.py +44 -80
- cartography/intel/digitalocean/platform.py +48 -43
- cartography/intel/dns.py +36 -10
- cartography/intel/duo/__init__.py +21 -16
- cartography/intel/duo/api_host.py +14 -9
- cartography/intel/duo/endpoints.py +50 -45
- cartography/intel/duo/groups.py +18 -14
- cartography/intel/duo/phones.py +37 -34
- cartography/intel/duo/tokens.py +26 -23
- cartography/intel/duo/users.py +54 -50
- cartography/intel/duo/web_authn_credentials.py +30 -25
- cartography/intel/entra/__init__.py +25 -7
- cartography/intel/entra/ou.py +112 -0
- cartography/intel/entra/users.py +69 -63
- cartography/intel/gcp/__init__.py +185 -49
- cartography/intel/gcp/compute.py +418 -231
- cartography/intel/gcp/crm.py +96 -43
- cartography/intel/gcp/dns.py +60 -19
- cartography/intel/gcp/gke.py +72 -38
- cartography/intel/gcp/iam.py +61 -41
- cartography/intel/gcp/storage.py +84 -55
- cartography/intel/github/__init__.py +13 -11
- cartography/intel/github/repos.py +270 -137
- cartography/intel/github/teams.py +170 -88
- cartography/intel/github/users.py +70 -39
- cartography/intel/github/util.py +36 -34
- cartography/intel/gsuite/__init__.py +47 -26
- cartography/intel/gsuite/api.py +73 -30
- cartography/intel/jamf/__init__.py +19 -1
- cartography/intel/jamf/computers.py +30 -7
- cartography/intel/jamf/util.py +7 -2
- cartography/intel/kandji/__init__.py +6 -3
- cartography/intel/kandji/devices.py +14 -8
- cartography/intel/kubernetes/namespaces.py +7 -4
- cartography/intel/kubernetes/pods.py +7 -4
- cartography/intel/kubernetes/services.py +8 -4
- cartography/intel/lastpass/__init__.py +2 -2
- cartography/intel/lastpass/users.py +23 -12
- cartography/intel/oci/__init__.py +44 -11
- cartography/intel/oci/iam.py +134 -38
- cartography/intel/oci/organizations.py +13 -6
- cartography/intel/oci/utils.py +43 -20
- cartography/intel/okta/__init__.py +66 -15
- cartography/intel/okta/applications.py +42 -20
- cartography/intel/okta/awssaml.py +93 -33
- cartography/intel/okta/factors.py +16 -4
- cartography/intel/okta/groups.py +56 -29
- cartography/intel/okta/organization.py +5 -1
- cartography/intel/okta/origins.py +6 -2
- cartography/intel/okta/roles.py +15 -5
- cartography/intel/okta/users.py +20 -8
- cartography/intel/okta/utils.py +6 -4
- cartography/intel/openai/__init__.py +86 -0
- cartography/intel/openai/adminapikeys.py +90 -0
- cartography/intel/openai/apikeys.py +96 -0
- cartography/intel/openai/projects.py +94 -0
- cartography/intel/openai/serviceaccounts.py +82 -0
- cartography/intel/openai/users.py +78 -0
- cartography/intel/openai/util.py +29 -0
- cartography/intel/pagerduty/__init__.py +8 -7
- cartography/intel/pagerduty/escalation_policies.py +18 -6
- cartography/intel/pagerduty/schedules.py +12 -4
- cartography/intel/pagerduty/services.py +11 -4
- cartography/intel/pagerduty/teams.py +8 -3
- cartography/intel/pagerduty/users.py +3 -1
- cartography/intel/pagerduty/vendors.py +3 -1
- cartography/intel/semgrep/__init__.py +24 -6
- cartography/intel/semgrep/dependencies.py +50 -28
- cartography/intel/semgrep/deployment.py +3 -1
- cartography/intel/semgrep/findings.py +42 -18
- cartography/intel/snipeit/__init__.py +17 -3
- cartography/intel/snipeit/asset.py +12 -6
- cartography/intel/snipeit/user.py +8 -5
- cartography/intel/snipeit/util.py +9 -4
- cartography/intel/tailscale/__init__.py +77 -0
- cartography/intel/tailscale/acls.py +146 -0
- cartography/intel/tailscale/devices.py +127 -0
- cartography/intel/tailscale/postureintegrations.py +81 -0
- cartography/intel/tailscale/tailnets.py +76 -0
- cartography/intel/tailscale/users.py +80 -0
- cartography/intel/tailscale/utils.py +132 -0
- cartography/models/aws/apigateway.py +21 -17
- cartography/models/aws/apigatewaycertificate.py +28 -22
- cartography/models/aws/apigatewayresource.py +28 -20
- cartography/models/aws/apigatewaystage.py +33 -25
- cartography/models/aws/cloudtrail/__init__.py +0 -0
- cartography/models/aws/cloudtrail/trail.py +61 -0
- cartography/models/aws/cloudwatch/__init__.py +0 -0
- cartography/models/aws/cloudwatch/loggroup.py +52 -0
- cartography/models/aws/dynamodb/gsi.py +30 -22
- cartography/models/aws/dynamodb/tables.py +25 -17
- cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
- cartography/models/aws/ec2/images.py +36 -34
- cartography/models/aws/ec2/instances.py +51 -45
- cartography/models/aws/ec2/keypair.py +21 -16
- cartography/models/aws/ec2/keypair_instance.py +28 -21
- cartography/models/aws/ec2/launch_configurations.py +30 -26
- cartography/models/aws/ec2/launch_template_versions.py +48 -38
- cartography/models/aws/ec2/launch_templates.py +21 -17
- cartography/models/aws/ec2/load_balancer_listeners.py +27 -23
- cartography/models/aws/ec2/load_balancers.py +47 -37
- cartography/models/aws/ec2/network_acl_rules.py +38 -30
- cartography/models/aws/ec2/network_acls.py +38 -29
- cartography/models/aws/ec2/networkinterface_instance.py +52 -39
- cartography/models/aws/ec2/networkinterfaces.py +53 -37
- cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
- cartography/models/aws/ec2/reservations.py +18 -14
- cartography/models/aws/ec2/route_table_associations.py +97 -0
- cartography/models/aws/ec2/route_tables.py +128 -0
- cartography/models/aws/ec2/routes.py +85 -0
- cartography/models/aws/ec2/securitygroup_instance.py +29 -20
- cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
- cartography/models/aws/ec2/subnet_instance.py +24 -19
- cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
- cartography/models/aws/ec2/volumes.py +47 -40
- cartography/models/aws/efs/__init__.py +0 -0
- cartography/models/aws/efs/mount_target.py +52 -0
- cartography/models/aws/eks/clusters.py +23 -21
- cartography/models/aws/emr.py +32 -30
- cartography/models/aws/iam/instanceprofile.py +33 -24
- cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
- cartography/models/aws/identitycenter/awspermissionset.py +37 -29
- cartography/models/aws/identitycenter/awsssouser.py +23 -21
- cartography/models/aws/inspector/findings.py +77 -65
- cartography/models/aws/inspector/packages.py +35 -29
- cartography/models/aws/s3/__init__.py +0 -0
- cartography/models/aws/s3/account_public_access_block.py +51 -0
- cartography/models/aws/sns/__init__.py +0 -0
- cartography/models/aws/sns/topic.py +50 -0
- cartography/models/aws/ssm/instance_information.py +51 -39
- cartography/models/aws/ssm/instance_patch.py +32 -26
- cartography/models/bigfix/bigfix_computer.py +42 -38
- cartography/models/bigfix/bigfix_root.py +3 -3
- cartography/models/cloudflare/__init__.py +0 -0
- cartography/models/cloudflare/account.py +25 -0
- cartography/models/cloudflare/dnsrecord.py +55 -0
- cartography/models/cloudflare/member.py +82 -0
- cartography/models/cloudflare/role.py +44 -0
- cartography/models/cloudflare/zone.py +59 -0
- cartography/models/core/common.py +12 -10
- cartography/models/core/nodes.py +5 -2
- cartography/models/core/relationships.py +14 -6
- cartography/models/crowdstrike/hosts.py +37 -35
- cartography/models/cve/cve.py +34 -32
- cartography/models/cve/cve_feed.py +6 -6
- cartography/models/digitalocean/__init__.py +0 -0
- cartography/models/digitalocean/account.py +21 -0
- cartography/models/digitalocean/droplet.py +56 -0
- cartography/models/digitalocean/project.py +48 -0
- cartography/models/duo/api_host.py +3 -3
- cartography/models/duo/endpoint.py +43 -41
- cartography/models/duo/group.py +14 -14
- cartography/models/duo/phone.py +27 -27
- cartography/models/duo/token.py +16 -16
- cartography/models/duo/user.py +46 -44
- cartography/models/duo/web_authn_credential.py +27 -19
- cartography/models/entra/ou.py +48 -0
- cartography/models/entra/tenant.py +24 -18
- cartography/models/entra/user.py +64 -48
- cartography/models/gcp/iam.py +23 -23
- cartography/models/github/orgs.py +5 -4
- cartography/models/github/teams.py +37 -31
- cartography/models/github/users.py +34 -23
- cartography/models/kandji/device.py +22 -16
- cartography/models/kandji/tenant.py +6 -4
- cartography/models/lastpass/tenant.py +3 -3
- cartography/models/lastpass/user.py +32 -28
- cartography/models/openai/__init__.py +0 -0
- cartography/models/openai/adminapikey.py +90 -0
- cartography/models/openai/apikey.py +84 -0
- cartography/models/openai/organization.py +17 -0
- cartography/models/openai/project.py +70 -0
- cartography/models/openai/serviceaccount.py +50 -0
- cartography/models/openai/user.py +49 -0
- cartography/models/semgrep/dependencies.py +36 -24
- cartography/models/semgrep/deployment.py +5 -5
- cartography/models/semgrep/findings.py +58 -42
- cartography/models/semgrep/locations.py +27 -21
- cartography/models/snipeit/asset.py +30 -21
- cartography/models/snipeit/tenant.py +6 -4
- cartography/models/snipeit/user.py +19 -12
- cartography/models/tailscale/__init__.py +0 -0
- cartography/models/tailscale/device.py +95 -0
- cartography/models/tailscale/group.py +86 -0
- cartography/models/tailscale/postureintegration.py +58 -0
- cartography/models/tailscale/tag.py +102 -0
- cartography/models/tailscale/tailnet.py +29 -0
- cartography/models/tailscale/user.py +52 -0
- cartography/stats.py +3 -3
- cartography/sync.py +113 -31
- cartography/util.py +84 -62
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/METADATA +8 -15
- cartography-0.103.0.dist-info/RECORD +442 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/WHEEL +1 -1
- cartography-0.102.0rc1.dist-info/RECORD +0 -377
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from cartography.client.core.tx import load
|
|
10
|
+
from cartography.graph.job import GraphJob
|
|
11
|
+
from cartography.models.tailscale.user import TailscaleUserSchema
|
|
12
|
+
from cartography.util import timeit
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
# Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
|
|
16
|
+
_TIMEOUT = (60, 60)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@timeit
|
|
20
|
+
def sync(
|
|
21
|
+
neo4j_session: neo4j.Session,
|
|
22
|
+
api_session: requests.Session,
|
|
23
|
+
common_job_parameters: Dict[str, Any],
|
|
24
|
+
org: str,
|
|
25
|
+
) -> List[Dict]:
|
|
26
|
+
users = get(
|
|
27
|
+
api_session,
|
|
28
|
+
common_job_parameters["BASE_URL"],
|
|
29
|
+
org,
|
|
30
|
+
)
|
|
31
|
+
load_users(
|
|
32
|
+
neo4j_session,
|
|
33
|
+
users,
|
|
34
|
+
org,
|
|
35
|
+
common_job_parameters["UPDATE_TAG"],
|
|
36
|
+
)
|
|
37
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
38
|
+
return users
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@timeit
|
|
42
|
+
def get(
|
|
43
|
+
api_session: requests.Session,
|
|
44
|
+
base_url: str,
|
|
45
|
+
org: str,
|
|
46
|
+
) -> List[Dict[str, Any]]:
|
|
47
|
+
results: List[Dict[str, Any]] = []
|
|
48
|
+
req = api_session.get(
|
|
49
|
+
f"{base_url}/tailnet/{org}/users",
|
|
50
|
+
timeout=_TIMEOUT,
|
|
51
|
+
)
|
|
52
|
+
req.raise_for_status()
|
|
53
|
+
results = req.json()["users"]
|
|
54
|
+
return results
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@timeit
|
|
58
|
+
def load_users(
|
|
59
|
+
neo4j_session: neo4j.Session,
|
|
60
|
+
data: List[Dict[str, Any]],
|
|
61
|
+
org: str,
|
|
62
|
+
update_tag: int,
|
|
63
|
+
) -> None:
|
|
64
|
+
logger.info(f"Loading {len(data)} Tailscale Users to the graph")
|
|
65
|
+
load(
|
|
66
|
+
neo4j_session,
|
|
67
|
+
TailscaleUserSchema(),
|
|
68
|
+
data,
|
|
69
|
+
lastupdated=update_tag,
|
|
70
|
+
org=org,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@timeit
|
|
75
|
+
def cleanup(
|
|
76
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
77
|
+
) -> None:
|
|
78
|
+
GraphJob.from_node_schema(TailscaleUserSchema(), common_job_parameters).run(
|
|
79
|
+
neo4j_session
|
|
80
|
+
)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import re
|
|
3
|
+
from typing import Any
|
|
4
|
+
from typing import Dict
|
|
5
|
+
from typing import List
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ACLParser:
|
|
9
|
+
"""ACLParser is a class that parses Tailscale ACLs to extract data.
|
|
10
|
+
|
|
11
|
+
It removes comments and trailing commas from the ACL string
|
|
12
|
+
and converts it to a JSON object. It then provides methods
|
|
13
|
+
to extract groups and tags from the ACL.
|
|
14
|
+
The ACL string is expected to be in a format similar to JSON,
|
|
15
|
+
but with some Tailscale-specific syntax. The parser handles
|
|
16
|
+
single-line comments (//) and multi-line comments (/* */)
|
|
17
|
+
and removes trailing commas from the JSON-like structure.
|
|
18
|
+
The parser also handles Tailscale-specific syntax for groups
|
|
19
|
+
and tags, which may include user and group identifiers.
|
|
20
|
+
The parser is initialized with a raw ACL string, which is
|
|
21
|
+
processed to remove comments and trailing commas.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
raw_acl (str): The raw ACL string to be parsed.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
data (dict): The parsed JSON object representing the ACL.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
RE_SINGLE_LINE_COMMENT = re.compile(r'("(?:(?=(\\?))\2.)*?")|(?:\/{2,}.*)')
|
|
31
|
+
RE_MULTI_LINE_COMMENT = re.compile(
|
|
32
|
+
r'("(?:(?=(\\?))\2.)*?")|(?:\/\*(?:(?!\*\/).)+\*\/)', flags=re.M | re.DOTALL
|
|
33
|
+
)
|
|
34
|
+
RE_TRAILING_COMMA = re.compile(r",(?=\s*?[\}\]])")
|
|
35
|
+
|
|
36
|
+
def __init__(self, raw_acl: str) -> None:
|
|
37
|
+
# Tailscale ACL use comments and trailing commas
|
|
38
|
+
# that are not valid JSON
|
|
39
|
+
filtered_json_string = self.RE_SINGLE_LINE_COMMENT.sub(r"\1", raw_acl)
|
|
40
|
+
filtered_json_string = self.RE_MULTI_LINE_COMMENT.sub(
|
|
41
|
+
r"\1", filtered_json_string
|
|
42
|
+
)
|
|
43
|
+
filtered_json_string = self.RE_TRAILING_COMMA.sub("", filtered_json_string)
|
|
44
|
+
self.data = json.loads(filtered_json_string)
|
|
45
|
+
|
|
46
|
+
def get_groups(self) -> List[Dict[str, Any]]:
|
|
47
|
+
"""
|
|
48
|
+
Get all groups from the ACL
|
|
49
|
+
|
|
50
|
+
:return: list of groups
|
|
51
|
+
"""
|
|
52
|
+
result: List[Dict[str, Any]] = []
|
|
53
|
+
groups = self.data.get("groups", {})
|
|
54
|
+
for group_id, members in groups.items():
|
|
55
|
+
group_name = group_id.split(":")[-1]
|
|
56
|
+
users_members = []
|
|
57
|
+
sub_groups = []
|
|
58
|
+
domain_members = []
|
|
59
|
+
for member in members:
|
|
60
|
+
if member.startswith("group:") or member.startswith("autogroup:"):
|
|
61
|
+
sub_groups.append(member)
|
|
62
|
+
elif member.startswith("user:*@"):
|
|
63
|
+
domain_members.append(member[7:])
|
|
64
|
+
elif member.startswith("user:"):
|
|
65
|
+
users_members.append(member[5:])
|
|
66
|
+
else:
|
|
67
|
+
users_members.append(member)
|
|
68
|
+
result.append(
|
|
69
|
+
{
|
|
70
|
+
"id": group_id,
|
|
71
|
+
"name": group_name,
|
|
72
|
+
"members": users_members,
|
|
73
|
+
"sub_groups": sub_groups,
|
|
74
|
+
"domain_members": domain_members,
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
return result
|
|
78
|
+
|
|
79
|
+
def get_tags(self) -> List[Dict[str, Any]]:
|
|
80
|
+
"""
|
|
81
|
+
Get all tags from the ACL
|
|
82
|
+
|
|
83
|
+
:return: list of tags
|
|
84
|
+
"""
|
|
85
|
+
result: List[Dict[str, Any]] = []
|
|
86
|
+
for tag, owners in self.data.get("tagOwners", {}).items():
|
|
87
|
+
tag_name = tag.split(":")[-1]
|
|
88
|
+
user_owners = []
|
|
89
|
+
group_owners = []
|
|
90
|
+
domain_owners = []
|
|
91
|
+
for owner in owners:
|
|
92
|
+
if owner.startswith("group:") or owner.startswith("autogroup:"):
|
|
93
|
+
group_owners.append(owner)
|
|
94
|
+
elif owner.startswith("user:*@"):
|
|
95
|
+
domain_owners.append(owner[7:])
|
|
96
|
+
elif owner.startswith("user:"):
|
|
97
|
+
user_owners.append(owner[5:])
|
|
98
|
+
else:
|
|
99
|
+
user_owners.append(owner)
|
|
100
|
+
result.append(
|
|
101
|
+
{
|
|
102
|
+
"id": tag,
|
|
103
|
+
"name": tag_name,
|
|
104
|
+
"owners": user_owners,
|
|
105
|
+
"group_owners": group_owners,
|
|
106
|
+
"domain_owners": domain_owners,
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
return result
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def role_to_group(role: str) -> list[str]:
|
|
113
|
+
"""Convert Tailscale role to group
|
|
114
|
+
|
|
115
|
+
This function is used to convert Tailscale role to autogroup
|
|
116
|
+
group. The autogroup is used to manage the access control
|
|
117
|
+
in Tailscale.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
role (str): The role of the user in Tailscale. (eg: owner, admin, member, etc)
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
list[str]: The list of autogroup that the user belongs to. (eg: autogroup:admin, autogroup:member, etc)
|
|
124
|
+
"""
|
|
125
|
+
result: list[str] = []
|
|
126
|
+
result.append(f"autogroup:{role}")
|
|
127
|
+
if role == "owner":
|
|
128
|
+
result.append("autogroup:admin")
|
|
129
|
+
result.append("autogroup:member")
|
|
130
|
+
elif role in ("admin", "auditor", "billing-admin", "it-admin", "network-admin"):
|
|
131
|
+
result.append("autogroup:member")
|
|
132
|
+
return result
|
|
@@ -12,36 +12,40 @@ from cartography.models.core.relationships import TargetNodeMatcher
|
|
|
12
12
|
|
|
13
13
|
@dataclass(frozen=True)
|
|
14
14
|
class APIGatewayRestAPINodeProperties(CartographyNodeProperties):
|
|
15
|
-
id: PropertyRef = PropertyRef(
|
|
16
|
-
createddate: PropertyRef = PropertyRef(
|
|
17
|
-
version: PropertyRef = PropertyRef(
|
|
18
|
-
minimumcompressionsize: PropertyRef = PropertyRef(
|
|
19
|
-
disableexecuteapiendpoint: PropertyRef = PropertyRef(
|
|
20
|
-
region: PropertyRef = PropertyRef(
|
|
21
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
22
|
-
anonymous_access: PropertyRef = PropertyRef(
|
|
23
|
-
anonymous_actions: PropertyRef = PropertyRef(
|
|
15
|
+
id: PropertyRef = PropertyRef("id", extra_index=True)
|
|
16
|
+
createddate: PropertyRef = PropertyRef("createdDate")
|
|
17
|
+
version: PropertyRef = PropertyRef("version")
|
|
18
|
+
minimumcompressionsize: PropertyRef = PropertyRef("minimumCompressionSize")
|
|
19
|
+
disableexecuteapiendpoint: PropertyRef = PropertyRef("disableExecuteApiEndpoint")
|
|
20
|
+
region: PropertyRef = PropertyRef("region", set_in_kwargs=True)
|
|
21
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
22
|
+
anonymous_access: PropertyRef = PropertyRef("anonymous_access")
|
|
23
|
+
anonymous_actions: PropertyRef = PropertyRef("anonymous_actions")
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
@dataclass(frozen=True)
|
|
27
|
-
class
|
|
28
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
27
|
+
class APIGatewayRestAPIToAWSAccountRelRelProperties(CartographyRelProperties):
|
|
28
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
@dataclass(frozen=True)
|
|
32
32
|
# (:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount)
|
|
33
|
-
class
|
|
34
|
-
target_node_label: str =
|
|
33
|
+
class APIGatewayRestAPIToAWSAccountRel(CartographyRelSchema):
|
|
34
|
+
target_node_label: str = "AWSAccount"
|
|
35
35
|
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
36
|
-
{
|
|
36
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
37
37
|
)
|
|
38
38
|
direction: LinkDirection = LinkDirection.INWARD
|
|
39
39
|
rel_label: str = "RESOURCE"
|
|
40
|
-
properties:
|
|
40
|
+
properties: APIGatewayRestAPIToAWSAccountRelRelProperties = (
|
|
41
|
+
APIGatewayRestAPIToAWSAccountRelRelProperties()
|
|
42
|
+
)
|
|
41
43
|
|
|
42
44
|
|
|
43
45
|
@dataclass(frozen=True)
|
|
44
46
|
class APIGatewayRestAPISchema(CartographyNodeSchema):
|
|
45
|
-
label: str =
|
|
47
|
+
label: str = "APIGatewayRestAPI"
|
|
46
48
|
properties: APIGatewayRestAPINodeProperties = APIGatewayRestAPINodeProperties()
|
|
47
|
-
sub_resource_relationship:
|
|
49
|
+
sub_resource_relationship: APIGatewayRestAPIToAWSAccountRel = (
|
|
50
|
+
APIGatewayRestAPIToAWSAccountRel()
|
|
51
|
+
)
|
|
@@ -13,54 +13,60 @@ from cartography.models.core.relationships import TargetNodeMatcher
|
|
|
13
13
|
|
|
14
14
|
@dataclass(frozen=True)
|
|
15
15
|
class APIGatewayClientCertificateNodeProperties(CartographyNodeProperties):
|
|
16
|
-
id: PropertyRef = PropertyRef(
|
|
17
|
-
createddate: PropertyRef = PropertyRef(
|
|
18
|
-
expirationdate: PropertyRef = PropertyRef(
|
|
19
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
16
|
+
id: PropertyRef = PropertyRef("clientCertificateId")
|
|
17
|
+
createddate: PropertyRef = PropertyRef("createdDate")
|
|
18
|
+
expirationdate: PropertyRef = PropertyRef("expirationDate")
|
|
19
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@dataclass(frozen=True)
|
|
23
|
-
class
|
|
24
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
23
|
+
class APIGatewayClientCertificateToStageRelRelProperties(CartographyRelProperties):
|
|
24
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
@dataclass(frozen=True)
|
|
28
|
-
class
|
|
29
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
28
|
+
class CertToStageRelProperties(CartographyRelProperties):
|
|
29
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
@dataclass(frozen=True)
|
|
33
33
|
# (:APIGatewayStage)-[:HAS_CERTIFICATE]->(:APIGatewayClientCertificate)
|
|
34
|
-
class
|
|
35
|
-
target_node_label: str =
|
|
34
|
+
class APIGatewayClientCertificateToStageRel(CartographyRelSchema):
|
|
35
|
+
target_node_label: str = "APIGatewayStage"
|
|
36
36
|
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
37
|
-
{
|
|
37
|
+
{"id": PropertyRef("stageArn")},
|
|
38
38
|
)
|
|
39
39
|
direction: LinkDirection = LinkDirection.INWARD
|
|
40
40
|
rel_label: str = "HAS_CERTIFICATE"
|
|
41
|
-
properties:
|
|
41
|
+
properties: CertToStageRelProperties = CertToStageRelProperties()
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
@dataclass(frozen=True)
|
|
45
|
-
class
|
|
46
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
45
|
+
class CertToAccountRelProperties(CartographyRelProperties):
|
|
46
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
@dataclass(frozen=True)
|
|
50
50
|
# (:APIGatewayClientCertificate)<-[:RESOURCE]-(:AWSAccount)
|
|
51
|
-
class
|
|
52
|
-
target_node_label: str =
|
|
51
|
+
class APIGatewayClientCertificateToAWSAccountRel(CartographyRelSchema):
|
|
52
|
+
target_node_label: str = "AWSAccount"
|
|
53
53
|
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
54
|
-
{
|
|
54
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
55
55
|
)
|
|
56
56
|
direction: LinkDirection = LinkDirection.INWARD
|
|
57
57
|
rel_label: str = "RESOURCE"
|
|
58
|
-
properties:
|
|
58
|
+
properties: CertToAccountRelProperties = CertToAccountRelProperties()
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
@dataclass(frozen=True)
|
|
62
62
|
class APIGatewayClientCertificateSchema(CartographyNodeSchema):
|
|
63
|
-
label: str =
|
|
64
|
-
properties: APIGatewayClientCertificateNodeProperties =
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
label: str = "APIGatewayClientCertificate"
|
|
64
|
+
properties: APIGatewayClientCertificateNodeProperties = (
|
|
65
|
+
APIGatewayClientCertificateNodeProperties()
|
|
66
|
+
)
|
|
67
|
+
sub_resource_relationship: APIGatewayClientCertificateToAWSAccountRel = (
|
|
68
|
+
APIGatewayClientCertificateToAWSAccountRel()
|
|
69
|
+
)
|
|
70
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
71
|
+
[APIGatewayClientCertificateToStageRel()],
|
|
72
|
+
)
|
|
@@ -13,50 +13,58 @@ from cartography.models.core.relationships import TargetNodeMatcher
|
|
|
13
13
|
|
|
14
14
|
@dataclass(frozen=True)
|
|
15
15
|
class APIGatewayResourceNodeProperties(CartographyNodeProperties):
|
|
16
|
-
id: PropertyRef = PropertyRef(
|
|
17
|
-
path: PropertyRef = PropertyRef(
|
|
18
|
-
pathpart: PropertyRef = PropertyRef(
|
|
19
|
-
parentid: PropertyRef = PropertyRef(
|
|
20
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
16
|
+
id: PropertyRef = PropertyRef("id")
|
|
17
|
+
path: PropertyRef = PropertyRef("path")
|
|
18
|
+
pathpart: PropertyRef = PropertyRef("pathPart")
|
|
19
|
+
parentid: PropertyRef = PropertyRef("parentId")
|
|
20
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
@dataclass(frozen=True)
|
|
24
|
-
class
|
|
25
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
24
|
+
class APIGatewayResourceToRestAPIRelRelProperties(CartographyRelProperties):
|
|
25
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
@dataclass(frozen=True)
|
|
29
29
|
# (:APIGatewayResource)<-[:RESOURCE]-(:APIGatewayRestAPI)
|
|
30
|
-
class
|
|
31
|
-
target_node_label: str =
|
|
30
|
+
class APIGatewayResourceToRestAPIRel(CartographyRelSchema):
|
|
31
|
+
target_node_label: str = "APIGatewayRestAPI"
|
|
32
32
|
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
33
|
-
{
|
|
33
|
+
{"id": PropertyRef("apiId")},
|
|
34
34
|
)
|
|
35
35
|
direction: LinkDirection = LinkDirection.INWARD
|
|
36
36
|
rel_label: str = "RESOURCE"
|
|
37
|
-
properties:
|
|
37
|
+
properties: APIGatewayResourceToRestAPIRelRelProperties = (
|
|
38
|
+
APIGatewayResourceToRestAPIRelRelProperties()
|
|
39
|
+
)
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
@dataclass(frozen=True)
|
|
41
|
-
class
|
|
42
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
43
|
+
class APIGatewayResourceToAWSAccountRelRelProperties(CartographyRelProperties):
|
|
44
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
43
45
|
|
|
44
46
|
|
|
45
47
|
@dataclass(frozen=True)
|
|
46
48
|
# (:APIGatewayResource)<-[:RESOURCE]-(:AWSAccount)
|
|
47
|
-
class
|
|
48
|
-
target_node_label: str =
|
|
49
|
+
class APIGatewayResourceToAWSAccountRel(CartographyRelSchema):
|
|
50
|
+
target_node_label: str = "AWSAccount"
|
|
49
51
|
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
50
|
-
{
|
|
52
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
51
53
|
)
|
|
52
54
|
direction: LinkDirection = LinkDirection.INWARD
|
|
53
55
|
rel_label: str = "RESOURCE"
|
|
54
|
-
properties:
|
|
56
|
+
properties: APIGatewayResourceToAWSAccountRelRelProperties = (
|
|
57
|
+
APIGatewayResourceToAWSAccountRelRelProperties()
|
|
58
|
+
)
|
|
55
59
|
|
|
56
60
|
|
|
57
61
|
@dataclass(frozen=True)
|
|
58
62
|
class APIGatewayResourceSchema(CartographyNodeSchema):
|
|
59
|
-
label: str =
|
|
63
|
+
label: str = "APIGatewayResource"
|
|
60
64
|
properties: APIGatewayResourceNodeProperties = APIGatewayResourceNodeProperties()
|
|
61
|
-
sub_resource_relationship:
|
|
62
|
-
|
|
65
|
+
sub_resource_relationship: APIGatewayResourceToAWSAccountRel = (
|
|
66
|
+
APIGatewayResourceToAWSAccountRel()
|
|
67
|
+
)
|
|
68
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
69
|
+
[APIGatewayResourceToRestAPIRel()],
|
|
70
|
+
)
|
|
@@ -13,55 +13,63 @@ from cartography.models.core.relationships import TargetNodeMatcher
|
|
|
13
13
|
|
|
14
14
|
@dataclass(frozen=True)
|
|
15
15
|
class APIGatewayStageNodeProperties(CartographyNodeProperties):
|
|
16
|
-
id: PropertyRef = PropertyRef(
|
|
17
|
-
stagename: PropertyRef = PropertyRef(
|
|
18
|
-
createddate: PropertyRef = PropertyRef(
|
|
19
|
-
deploymentid: PropertyRef = PropertyRef(
|
|
20
|
-
clientcertificateid: PropertyRef = PropertyRef(
|
|
21
|
-
cacheclusterenabled: PropertyRef = PropertyRef(
|
|
22
|
-
cacheclusterstatus: PropertyRef = PropertyRef(
|
|
23
|
-
tracingenabled: PropertyRef = PropertyRef(
|
|
24
|
-
webaclarn: PropertyRef = PropertyRef(
|
|
25
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
16
|
+
id: PropertyRef = PropertyRef("arn")
|
|
17
|
+
stagename: PropertyRef = PropertyRef("stageName")
|
|
18
|
+
createddate: PropertyRef = PropertyRef("createdDate")
|
|
19
|
+
deploymentid: PropertyRef = PropertyRef("deploymentId")
|
|
20
|
+
clientcertificateid: PropertyRef = PropertyRef("clientCertificateId")
|
|
21
|
+
cacheclusterenabled: PropertyRef = PropertyRef("cacheClusterEnabled")
|
|
22
|
+
cacheclusterstatus: PropertyRef = PropertyRef("cacheClusterStatus")
|
|
23
|
+
tracingenabled: PropertyRef = PropertyRef("tracingEnabled")
|
|
24
|
+
webaclarn: PropertyRef = PropertyRef("webAclArn")
|
|
25
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
@dataclass(frozen=True)
|
|
29
|
-
class
|
|
30
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
29
|
+
class APIGatewayStageToRestAPIRelRelProperties(CartographyRelProperties):
|
|
30
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
@dataclass(frozen=True)
|
|
34
34
|
# (:APIGatewayStage)<-[:ASSOCIATED_WITH]-(:APIGatewayRestAPI)
|
|
35
|
-
class
|
|
36
|
-
target_node_label: str =
|
|
35
|
+
class APIGatewayStageToRestAPIRel(CartographyRelSchema):
|
|
36
|
+
target_node_label: str = "APIGatewayRestAPI"
|
|
37
37
|
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
38
|
-
{
|
|
38
|
+
{"id": PropertyRef("apiId")},
|
|
39
39
|
)
|
|
40
40
|
direction: LinkDirection = LinkDirection.INWARD
|
|
41
41
|
rel_label: str = "ASSOCIATED_WITH"
|
|
42
|
-
properties:
|
|
42
|
+
properties: APIGatewayStageToRestAPIRelRelProperties = (
|
|
43
|
+
APIGatewayStageToRestAPIRelRelProperties()
|
|
44
|
+
)
|
|
43
45
|
|
|
44
46
|
|
|
45
47
|
@dataclass(frozen=True)
|
|
46
|
-
class
|
|
47
|
-
lastupdated: PropertyRef = PropertyRef(
|
|
48
|
+
class APIGatewayStageToAWSAccountRelRelProperties(CartographyRelProperties):
|
|
49
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
48
50
|
|
|
49
51
|
|
|
50
52
|
@dataclass(frozen=True)
|
|
51
53
|
# (:APIGatewayStage)<-[:RESOURCE]-(:AWSAccount)
|
|
52
|
-
class
|
|
53
|
-
target_node_label: str =
|
|
54
|
+
class APIGatewayStageToAWSAccountRel(CartographyRelSchema):
|
|
55
|
+
target_node_label: str = "AWSAccount"
|
|
54
56
|
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
55
|
-
{
|
|
57
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
56
58
|
)
|
|
57
59
|
direction: LinkDirection = LinkDirection.INWARD
|
|
58
60
|
rel_label: str = "RESOURCE"
|
|
59
|
-
properties:
|
|
61
|
+
properties: APIGatewayStageToAWSAccountRelRelProperties = (
|
|
62
|
+
APIGatewayStageToAWSAccountRelRelProperties()
|
|
63
|
+
)
|
|
60
64
|
|
|
61
65
|
|
|
62
66
|
@dataclass(frozen=True)
|
|
63
67
|
class APIGatewayStageSchema(CartographyNodeSchema):
|
|
64
|
-
label: str =
|
|
68
|
+
label: str = "APIGatewayStage"
|
|
65
69
|
properties: APIGatewayStageNodeProperties = APIGatewayStageNodeProperties()
|
|
66
|
-
sub_resource_relationship:
|
|
67
|
-
|
|
70
|
+
sub_resource_relationship: APIGatewayStageToAWSAccountRel = (
|
|
71
|
+
APIGatewayStageToAWSAccountRel()
|
|
72
|
+
)
|
|
73
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
74
|
+
[APIGatewayStageToRestAPIRel()],
|
|
75
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,61 @@
|
|
|
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 CloudTrailTrailNodeProperties(CartographyNodeProperties):
|
|
15
|
+
id: PropertyRef = PropertyRef("TrailARN")
|
|
16
|
+
arn: PropertyRef = PropertyRef("TrailARN")
|
|
17
|
+
name: PropertyRef = PropertyRef("Name")
|
|
18
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
19
|
+
cloudwatch_logs_log_group_arn: PropertyRef = PropertyRef(
|
|
20
|
+
"CloudWatchLogsLogGroupArn"
|
|
21
|
+
)
|
|
22
|
+
cloudwatch_logs_role_arn: PropertyRef = PropertyRef("CloudWatchLogsRoleArn")
|
|
23
|
+
has_custom_event_selectors: PropertyRef = PropertyRef("HasCustomEventSelectors")
|
|
24
|
+
has_insight_selectors: PropertyRef = PropertyRef("HasInsightSelectors")
|
|
25
|
+
home_region: PropertyRef = PropertyRef("HomeRegion")
|
|
26
|
+
include_global_service_events: PropertyRef = PropertyRef(
|
|
27
|
+
"IncludeGlobalServiceEvents"
|
|
28
|
+
)
|
|
29
|
+
is_multi_region_trail: PropertyRef = PropertyRef("IsMultiRegionTrail")
|
|
30
|
+
is_organization_trail: PropertyRef = PropertyRef("IsOrganizationTrail")
|
|
31
|
+
kms_key_id: PropertyRef = PropertyRef("KmsKeyId")
|
|
32
|
+
log_file_validation_enabled: PropertyRef = PropertyRef("LogFileValidationEnabled")
|
|
33
|
+
s3_bucket_name: PropertyRef = PropertyRef("S3BucketName")
|
|
34
|
+
s3_key_prefix: PropertyRef = PropertyRef("S3KeyPrefix")
|
|
35
|
+
sns_topic_arn: PropertyRef = PropertyRef("SnsTopicARN")
|
|
36
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True)
|
|
40
|
+
class CloudTrailTrailToAwsAccountRelProperties(CartographyRelProperties):
|
|
41
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class CloudTrailToAWSAccountRel(CartographyRelSchema):
|
|
46
|
+
target_node_label: str = "AWSAccount"
|
|
47
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
48
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
49
|
+
)
|
|
50
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
51
|
+
rel_label: str = "RESOURCE"
|
|
52
|
+
properties: CloudTrailTrailToAwsAccountRelProperties = (
|
|
53
|
+
CloudTrailTrailToAwsAccountRelProperties()
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass(frozen=True)
|
|
58
|
+
class CloudTrailTrailSchema(CartographyNodeSchema):
|
|
59
|
+
label: str = "CloudTrailTrail"
|
|
60
|
+
properties: CloudTrailTrailNodeProperties = CloudTrailTrailNodeProperties()
|
|
61
|
+
sub_resource_relationship: CloudTrailToAWSAccountRel = CloudTrailToAWSAccountRel()
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
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 CloudWatchLogGroupNodeProperties(CartographyNodeProperties):
|
|
15
|
+
id: PropertyRef = PropertyRef("logGroupArn")
|
|
16
|
+
arn: PropertyRef = PropertyRef("logGroupArn", extra_index=True)
|
|
17
|
+
creation_time: PropertyRef = PropertyRef("creationTime")
|
|
18
|
+
data_protection_status: PropertyRef = PropertyRef("dataProtectionStatus")
|
|
19
|
+
inherited_properties: PropertyRef = PropertyRef("inheritedProperties")
|
|
20
|
+
kms_key_id: PropertyRef = PropertyRef("kmsKeyId")
|
|
21
|
+
log_group_arn: PropertyRef = PropertyRef("logGroupArn")
|
|
22
|
+
log_group_class: PropertyRef = PropertyRef("logGroupClass")
|
|
23
|
+
log_group_name: PropertyRef = PropertyRef("logGroupName")
|
|
24
|
+
metric_filter_count: PropertyRef = PropertyRef("metricFilterCount")
|
|
25
|
+
retention_in_days: PropertyRef = PropertyRef("retentionInDays")
|
|
26
|
+
stored_bytes: PropertyRef = PropertyRef("storedBytes")
|
|
27
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True)
|
|
31
|
+
class CloudWatchLogGroupToAwsAccountRelProperties(CartographyRelProperties):
|
|
32
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class CloudWatchToAWSAccountRel(CartographyRelSchema):
|
|
37
|
+
target_node_label: str = "AWSAccount"
|
|
38
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
39
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
40
|
+
)
|
|
41
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
42
|
+
rel_label: str = "RESOURCE"
|
|
43
|
+
properties: CloudWatchLogGroupToAwsAccountRelProperties = (
|
|
44
|
+
CloudWatchLogGroupToAwsAccountRelProperties()
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class CloudWatchLogGroupSchema(CartographyNodeSchema):
|
|
50
|
+
label: str = "CloudWatchLogGroup"
|
|
51
|
+
properties: CloudWatchLogGroupNodeProperties = CloudWatchLogGroupNodeProperties()
|
|
52
|
+
sub_resource_relationship: CloudWatchToAWSAccountRel = CloudWatchToAWSAccountRel()
|