cartography 0.102.0rc1__py3-none-any.whl → 0.103.0rc1__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 +302 -253
- cartography/client/core/tx.py +39 -18
- cartography/config.py +4 -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/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/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 +53 -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/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/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/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/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/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/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/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/stats.py +3 -3
- cartography/sync.py +107 -31
- cartography/util.py +84 -62
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/METADATA +3 -14
- cartography-0.103.0rc1.dist-info/RECORD +396 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/WHEEL +1 -1
- cartography-0.102.0rc1.dist-info/RECORD +0 -377
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/entry_points.txt +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/top_level.txt +0 -0
cartography/intel/aws/ec2/vpc.py
CHANGED
|
@@ -6,23 +6,29 @@ from typing import List
|
|
|
6
6
|
import boto3
|
|
7
7
|
import neo4j
|
|
8
8
|
|
|
9
|
-
from .util import get_botocore_config
|
|
10
9
|
from cartography.util import aws_handle_regions
|
|
11
10
|
from cartography.util import run_cleanup_job
|
|
12
11
|
from cartography.util import timeit
|
|
13
12
|
|
|
13
|
+
from .util import get_botocore_config
|
|
14
|
+
|
|
14
15
|
logger = logging.getLogger(__name__)
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
@timeit
|
|
18
19
|
@aws_handle_regions
|
|
19
20
|
def get_ec2_vpcs(boto3_session: boto3.session.Session, region: str) -> List[Dict]:
|
|
20
|
-
client = boto3_session.client(
|
|
21
|
-
|
|
21
|
+
client = boto3_session.client(
|
|
22
|
+
"ec2",
|
|
23
|
+
region_name=region,
|
|
24
|
+
config=get_botocore_config(),
|
|
25
|
+
)
|
|
26
|
+
return client.describe_vpcs()["Vpcs"]
|
|
22
27
|
|
|
23
28
|
|
|
24
29
|
def _get_cidr_association_statement(block_type: str) -> str:
|
|
25
|
-
INGEST_CIDR_TEMPLATE = Template(
|
|
30
|
+
INGEST_CIDR_TEMPLATE = Template(
|
|
31
|
+
"""
|
|
26
32
|
MATCH (vpc:AWSVpc{id: $VpcId})
|
|
27
33
|
WITH vpc
|
|
28
34
|
UNWIND $CidrBlock as block_data
|
|
@@ -36,7 +42,8 @@ def _get_cidr_association_statement(block_type: str) -> str:
|
|
|
36
42
|
WITH vpc, new_block
|
|
37
43
|
MERGE (vpc)-[r:BLOCK_ASSOCIATION]->(new_block)
|
|
38
44
|
ON CREATE SET r.firstseen = timestamp()
|
|
39
|
-
SET r.lastupdated = $update_tag"""
|
|
45
|
+
SET r.lastupdated = $update_tag""",
|
|
46
|
+
)
|
|
40
47
|
|
|
41
48
|
BLOCK_CIDR = "CidrBlock"
|
|
42
49
|
STATE_NAME = "CidrBlockState"
|
|
@@ -53,12 +60,19 @@ def _get_cidr_association_statement(block_type: str) -> str:
|
|
|
53
60
|
else:
|
|
54
61
|
raise ValueError(f"Unsupported block type specified - {block_type}")
|
|
55
62
|
|
|
56
|
-
return INGEST_CIDR_TEMPLATE.safe_substitute(
|
|
63
|
+
return INGEST_CIDR_TEMPLATE.safe_substitute(
|
|
64
|
+
block_label=BLOCK_TYPE,
|
|
65
|
+
block_cidr=BLOCK_CIDR,
|
|
66
|
+
state_name=STATE_NAME,
|
|
67
|
+
)
|
|
57
68
|
|
|
58
69
|
|
|
59
70
|
@timeit
|
|
60
71
|
def load_cidr_association_set(
|
|
61
|
-
neo4j_session: neo4j.Session,
|
|
72
|
+
neo4j_session: neo4j.Session,
|
|
73
|
+
vpc_id: str,
|
|
74
|
+
vpc_data: Dict,
|
|
75
|
+
block_type: str,
|
|
62
76
|
update_tag: int,
|
|
63
77
|
) -> None:
|
|
64
78
|
ingest_statement = _get_cidr_association_statement(block_type)
|
|
@@ -78,7 +92,10 @@ def load_cidr_association_set(
|
|
|
78
92
|
|
|
79
93
|
@timeit
|
|
80
94
|
def load_ec2_vpcs(
|
|
81
|
-
neo4j_session: neo4j.Session,
|
|
95
|
+
neo4j_session: neo4j.Session,
|
|
96
|
+
data: List[Dict],
|
|
97
|
+
region: str,
|
|
98
|
+
current_aws_account_id: str,
|
|
82
99
|
update_tag: int,
|
|
83
100
|
) -> None:
|
|
84
101
|
# https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-vpcs.html
|
|
@@ -161,16 +178,24 @@ def load_ec2_vpcs(
|
|
|
161
178
|
|
|
162
179
|
@timeit
|
|
163
180
|
def cleanup_ec2_vpcs(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
164
|
-
run_cleanup_job(
|
|
181
|
+
run_cleanup_job("aws_import_vpc_cleanup.json", neo4j_session, common_job_parameters)
|
|
165
182
|
|
|
166
183
|
|
|
167
184
|
@timeit
|
|
168
185
|
def sync_vpc(
|
|
169
|
-
neo4j_session: neo4j.Session,
|
|
170
|
-
|
|
186
|
+
neo4j_session: neo4j.Session,
|
|
187
|
+
boto3_session: boto3.session.Session,
|
|
188
|
+
regions: List[str],
|
|
189
|
+
current_aws_account_id: str,
|
|
190
|
+
update_tag: int,
|
|
191
|
+
common_job_parameters: Dict,
|
|
171
192
|
) -> None:
|
|
172
193
|
for region in regions:
|
|
173
|
-
logger.info(
|
|
194
|
+
logger.info(
|
|
195
|
+
"Syncing EC2 VPC for region '%s' in account '%s'.",
|
|
196
|
+
region,
|
|
197
|
+
current_aws_account_id,
|
|
198
|
+
)
|
|
174
199
|
data = get_ec2_vpcs(boto3_session, region)
|
|
175
200
|
load_ec2_vpcs(neo4j_session, data, region, current_aws_account_id, update_tag)
|
|
176
201
|
cleanup_ec2_vpcs(neo4j_session, common_job_parameters)
|
|
@@ -5,25 +5,36 @@ from typing import List
|
|
|
5
5
|
import boto3
|
|
6
6
|
import neo4j
|
|
7
7
|
|
|
8
|
-
from .util import get_botocore_config
|
|
9
8
|
from cartography.util import aws_handle_regions
|
|
10
9
|
from cartography.util import run_cleanup_job
|
|
11
10
|
from cartography.util import timeit
|
|
12
11
|
|
|
12
|
+
from .util import get_botocore_config
|
|
13
|
+
|
|
13
14
|
logger = logging.getLogger(__name__)
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
@timeit
|
|
17
18
|
@aws_handle_regions
|
|
18
|
-
def get_vpc_peerings_data(
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
def get_vpc_peerings_data(
|
|
20
|
+
boto3_session: boto3.session.Session,
|
|
21
|
+
region: str,
|
|
22
|
+
) -> List[Dict]:
|
|
23
|
+
client = boto3_session.client(
|
|
24
|
+
"ec2",
|
|
25
|
+
region_name=region,
|
|
26
|
+
config=get_botocore_config(),
|
|
27
|
+
)
|
|
28
|
+
return client.describe_vpc_peering_connections()["VpcPeeringConnections"]
|
|
21
29
|
|
|
22
30
|
|
|
23
31
|
@timeit
|
|
24
32
|
def load_vpc_peerings(
|
|
25
|
-
neo4j_session: neo4j.Session,
|
|
26
|
-
|
|
33
|
+
neo4j_session: neo4j.Session,
|
|
34
|
+
data: List[Dict],
|
|
35
|
+
region: str,
|
|
36
|
+
aws_account_id: str,
|
|
37
|
+
update_tag: int,
|
|
27
38
|
) -> None:
|
|
28
39
|
ingest_vpc_peerings = """
|
|
29
40
|
UNWIND $vpc_peerings AS vpc_peering
|
|
@@ -77,15 +88,21 @@ def load_vpc_peerings(
|
|
|
77
88
|
"""
|
|
78
89
|
|
|
79
90
|
neo4j_session.run(
|
|
80
|
-
ingest_vpc_peerings,
|
|
81
|
-
|
|
91
|
+
ingest_vpc_peerings,
|
|
92
|
+
vpc_peerings=data,
|
|
93
|
+
update_tag=update_tag,
|
|
94
|
+
region=region,
|
|
95
|
+
aws_account_id=aws_account_id,
|
|
82
96
|
)
|
|
83
97
|
|
|
84
98
|
|
|
85
99
|
@timeit
|
|
86
100
|
def load_accepter_cidrs(
|
|
87
|
-
neo4j_session: neo4j.Session,
|
|
88
|
-
|
|
101
|
+
neo4j_session: neo4j.Session,
|
|
102
|
+
data: List[Dict],
|
|
103
|
+
region: str,
|
|
104
|
+
aws_account_id: str,
|
|
105
|
+
update_tag: int,
|
|
89
106
|
) -> None:
|
|
90
107
|
|
|
91
108
|
ingest_accepter_cidr = """
|
|
@@ -110,15 +127,21 @@ def load_accepter_cidrs(
|
|
|
110
127
|
"""
|
|
111
128
|
|
|
112
129
|
neo4j_session.run(
|
|
113
|
-
ingest_accepter_cidr,
|
|
114
|
-
|
|
130
|
+
ingest_accepter_cidr,
|
|
131
|
+
vpc_peerings=data,
|
|
132
|
+
update_tag=update_tag,
|
|
133
|
+
region=region,
|
|
134
|
+
aws_account_id=aws_account_id,
|
|
115
135
|
)
|
|
116
136
|
|
|
117
137
|
|
|
118
138
|
@timeit
|
|
119
139
|
def load_requester_cidrs(
|
|
120
|
-
neo4j_session: neo4j.Session,
|
|
121
|
-
|
|
140
|
+
neo4j_session: neo4j.Session,
|
|
141
|
+
data: List[Dict],
|
|
142
|
+
region: str,
|
|
143
|
+
aws_account_id: str,
|
|
144
|
+
update_tag: int,
|
|
122
145
|
) -> None:
|
|
123
146
|
|
|
124
147
|
ingest_requester_cidr = """
|
|
@@ -143,25 +166,61 @@ def load_requester_cidrs(
|
|
|
143
166
|
"""
|
|
144
167
|
|
|
145
168
|
neo4j_session.run(
|
|
146
|
-
ingest_requester_cidr,
|
|
147
|
-
|
|
169
|
+
ingest_requester_cidr,
|
|
170
|
+
vpc_peerings=data,
|
|
171
|
+
update_tag=update_tag,
|
|
172
|
+
region=region,
|
|
173
|
+
aws_account_id=aws_account_id,
|
|
148
174
|
)
|
|
149
175
|
|
|
150
176
|
|
|
151
177
|
@timeit
|
|
152
|
-
def cleanup_vpc_peerings(
|
|
153
|
-
|
|
178
|
+
def cleanup_vpc_peerings(
|
|
179
|
+
neo4j_session: neo4j.Session,
|
|
180
|
+
common_job_parameters: Dict,
|
|
181
|
+
) -> None:
|
|
182
|
+
run_cleanup_job(
|
|
183
|
+
"aws_import_vpc_peering_cleanup.json",
|
|
184
|
+
neo4j_session,
|
|
185
|
+
common_job_parameters,
|
|
186
|
+
)
|
|
154
187
|
|
|
155
188
|
|
|
156
189
|
@timeit
|
|
157
190
|
def sync_vpc_peerings(
|
|
158
|
-
neo4j_session: neo4j.Session,
|
|
159
|
-
|
|
191
|
+
neo4j_session: neo4j.Session,
|
|
192
|
+
boto3_session: boto3.session.Session,
|
|
193
|
+
regions: List[str],
|
|
194
|
+
current_aws_account_id: str,
|
|
195
|
+
update_tag: int,
|
|
196
|
+
common_job_parameters: Dict,
|
|
160
197
|
) -> None:
|
|
161
198
|
for region in regions:
|
|
162
|
-
logger.debug(
|
|
199
|
+
logger.debug(
|
|
200
|
+
"Syncing EC2 VPC peering for region '%s' in account '%s'.",
|
|
201
|
+
region,
|
|
202
|
+
current_aws_account_id,
|
|
203
|
+
)
|
|
163
204
|
data = get_vpc_peerings_data(boto3_session, region)
|
|
164
|
-
load_vpc_peerings(
|
|
165
|
-
|
|
166
|
-
|
|
205
|
+
load_vpc_peerings(
|
|
206
|
+
neo4j_session,
|
|
207
|
+
data,
|
|
208
|
+
region,
|
|
209
|
+
current_aws_account_id,
|
|
210
|
+
update_tag,
|
|
211
|
+
)
|
|
212
|
+
load_accepter_cidrs(
|
|
213
|
+
neo4j_session,
|
|
214
|
+
data,
|
|
215
|
+
region,
|
|
216
|
+
current_aws_account_id,
|
|
217
|
+
update_tag,
|
|
218
|
+
)
|
|
219
|
+
load_requester_cidrs(
|
|
220
|
+
neo4j_session,
|
|
221
|
+
data,
|
|
222
|
+
region,
|
|
223
|
+
current_aws_account_id,
|
|
224
|
+
update_tag,
|
|
225
|
+
)
|
|
167
226
|
cleanup_vpc_peerings(neo4j_session, common_job_parameters)
|
cartography/intel/aws/ecr.py
CHANGED
|
@@ -18,33 +18,48 @@ logger = logging.getLogger(__name__)
|
|
|
18
18
|
|
|
19
19
|
@timeit
|
|
20
20
|
@aws_handle_regions
|
|
21
|
-
def get_ecr_repositories(
|
|
21
|
+
def get_ecr_repositories(
|
|
22
|
+
boto3_session: boto3.session.Session,
|
|
23
|
+
region: str,
|
|
24
|
+
) -> List[Dict]:
|
|
22
25
|
logger.info("Getting ECR repositories for region '%s'.", region)
|
|
23
|
-
client = boto3_session.client(
|
|
24
|
-
paginator = client.get_paginator(
|
|
26
|
+
client = boto3_session.client("ecr", region_name=region)
|
|
27
|
+
paginator = client.get_paginator("describe_repositories")
|
|
25
28
|
ecr_repositories: List[Dict] = []
|
|
26
29
|
for page in paginator.paginate():
|
|
27
|
-
ecr_repositories.extend(page[
|
|
30
|
+
ecr_repositories.extend(page["repositories"])
|
|
28
31
|
return ecr_repositories
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
@timeit
|
|
32
35
|
@aws_handle_regions
|
|
33
|
-
def get_ecr_repository_images(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
def get_ecr_repository_images(
|
|
37
|
+
boto3_session: boto3.session.Session, region: str, repository_name: str
|
|
38
|
+
) -> List[Dict]:
|
|
39
|
+
logger.debug(
|
|
40
|
+
"Getting ECR images in repository '%s' for region '%s'.",
|
|
41
|
+
repository_name,
|
|
42
|
+
region,
|
|
43
|
+
)
|
|
44
|
+
client = boto3_session.client("ecr", region_name=region)
|
|
45
|
+
list_paginator = client.get_paginator("list_images")
|
|
37
46
|
ecr_repository_images: List[Dict] = []
|
|
38
47
|
for page in list_paginator.paginate(repositoryName=repository_name):
|
|
39
|
-
image_ids = page[
|
|
48
|
+
image_ids = page["imageIds"]
|
|
40
49
|
if not image_ids:
|
|
41
50
|
continue
|
|
42
|
-
describe_paginator = client.get_paginator(
|
|
43
|
-
describe_response = describe_paginator.paginate(
|
|
51
|
+
describe_paginator = client.get_paginator("describe_images")
|
|
52
|
+
describe_response = describe_paginator.paginate(
|
|
53
|
+
repositoryName=repository_name, imageIds=image_ids
|
|
54
|
+
)
|
|
44
55
|
for response in describe_response:
|
|
45
|
-
image_details = response[
|
|
56
|
+
image_details = response["imageDetails"]
|
|
46
57
|
image_details = [
|
|
47
|
-
|
|
58
|
+
(
|
|
59
|
+
{**detail, "imageTag": detail["imageTags"][0]}
|
|
60
|
+
if detail.get("imageTags")
|
|
61
|
+
else detail
|
|
62
|
+
)
|
|
48
63
|
for detail in image_details
|
|
49
64
|
]
|
|
50
65
|
ecr_repository_images.extend(image_details)
|
|
@@ -53,7 +68,10 @@ def get_ecr_repository_images(boto3_session: boto3.session.Session, region: str,
|
|
|
53
68
|
|
|
54
69
|
@timeit
|
|
55
70
|
def load_ecr_repositories(
|
|
56
|
-
neo4j_session: neo4j.Session,
|
|
71
|
+
neo4j_session: neo4j.Session,
|
|
72
|
+
repos: List[Dict],
|
|
73
|
+
region: str,
|
|
74
|
+
current_aws_account_id: str,
|
|
57
75
|
aws_update_tag: int,
|
|
58
76
|
) -> None:
|
|
59
77
|
query = """
|
|
@@ -73,7 +91,9 @@ def load_ecr_repositories(
|
|
|
73
91
|
ON CREATE SET r.firstseen = timestamp()
|
|
74
92
|
SET r.lastupdated = $aws_update_tag
|
|
75
93
|
"""
|
|
76
|
-
logger.info(
|
|
94
|
+
logger.info(
|
|
95
|
+
f"Loading {len(repos)} ECR repositories for region {region} into graph.",
|
|
96
|
+
)
|
|
77
97
|
neo4j_session.run(
|
|
78
98
|
query,
|
|
79
99
|
Repositories=repos,
|
|
@@ -91,21 +111,23 @@ def transform_ecr_repository_images(repo_data: Dict) -> List[Dict]:
|
|
|
91
111
|
repo_images_list = []
|
|
92
112
|
for repo_uri, repo_images in repo_data.items():
|
|
93
113
|
for img in repo_images:
|
|
94
|
-
if
|
|
95
|
-
img[
|
|
114
|
+
if "imageDigest" in img and img["imageDigest"]:
|
|
115
|
+
img["repo_uri"] = repo_uri
|
|
96
116
|
repo_images_list.append(img)
|
|
97
117
|
else:
|
|
98
118
|
logger.warning(
|
|
99
119
|
"Repo %s has an image that has no imageDigest. Its tag is %s. Continuing on.",
|
|
100
120
|
repo_uri,
|
|
101
|
-
img.get(
|
|
121
|
+
img.get("imageTag"),
|
|
102
122
|
)
|
|
103
123
|
|
|
104
124
|
return repo_images_list
|
|
105
125
|
|
|
106
126
|
|
|
107
127
|
def _load_ecr_repo_img_tx(
|
|
108
|
-
tx: neo4j.Transaction,
|
|
128
|
+
tx: neo4j.Transaction,
|
|
129
|
+
repo_images_list: List[Dict],
|
|
130
|
+
aws_update_tag: int,
|
|
109
131
|
region: str,
|
|
110
132
|
) -> None:
|
|
111
133
|
query = """
|
|
@@ -139,23 +161,37 @@ def _load_ecr_repo_img_tx(
|
|
|
139
161
|
ON CREATE SET r2.firstseen = timestamp()
|
|
140
162
|
SET r2.lastupdated = $aws_update_tag
|
|
141
163
|
"""
|
|
142
|
-
tx.run(
|
|
164
|
+
tx.run(
|
|
165
|
+
query,
|
|
166
|
+
RepoList=repo_images_list,
|
|
167
|
+
Region=region,
|
|
168
|
+
aws_update_tag=aws_update_tag,
|
|
169
|
+
)
|
|
143
170
|
|
|
144
171
|
|
|
145
172
|
@timeit
|
|
146
173
|
def load_ecr_repository_images(
|
|
147
|
-
neo4j_session: neo4j.Session,
|
|
174
|
+
neo4j_session: neo4j.Session,
|
|
175
|
+
repo_images_list: List[Dict],
|
|
176
|
+
region: str,
|
|
148
177
|
aws_update_tag: int,
|
|
149
178
|
) -> None:
|
|
150
|
-
logger.info(
|
|
179
|
+
logger.info(
|
|
180
|
+
f"Loading {len(repo_images_list)} ECR repository images in {region} into graph.",
|
|
181
|
+
)
|
|
151
182
|
for repo_image_batch in batch(repo_images_list, size=10000):
|
|
152
|
-
neo4j_session.write_transaction(
|
|
183
|
+
neo4j_session.write_transaction(
|
|
184
|
+
_load_ecr_repo_img_tx,
|
|
185
|
+
repo_image_batch,
|
|
186
|
+
aws_update_tag,
|
|
187
|
+
region,
|
|
188
|
+
)
|
|
153
189
|
|
|
154
190
|
|
|
155
191
|
@timeit
|
|
156
192
|
def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
157
193
|
logger.debug("Running ECR cleanup job.")
|
|
158
|
-
run_cleanup_job(
|
|
194
|
+
run_cleanup_job("aws_import_ecr_cleanup.json", neo4j_session, common_job_parameters)
|
|
159
195
|
|
|
160
196
|
|
|
161
197
|
def _get_image_data(
|
|
@@ -163,15 +199,21 @@ def _get_image_data(
|
|
|
163
199
|
region: str,
|
|
164
200
|
repositories: List[Dict[str, Any]],
|
|
165
201
|
) -> Dict[str, Any]:
|
|
166
|
-
|
|
202
|
+
"""
|
|
167
203
|
Given a list of repositories, get the image data for each repository,
|
|
168
204
|
return as a mapping from repositoryUri to image object
|
|
169
|
-
|
|
205
|
+
"""
|
|
170
206
|
image_data = {}
|
|
171
207
|
|
|
172
208
|
async def async_get_images(repo: Dict[str, Any]) -> None:
|
|
173
|
-
repo_image_obj = await to_asynchronous(
|
|
174
|
-
|
|
209
|
+
repo_image_obj = await to_asynchronous(
|
|
210
|
+
get_ecr_repository_images,
|
|
211
|
+
boto3_session,
|
|
212
|
+
region,
|
|
213
|
+
repo["repositoryName"],
|
|
214
|
+
)
|
|
215
|
+
image_data[repo["repositoryUri"]] = repo_image_obj
|
|
216
|
+
|
|
175
217
|
to_synchronous(*[async_get_images(repo) for repo in repositories])
|
|
176
218
|
|
|
177
219
|
return image_data
|
|
@@ -179,15 +221,29 @@ def _get_image_data(
|
|
|
179
221
|
|
|
180
222
|
@timeit
|
|
181
223
|
def sync(
|
|
182
|
-
neo4j_session: neo4j.Session,
|
|
183
|
-
|
|
224
|
+
neo4j_session: neo4j.Session,
|
|
225
|
+
boto3_session: boto3.session.Session,
|
|
226
|
+
regions: List[str],
|
|
227
|
+
current_aws_account_id: str,
|
|
228
|
+
update_tag: int,
|
|
229
|
+
common_job_parameters: Dict,
|
|
184
230
|
) -> None:
|
|
185
231
|
for region in regions:
|
|
186
|
-
logger.info(
|
|
232
|
+
logger.info(
|
|
233
|
+
"Syncing ECR for region '%s' in account '%s'.",
|
|
234
|
+
region,
|
|
235
|
+
current_aws_account_id,
|
|
236
|
+
)
|
|
187
237
|
image_data = {}
|
|
188
238
|
repositories = get_ecr_repositories(boto3_session, region)
|
|
189
239
|
image_data = _get_image_data(boto3_session, region, repositories)
|
|
190
|
-
load_ecr_repositories(
|
|
240
|
+
load_ecr_repositories(
|
|
241
|
+
neo4j_session,
|
|
242
|
+
repositories,
|
|
243
|
+
region,
|
|
244
|
+
current_aws_account_id,
|
|
245
|
+
update_tag,
|
|
246
|
+
)
|
|
191
247
|
repo_images_list = transform_ecr_repository_images(image_data)
|
|
192
248
|
load_ecr_repository_images(neo4j_session, repo_images_list, region, update_tag)
|
|
193
249
|
cleanup(neo4j_session, common_job_parameters)
|