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
|
@@ -14,30 +14,52 @@ logger = logging.getLogger(__name__)
|
|
|
14
14
|
|
|
15
15
|
@timeit
|
|
16
16
|
@aws_handle_regions
|
|
17
|
-
def get_redshift_cluster_data(
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
def get_redshift_cluster_data(
|
|
18
|
+
boto3_session: boto3.session.Session,
|
|
19
|
+
region: str,
|
|
20
|
+
) -> List[Dict]:
|
|
21
|
+
client = boto3_session.client("redshift", region_name=region)
|
|
22
|
+
paginator = client.get_paginator("describe_clusters")
|
|
20
23
|
clusters: List[Dict] = []
|
|
21
24
|
for page in paginator.paginate():
|
|
22
|
-
clusters.extend(page[
|
|
25
|
+
clusters.extend(page["Clusters"])
|
|
23
26
|
return clusters
|
|
24
27
|
|
|
25
28
|
|
|
26
|
-
def _make_redshift_cluster_arn(
|
|
29
|
+
def _make_redshift_cluster_arn(
|
|
30
|
+
region: str,
|
|
31
|
+
aws_account_id: str,
|
|
32
|
+
cluster_identifier: str,
|
|
33
|
+
) -> str:
|
|
27
34
|
"""Cluster ARN format: https://docs.aws.amazon.com/redshift/latest/mgmt/redshift-iam-access-control-overview.html"""
|
|
28
|
-
return f
|
|
35
|
+
return f"arn:aws:redshift:{region}:{aws_account_id}:cluster:{cluster_identifier}"
|
|
29
36
|
|
|
30
37
|
|
|
31
|
-
def transform_redshift_cluster_data(
|
|
38
|
+
def transform_redshift_cluster_data(
|
|
39
|
+
clusters: List[Dict],
|
|
40
|
+
region: str,
|
|
41
|
+
current_aws_account_id: str,
|
|
42
|
+
) -> None:
|
|
32
43
|
for cluster in clusters:
|
|
33
|
-
cluster[
|
|
34
|
-
|
|
44
|
+
cluster["arn"] = _make_redshift_cluster_arn(
|
|
45
|
+
region,
|
|
46
|
+
current_aws_account_id,
|
|
47
|
+
cluster["ClusterIdentifier"],
|
|
48
|
+
)
|
|
49
|
+
cluster["ClusterCreateTime"] = (
|
|
50
|
+
str(cluster["ClusterCreateTime"])
|
|
51
|
+
if "ClusterCreateTime" in cluster
|
|
52
|
+
else None
|
|
53
|
+
)
|
|
35
54
|
|
|
36
55
|
|
|
37
56
|
@timeit
|
|
38
57
|
def load_redshift_cluster_data(
|
|
39
|
-
neo4j_session: neo4j.Session,
|
|
40
|
-
|
|
58
|
+
neo4j_session: neo4j.Session,
|
|
59
|
+
clusters: List[Dict],
|
|
60
|
+
region: str,
|
|
61
|
+
current_aws_account_id: str,
|
|
62
|
+
aws_update_tag: int,
|
|
41
63
|
) -> None:
|
|
42
64
|
ingest_cluster = """
|
|
43
65
|
MERGE (cluster:RedshiftCluster{id: $Arn})
|
|
@@ -68,21 +90,21 @@ def load_redshift_cluster_data(
|
|
|
68
90
|
for cluster in clusters:
|
|
69
91
|
neo4j_session.run(
|
|
70
92
|
ingest_cluster,
|
|
71
|
-
Arn=cluster[
|
|
72
|
-
AZ=cluster[
|
|
73
|
-
ClusterCreateTime=cluster[
|
|
74
|
-
ClusterIdentifier=cluster[
|
|
75
|
-
ClusterRevisionNumber=cluster[
|
|
76
|
-
ClusterStatus=cluster[
|
|
77
|
-
DBName=cluster[
|
|
78
|
-
Encrypted=cluster[
|
|
79
|
-
EndpointAddress=cluster.get(
|
|
80
|
-
EndpointPort=cluster.get(
|
|
81
|
-
MasterUsername=cluster[
|
|
82
|
-
NodeType=cluster[
|
|
83
|
-
NumberOfNodes=cluster[
|
|
84
|
-
PubliclyAccessible=cluster[
|
|
85
|
-
VpcId=cluster.get(
|
|
93
|
+
Arn=cluster["arn"],
|
|
94
|
+
AZ=cluster["AvailabilityZone"],
|
|
95
|
+
ClusterCreateTime=cluster["ClusterCreateTime"],
|
|
96
|
+
ClusterIdentifier=cluster["ClusterIdentifier"],
|
|
97
|
+
ClusterRevisionNumber=cluster["ClusterRevisionNumber"],
|
|
98
|
+
ClusterStatus=cluster["ClusterStatus"],
|
|
99
|
+
DBName=cluster["DBName"],
|
|
100
|
+
Encrypted=cluster["Encrypted"],
|
|
101
|
+
EndpointAddress=cluster.get("Endpoint").get("Address"), # type: ignore
|
|
102
|
+
EndpointPort=cluster.get("Endpoint").get("Port"), # type: ignore
|
|
103
|
+
MasterUsername=cluster["MasterUsername"],
|
|
104
|
+
NodeType=cluster["NodeType"],
|
|
105
|
+
NumberOfNodes=cluster["NumberOfNodes"],
|
|
106
|
+
PubliclyAccessible=cluster["PubliclyAccessible"],
|
|
107
|
+
VpcId=cluster.get("VpcId"),
|
|
86
108
|
Region=region,
|
|
87
109
|
AWS_ACCOUNT_ID=current_aws_account_id,
|
|
88
110
|
aws_update_tag=aws_update_tag,
|
|
@@ -93,7 +115,11 @@ def load_redshift_cluster_data(
|
|
|
93
115
|
|
|
94
116
|
|
|
95
117
|
@timeit
|
|
96
|
-
def _attach_ec2_security_groups(
|
|
118
|
+
def _attach_ec2_security_groups(
|
|
119
|
+
neo4j_session: neo4j.Session,
|
|
120
|
+
cluster: Dict,
|
|
121
|
+
aws_update_tag: int,
|
|
122
|
+
) -> None:
|
|
97
123
|
attach_cluster_to_group = """
|
|
98
124
|
MATCH (c:RedshiftCluster{id:$ClusterArn})
|
|
99
125
|
MERGE (sg:EC2SecurityGroup{id:$GroupId})
|
|
@@ -101,17 +127,21 @@ def _attach_ec2_security_groups(neo4j_session: neo4j.Session, cluster: Dict, aws
|
|
|
101
127
|
ON CREATE SET m.firstseen = timestamp()
|
|
102
128
|
SET m.lastupdated = $aws_update_tag
|
|
103
129
|
"""
|
|
104
|
-
for group in cluster.get(
|
|
130
|
+
for group in cluster.get("VpcSecurityGroups", []):
|
|
105
131
|
neo4j_session.run(
|
|
106
132
|
attach_cluster_to_group,
|
|
107
|
-
ClusterArn=cluster[
|
|
108
|
-
GroupId=group[
|
|
133
|
+
ClusterArn=cluster["arn"],
|
|
134
|
+
GroupId=group["VpcSecurityGroupId"],
|
|
109
135
|
aws_update_tag=aws_update_tag,
|
|
110
136
|
)
|
|
111
137
|
|
|
112
138
|
|
|
113
139
|
@timeit
|
|
114
|
-
def _attach_iam_roles(
|
|
140
|
+
def _attach_iam_roles(
|
|
141
|
+
neo4j_session: neo4j.Session,
|
|
142
|
+
cluster: Dict,
|
|
143
|
+
aws_update_tag: int,
|
|
144
|
+
) -> None:
|
|
115
145
|
attach_cluster_to_role = """
|
|
116
146
|
MATCH (c:RedshiftCluster{id:$ClusterArn})
|
|
117
147
|
MERGE (p:AWSPrincipal{arn:$RoleArn})
|
|
@@ -119,17 +149,21 @@ def _attach_iam_roles(neo4j_session: neo4j.Session, cluster: Dict, aws_update_ta
|
|
|
119
149
|
ON CREATE SET s.firstseen = timestamp()
|
|
120
150
|
SET s.lastupdated = $aws_update_tag
|
|
121
151
|
"""
|
|
122
|
-
for role in cluster.get(
|
|
152
|
+
for role in cluster.get("IamRoles", []):
|
|
123
153
|
neo4j_session.run(
|
|
124
154
|
attach_cluster_to_role,
|
|
125
|
-
ClusterArn=cluster[
|
|
126
|
-
RoleArn=role[
|
|
155
|
+
ClusterArn=cluster["arn"],
|
|
156
|
+
RoleArn=role["IamRoleArn"],
|
|
127
157
|
aws_update_tag=aws_update_tag,
|
|
128
158
|
)
|
|
129
159
|
|
|
130
160
|
|
|
131
161
|
@timeit
|
|
132
|
-
def _attach_aws_vpc(
|
|
162
|
+
def _attach_aws_vpc(
|
|
163
|
+
neo4j_session: neo4j.Session,
|
|
164
|
+
cluster: Dict,
|
|
165
|
+
aws_update_tag: int,
|
|
166
|
+
) -> None:
|
|
133
167
|
attach_cluster_to_vpc = """
|
|
134
168
|
MATCH (c:RedshiftCluster{id:$ClusterArn})
|
|
135
169
|
MERGE (v:AWSVpc{id:$VpcId})
|
|
@@ -137,36 +171,63 @@ def _attach_aws_vpc(neo4j_session: neo4j.Session, cluster: Dict, aws_update_tag:
|
|
|
137
171
|
ON CREATE SET m.firstseen = timestamp()
|
|
138
172
|
SET m.lastupdated = $aws_update_tag
|
|
139
173
|
"""
|
|
140
|
-
if cluster.get(
|
|
174
|
+
if cluster.get("VpcId"):
|
|
141
175
|
neo4j_session.run(
|
|
142
176
|
attach_cluster_to_vpc,
|
|
143
|
-
ClusterArn=cluster[
|
|
144
|
-
VpcId=cluster[
|
|
177
|
+
ClusterArn=cluster["arn"],
|
|
178
|
+
VpcId=cluster["VpcId"],
|
|
145
179
|
aws_update_tag=aws_update_tag,
|
|
146
180
|
)
|
|
147
181
|
|
|
148
182
|
|
|
149
183
|
@timeit
|
|
150
184
|
def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
151
|
-
run_cleanup_job(
|
|
185
|
+
run_cleanup_job(
|
|
186
|
+
"aws_import_redshift_clusters_cleanup.json",
|
|
187
|
+
neo4j_session,
|
|
188
|
+
common_job_parameters,
|
|
189
|
+
)
|
|
152
190
|
|
|
153
191
|
|
|
154
192
|
@timeit
|
|
155
193
|
def sync_redshift_clusters(
|
|
156
|
-
neo4j_session: neo4j.Session,
|
|
157
|
-
|
|
194
|
+
neo4j_session: neo4j.Session,
|
|
195
|
+
boto3_session: boto3.session.Session,
|
|
196
|
+
region: str,
|
|
197
|
+
current_aws_account_id: str,
|
|
198
|
+
aws_update_tag: int,
|
|
158
199
|
) -> None:
|
|
159
200
|
data = get_redshift_cluster_data(boto3_session, region)
|
|
160
201
|
transform_redshift_cluster_data(data, region, current_aws_account_id)
|
|
161
|
-
load_redshift_cluster_data(
|
|
202
|
+
load_redshift_cluster_data(
|
|
203
|
+
neo4j_session,
|
|
204
|
+
data,
|
|
205
|
+
region,
|
|
206
|
+
current_aws_account_id,
|
|
207
|
+
aws_update_tag,
|
|
208
|
+
)
|
|
162
209
|
|
|
163
210
|
|
|
164
211
|
@timeit
|
|
165
212
|
def sync(
|
|
166
|
-
neo4j_session: neo4j.Session,
|
|
167
|
-
|
|
213
|
+
neo4j_session: neo4j.Session,
|
|
214
|
+
boto3_session: boto3.session.Session,
|
|
215
|
+
regions: List[str],
|
|
216
|
+
current_aws_account_id: str,
|
|
217
|
+
update_tag: int,
|
|
218
|
+
common_job_parameters: Dict,
|
|
168
219
|
) -> None:
|
|
169
220
|
for region in regions:
|
|
170
|
-
logger.info(
|
|
171
|
-
|
|
221
|
+
logger.info(
|
|
222
|
+
"Syncing Redshift clusters for region '%s' in account '%s'.",
|
|
223
|
+
region,
|
|
224
|
+
current_aws_account_id,
|
|
225
|
+
)
|
|
226
|
+
sync_redshift_clusters(
|
|
227
|
+
neo4j_session,
|
|
228
|
+
boto3_session,
|
|
229
|
+
region,
|
|
230
|
+
current_aws_account_id,
|
|
231
|
+
update_tag,
|
|
232
|
+
)
|
|
172
233
|
cleanup(neo4j_session, common_job_parameters)
|
|
@@ -22,7 +22,7 @@ def get_short_id_from_ec2_arn(arn: str) -> str:
|
|
|
22
22
|
:param arn: The ARN
|
|
23
23
|
:return: The resource ID
|
|
24
24
|
"""
|
|
25
|
-
return arn.split(
|
|
25
|
+
return arn.split("/")[-1]
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def get_bucket_name_from_arn(bucket_arn: str) -> str:
|
|
@@ -32,7 +32,7 @@ def get_bucket_name_from_arn(bucket_arn: str) -> str:
|
|
|
32
32
|
:param arn: The S3 bucket's full ARN
|
|
33
33
|
:return: The S3 bucket's name
|
|
34
34
|
"""
|
|
35
|
-
return bucket_arn.split(
|
|
35
|
+
return bucket_arn.split(":")[-1]
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def get_short_id_from_elb_arn(alb_arn: str) -> str:
|
|
@@ -42,7 +42,7 @@ def get_short_id_from_elb_arn(alb_arn: str) -> str:
|
|
|
42
42
|
:param arn: The ELB's full ARN
|
|
43
43
|
:return: The ELB's name
|
|
44
44
|
"""
|
|
45
|
-
return alb_arn.split(
|
|
45
|
+
return alb_arn.split("/")[-1]
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
def get_short_id_from_lb2_arn(alb_arn: str) -> str:
|
|
@@ -53,7 +53,7 @@ def get_short_id_from_lb2_arn(alb_arn: str) -> str:
|
|
|
53
53
|
:param arn: The (N|A)LB's full ARN
|
|
54
54
|
:return: The (N|A)LB's name
|
|
55
55
|
"""
|
|
56
|
-
return alb_arn.split(
|
|
56
|
+
return alb_arn.split("/")[-2]
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
# We maintain a mapping from AWS resource types to their associated labels and unique identifiers.
|
|
@@ -64,79 +64,121 @@ def get_short_id_from_lb2_arn(alb_arn: str) -> str:
|
|
|
64
64
|
# cartography uses.
|
|
65
65
|
# TODO - we should make EC2 and S3 assets query-able by their full ARN so that we don't need this workaround.
|
|
66
66
|
TAG_RESOURCE_TYPE_MAPPINGS: Dict = {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
'ecr:repository': {'label': 'ECRRepository', 'property': 'id'},
|
|
74
|
-
'ec2:security-group': {'label': 'EC2SecurityGroup', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
|
|
75
|
-
'ec2:subnet': {'label': 'EC2Subnet', 'property': 'subnetid', 'id_func': get_short_id_from_ec2_arn},
|
|
76
|
-
'ec2:transit-gateway': {'label': 'AWSTransitGateway', 'property': 'id'},
|
|
77
|
-
'ec2:transit-gateway-attachment': {'label': 'AWSTransitGatewayAttachment', 'property': 'id'},
|
|
78
|
-
'ec2:vpc': {'label': 'AWSVpc', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
|
|
79
|
-
'ec2:volume': {'label': 'EBSVolume', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
|
|
80
|
-
'ec2:elastic-ip-address': {'label': 'ElasticIPAddress', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
|
|
81
|
-
'ecs:cluster': {'label': 'ECSCluster', 'property': 'id'},
|
|
82
|
-
'ecs:container': {'label': 'ECSContainer', 'property': 'id'},
|
|
83
|
-
'ecs:container-instance': {'label': 'ECSContainerInstance', 'property': 'id'},
|
|
84
|
-
'ecs:task': {'label': 'ECSTask', 'property': 'id'},
|
|
85
|
-
'ecs:task-definition': {'label': 'ECSTaskDefinition', 'property': 'id'},
|
|
86
|
-
'eks:cluster': {'label': 'EKSCluster', 'property': 'id'},
|
|
87
|
-
'elasticache:cluster': {'label': 'ElasticacheCluster', 'property': 'arn'},
|
|
88
|
-
'elasticloadbalancing:loadbalancer': {
|
|
89
|
-
'label': 'LoadBalancer', 'property':
|
|
90
|
-
'name', 'id_func': get_short_id_from_elb_arn,
|
|
67
|
+
"autoscaling:autoScalingGroup": {"label": "AutoScalingGroup", "property": "arn"},
|
|
68
|
+
"dynamodb:table": {"label": "DynamoDBTable", "property": "id"},
|
|
69
|
+
"ec2:instance": {
|
|
70
|
+
"label": "EC2Instance",
|
|
71
|
+
"property": "id",
|
|
72
|
+
"id_func": get_short_id_from_ec2_arn,
|
|
91
73
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
74
|
+
"ec2:internet-gateway": {
|
|
75
|
+
"label": "AWSInternetGateway",
|
|
76
|
+
"property": "id",
|
|
77
|
+
"id_func": get_short_id_from_ec2_arn,
|
|
95
78
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
79
|
+
"ec2:key-pair": {"label": "EC2KeyPair", "property": "id"},
|
|
80
|
+
"ec2:network-interface": {
|
|
81
|
+
"label": "NetworkInterface",
|
|
82
|
+
"property": "id",
|
|
83
|
+
"id_func": get_short_id_from_ec2_arn,
|
|
99
84
|
},
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
85
|
+
"ecr:repository": {"label": "ECRRepository", "property": "id"},
|
|
86
|
+
"ec2:security-group": {
|
|
87
|
+
"label": "EC2SecurityGroup",
|
|
88
|
+
"property": "id",
|
|
89
|
+
"id_func": get_short_id_from_ec2_arn,
|
|
90
|
+
},
|
|
91
|
+
"ec2:subnet": {
|
|
92
|
+
"label": "EC2Subnet",
|
|
93
|
+
"property": "subnetid",
|
|
94
|
+
"id_func": get_short_id_from_ec2_arn,
|
|
95
|
+
},
|
|
96
|
+
"ec2:transit-gateway": {"label": "AWSTransitGateway", "property": "id"},
|
|
97
|
+
"ec2:transit-gateway-attachment": {
|
|
98
|
+
"label": "AWSTransitGatewayAttachment",
|
|
99
|
+
"property": "id",
|
|
100
|
+
},
|
|
101
|
+
"ec2:vpc": {
|
|
102
|
+
"label": "AWSVpc",
|
|
103
|
+
"property": "id",
|
|
104
|
+
"id_func": get_short_id_from_ec2_arn,
|
|
105
|
+
},
|
|
106
|
+
"ec2:volume": {
|
|
107
|
+
"label": "EBSVolume",
|
|
108
|
+
"property": "id",
|
|
109
|
+
"id_func": get_short_id_from_ec2_arn,
|
|
110
|
+
},
|
|
111
|
+
"ec2:elastic-ip-address": {
|
|
112
|
+
"label": "ElasticIPAddress",
|
|
113
|
+
"property": "id",
|
|
114
|
+
"id_func": get_short_id_from_ec2_arn,
|
|
115
|
+
},
|
|
116
|
+
"ecs:cluster": {"label": "ECSCluster", "property": "id"},
|
|
117
|
+
"ecs:container": {"label": "ECSContainer", "property": "id"},
|
|
118
|
+
"ecs:container-instance": {"label": "ECSContainerInstance", "property": "id"},
|
|
119
|
+
"ecs:task": {"label": "ECSTask", "property": "id"},
|
|
120
|
+
"ecs:task-definition": {"label": "ECSTaskDefinition", "property": "id"},
|
|
121
|
+
"eks:cluster": {"label": "EKSCluster", "property": "id"},
|
|
122
|
+
"elasticache:cluster": {"label": "ElasticacheCluster", "property": "arn"},
|
|
123
|
+
"elasticloadbalancing:loadbalancer": {
|
|
124
|
+
"label": "LoadBalancer",
|
|
125
|
+
"property": "name",
|
|
126
|
+
"id_func": get_short_id_from_elb_arn,
|
|
127
|
+
},
|
|
128
|
+
"elasticloadbalancing:loadbalancer/app": {
|
|
129
|
+
"label": "LoadBalancerV2",
|
|
130
|
+
"property": "name",
|
|
131
|
+
"id_func": get_short_id_from_lb2_arn,
|
|
132
|
+
},
|
|
133
|
+
"elasticloadbalancing:loadbalancer/net": {
|
|
134
|
+
"label": "LoadBalancerV2",
|
|
135
|
+
"property": "name",
|
|
136
|
+
"id_func": get_short_id_from_lb2_arn,
|
|
137
|
+
},
|
|
138
|
+
"elasticmapreduce:cluster": {"label": "EMRCluster", "property": "arn"},
|
|
139
|
+
"es:domain": {"label": "ESDomain", "property": "arn"},
|
|
140
|
+
"kms:key": {"label": "KMSKey", "property": "arn"},
|
|
141
|
+
"iam:group": {"label": "AWSGroup", "property": "arn"},
|
|
142
|
+
"iam:role": {"label": "AWSRole", "property": "arn"},
|
|
143
|
+
"iam:user": {"label": "AWSUser", "property": "arn"},
|
|
144
|
+
"lambda:function": {"label": "AWSLambda", "property": "id"},
|
|
145
|
+
"redshift:cluster": {"label": "RedshiftCluster", "property": "id"},
|
|
146
|
+
"rds:db": {"label": "RDSInstance", "property": "id"},
|
|
147
|
+
"rds:subgrp": {"label": "DBSubnetGroup", "property": "id"},
|
|
148
|
+
"rds:cluster": {"label": "RDSCluster", "property": "id"},
|
|
149
|
+
"rds:snapshot": {"label": "RDSSnapshot", "property": "id"},
|
|
112
150
|
# Buckets are the only objects in the S3 service: https://docs.aws.amazon.com/AmazonS3/latest/dev/s3-arn-format.html
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
151
|
+
"s3": {"label": "S3Bucket", "property": "id", "id_func": get_bucket_name_from_arn},
|
|
152
|
+
"secretsmanager:secret": {"label": "SecretsManagerSecret", "property": "id"},
|
|
153
|
+
"sqs": {"label": "SQSQueue", "property": "id"},
|
|
116
154
|
}
|
|
117
155
|
|
|
118
156
|
|
|
119
157
|
@timeit
|
|
120
158
|
@aws_handle_regions
|
|
121
|
-
def get_tags(
|
|
159
|
+
def get_tags(
|
|
160
|
+
boto3_session: boto3.session.Session,
|
|
161
|
+
resource_type: str,
|
|
162
|
+
region: str,
|
|
163
|
+
) -> List[Dict]:
|
|
122
164
|
"""
|
|
123
165
|
Create boto3 client and retrieve tag data.
|
|
124
166
|
"""
|
|
125
167
|
# this is a temporary workaround to populate AWS tags for IAM roles.
|
|
126
168
|
# resourcegroupstaggingapi does not support IAM roles and no ETA is provided
|
|
127
169
|
# TODO: when resourcegroupstaggingapi supports iam:role, remove this condition block
|
|
128
|
-
if resource_type ==
|
|
170
|
+
if resource_type == "iam:role":
|
|
129
171
|
return get_role_tags(boto3_session)
|
|
130
172
|
|
|
131
|
-
client = boto3_session.client(
|
|
132
|
-
paginator = client.get_paginator(
|
|
173
|
+
client = boto3_session.client("resourcegroupstaggingapi", region_name=region)
|
|
174
|
+
paginator = client.get_paginator("get_resources")
|
|
133
175
|
resources: List[Dict] = []
|
|
134
176
|
for page in paginator.paginate(
|
|
135
177
|
# Only ingest tags for resources that Cartography supports.
|
|
136
178
|
# This is just a starting list; there may be others supported by this API.
|
|
137
179
|
ResourceTypeFilters=[resource_type],
|
|
138
180
|
):
|
|
139
|
-
resources.extend(page[
|
|
181
|
+
resources.extend(page["ResourceTagMappingList"])
|
|
140
182
|
return resources
|
|
141
183
|
|
|
142
184
|
|
|
@@ -148,7 +190,8 @@ def _load_tags_tx(
|
|
|
148
190
|
current_aws_account_id: str,
|
|
149
191
|
aws_update_tag: int,
|
|
150
192
|
) -> None:
|
|
151
|
-
INGEST_TAG_TEMPLATE = Template(
|
|
193
|
+
INGEST_TAG_TEMPLATE = Template(
|
|
194
|
+
"""
|
|
152
195
|
UNWIND $TagData as tag_mapping
|
|
153
196
|
UNWIND tag_mapping.Tags as input_tag
|
|
154
197
|
MATCH
|
|
@@ -165,10 +208,11 @@ def _load_tags_tx(
|
|
|
165
208
|
MERGE (resource)-[r:TAGGED]->(aws_tag)
|
|
166
209
|
SET r.lastupdated = $UpdateTag,
|
|
167
210
|
r.firstseen = timestamp()
|
|
168
|
-
"""
|
|
211
|
+
""",
|
|
212
|
+
)
|
|
169
213
|
query = INGEST_TAG_TEMPLATE.safe_substitute(
|
|
170
|
-
resource_label=TAG_RESOURCE_TYPE_MAPPINGS[resource_type][
|
|
171
|
-
property=TAG_RESOURCE_TYPE_MAPPINGS[resource_type][
|
|
214
|
+
resource_label=TAG_RESOURCE_TYPE_MAPPINGS[resource_type]["label"],
|
|
215
|
+
property=TAG_RESOURCE_TYPE_MAPPINGS[resource_type]["property"],
|
|
172
216
|
)
|
|
173
217
|
tx.run(
|
|
174
218
|
query,
|
|
@@ -205,20 +249,26 @@ def load_tags(
|
|
|
205
249
|
@timeit
|
|
206
250
|
def transform_tags(tag_data: Dict, resource_type: str) -> None:
|
|
207
251
|
for tag_mapping in tag_data:
|
|
208
|
-
tag_mapping[
|
|
252
|
+
tag_mapping["resource_id"] = compute_resource_id(tag_mapping, resource_type)
|
|
209
253
|
|
|
210
254
|
|
|
211
255
|
def compute_resource_id(tag_mapping: Dict, resource_type: str) -> str:
|
|
212
|
-
resource_id = tag_mapping[
|
|
213
|
-
if
|
|
214
|
-
parse_resource_id_from_arn = TAG_RESOURCE_TYPE_MAPPINGS[resource_type][
|
|
215
|
-
|
|
256
|
+
resource_id = tag_mapping["ResourceARN"]
|
|
257
|
+
if "id_func" in TAG_RESOURCE_TYPE_MAPPINGS[resource_type]:
|
|
258
|
+
parse_resource_id_from_arn = TAG_RESOURCE_TYPE_MAPPINGS[resource_type][
|
|
259
|
+
"id_func"
|
|
260
|
+
]
|
|
261
|
+
resource_id = parse_resource_id_from_arn(tag_mapping["ResourceARN"])
|
|
216
262
|
return resource_id
|
|
217
263
|
|
|
218
264
|
|
|
219
265
|
@timeit
|
|
220
266
|
def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
221
|
-
run_cleanup_job(
|
|
267
|
+
run_cleanup_job(
|
|
268
|
+
"aws_import_tags_cleanup.json",
|
|
269
|
+
neo4j_session,
|
|
270
|
+
common_job_parameters,
|
|
271
|
+
)
|
|
222
272
|
|
|
223
273
|
|
|
224
274
|
@timeit
|
|
@@ -232,11 +282,15 @@ def sync(
|
|
|
232
282
|
tag_resource_type_mappings: Dict = TAG_RESOURCE_TYPE_MAPPINGS,
|
|
233
283
|
) -> None:
|
|
234
284
|
for region in regions:
|
|
235
|
-
logger.info(
|
|
285
|
+
logger.info(
|
|
286
|
+
f"Syncing AWS tags for account {current_aws_account_id} and region {region}",
|
|
287
|
+
)
|
|
236
288
|
for resource_type in tag_resource_type_mappings.keys():
|
|
237
289
|
tag_data = get_tags(boto3_session, resource_type, region)
|
|
238
290
|
transform_tags(tag_data, resource_type) # type: ignore
|
|
239
|
-
logger.info(
|
|
291
|
+
logger.info(
|
|
292
|
+
f"Loading {len(tag_data)} tags for resource type {resource_type}",
|
|
293
|
+
)
|
|
240
294
|
load_tags(
|
|
241
295
|
neo4j_session=neo4j_session,
|
|
242
296
|
tag_data=tag_data, # type: ignore
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
from typing import Callable
|
|
2
2
|
from typing import Dict
|
|
3
3
|
|
|
4
|
+
from cartography.intel.aws.ec2.route_tables import sync_route_tables
|
|
5
|
+
|
|
4
6
|
from . import apigateway
|
|
7
|
+
from . import cloudtrail
|
|
8
|
+
from . import cloudwatch
|
|
5
9
|
from . import config
|
|
6
10
|
from . import dynamodb
|
|
7
11
|
from . import ecr
|
|
8
12
|
from . import ecs
|
|
13
|
+
from . import efs
|
|
9
14
|
from . import eks
|
|
10
15
|
from . import elasticache
|
|
11
16
|
from . import elasticsearch
|
|
@@ -21,8 +26,10 @@ from . import redshift
|
|
|
21
26
|
from . import resourcegroupstaggingapi
|
|
22
27
|
from . import route53
|
|
23
28
|
from . import s3
|
|
29
|
+
from . import s3accountpublicaccessblock
|
|
24
30
|
from . import secretsmanager
|
|
25
31
|
from . import securityhub
|
|
32
|
+
from . import sns
|
|
26
33
|
from . import sqs
|
|
27
34
|
from . import ssm
|
|
28
35
|
from .ec2.auto_scaling_groups import sync_ec2_auto_scaling_groups
|
|
@@ -47,50 +54,56 @@ from .ec2.vpc_peerings import sync_vpc_peerings
|
|
|
47
54
|
from .iam_instance_profiles import sync_iam_instance_profiles
|
|
48
55
|
|
|
49
56
|
RESOURCE_FUNCTIONS: Dict[str, Callable[..., None]] = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
"iam": iam.sync,
|
|
58
|
+
"iaminstanceprofiles": sync_iam_instance_profiles,
|
|
59
|
+
"s3": s3.sync,
|
|
60
|
+
"dynamodb": dynamodb.sync,
|
|
61
|
+
"ec2:launch_templates": sync_ec2_launch_templates,
|
|
62
|
+
"ec2:autoscalinggroup": sync_ec2_auto_scaling_groups,
|
|
56
63
|
# `ec2:instance` must be included before `ssm` and `ec2:images`,
|
|
57
64
|
# they rely on EC2Instance data provided by this module.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
65
|
+
"ec2:instance": sync_ec2_instances,
|
|
66
|
+
"ec2:images": sync_ec2_images,
|
|
67
|
+
"ec2:keypair": sync_ec2_key_pairs,
|
|
68
|
+
"ec2:load_balancer": sync_load_balancers,
|
|
69
|
+
"ec2:load_balancer_v2": sync_load_balancer_v2s,
|
|
70
|
+
"ec2:network_acls": sync_network_acls,
|
|
71
|
+
"ec2:network_interface": sync_network_interfaces,
|
|
72
|
+
"ec2:route_table": sync_route_tables,
|
|
73
|
+
"ec2:security_group": sync_ec2_security_groupinfo,
|
|
74
|
+
"ec2:subnet": sync_subnets,
|
|
75
|
+
"ec2:tgw": sync_transit_gateways,
|
|
76
|
+
"ec2:vpc": sync_vpc,
|
|
77
|
+
"ec2:vpc_peering": sync_vpc_peerings,
|
|
78
|
+
"ec2:internet_gateway": sync_internet_gateways,
|
|
79
|
+
"ec2:reserved_instances": sync_ec2_reserved_instances,
|
|
80
|
+
"ec2:volumes": sync_ebs_volumes,
|
|
81
|
+
"ec2:snapshots": sync_ebs_snapshots,
|
|
82
|
+
"ecr": ecr.sync,
|
|
83
|
+
"ecs": ecs.sync,
|
|
84
|
+
"eks": eks.sync,
|
|
85
|
+
"elasticache": elasticache.sync,
|
|
86
|
+
"elastic_ip_addresses": sync_elastic_ip_addresses,
|
|
87
|
+
"emr": emr.sync,
|
|
88
|
+
"lambda_function": lambda_function.sync,
|
|
89
|
+
"kms": kms.sync,
|
|
90
|
+
"rds": rds.sync,
|
|
91
|
+
"redshift": redshift.sync,
|
|
92
|
+
"route53": route53.sync,
|
|
93
|
+
"elasticsearch": elasticsearch.sync,
|
|
94
|
+
"permission_relationships": permission_relationships.sync,
|
|
95
|
+
"resourcegroupstaggingapi": resourcegroupstaggingapi.sync,
|
|
96
|
+
"apigateway": apigateway.sync,
|
|
97
|
+
"secretsmanager": secretsmanager.sync,
|
|
98
|
+
"securityhub": securityhub.sync,
|
|
99
|
+
"s3accountpublicaccessblock": s3accountpublicaccessblock.sync,
|
|
100
|
+
"sns": sns.sync,
|
|
101
|
+
"sqs": sqs.sync,
|
|
102
|
+
"ssm": ssm.sync,
|
|
103
|
+
"inspector": inspector.sync,
|
|
104
|
+
"config": config.sync,
|
|
105
|
+
"identitycenter": identitycenter.sync_identity_center_instances,
|
|
106
|
+
"cloudtrail": cloudtrail.sync,
|
|
107
|
+
"cloudwatch": cloudwatch.sync,
|
|
108
|
+
"efs": efs.sync,
|
|
96
109
|
}
|