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
|
@@ -19,7 +19,11 @@ logger = logging.getLogger(__name__)
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@timeit
|
|
22
|
-
def get_images_in_use(
|
|
22
|
+
def get_images_in_use(
|
|
23
|
+
neo4j_session: neo4j.Session,
|
|
24
|
+
region: str,
|
|
25
|
+
current_aws_account_id: str,
|
|
26
|
+
) -> List[str]:
|
|
23
27
|
get_images_query = """
|
|
24
28
|
CALL {
|
|
25
29
|
MATCH (:AWSAccount{id: $AWS_ACCOUNT_ID})-[:RESOURCE]->(i:EC2Instance)
|
|
@@ -37,8 +41,10 @@ def get_images_in_use(neo4j_session: neo4j.Session, region: str, current_aws_acc
|
|
|
37
41
|
RETURN DISTINCT image;
|
|
38
42
|
"""
|
|
39
43
|
result = read_list_of_values_tx(
|
|
40
|
-
neo4j_session,
|
|
41
|
-
|
|
44
|
+
neo4j_session,
|
|
45
|
+
get_images_query,
|
|
46
|
+
AWS_ACCOUNT_ID=current_aws_account_id,
|
|
47
|
+
Region=region,
|
|
42
48
|
)
|
|
43
49
|
images = [str(image) for image in result]
|
|
44
50
|
return images
|
|
@@ -46,40 +52,52 @@ def get_images_in_use(neo4j_session: neo4j.Session, region: str, current_aws_acc
|
|
|
46
52
|
|
|
47
53
|
@timeit
|
|
48
54
|
@aws_handle_regions
|
|
49
|
-
def get_images(
|
|
50
|
-
|
|
55
|
+
def get_images(
|
|
56
|
+
boto3_session: boto3.session.Session,
|
|
57
|
+
region: str,
|
|
58
|
+
image_ids: List[str],
|
|
59
|
+
) -> List[Dict]:
|
|
60
|
+
client = boto3_session.client(
|
|
61
|
+
"ec2",
|
|
62
|
+
region_name=region,
|
|
63
|
+
config=get_botocore_config(),
|
|
64
|
+
)
|
|
51
65
|
images = []
|
|
52
66
|
self_images = []
|
|
53
67
|
try:
|
|
54
|
-
self_images = client.describe_images(Owners=[
|
|
68
|
+
self_images = client.describe_images(Owners=["self"])["Images"]
|
|
55
69
|
except ClientError as e:
|
|
56
|
-
logger.warning(
|
|
70
|
+
logger.warning(
|
|
71
|
+
f"Failed retrieve self owned images for region - {region}. Error - {e}"
|
|
72
|
+
)
|
|
57
73
|
images.extend(self_images)
|
|
58
74
|
if image_ids:
|
|
59
|
-
self_image_ids = {image[
|
|
75
|
+
self_image_ids = {image["ImageId"] for image in images}
|
|
60
76
|
# Go one by one to avoid losing all images if one fails
|
|
61
77
|
for image in image_ids:
|
|
62
78
|
if image in self_image_ids:
|
|
63
79
|
continue
|
|
64
80
|
try:
|
|
65
|
-
public_images = client.describe_images(ImageIds=[image])[
|
|
81
|
+
public_images = client.describe_images(ImageIds=[image])["Images"]
|
|
66
82
|
images.extend(public_images)
|
|
67
83
|
except ClientError as e:
|
|
68
|
-
logger.warning(
|
|
84
|
+
logger.warning(
|
|
85
|
+
f"Failed retrieve image id {image} for region - {region}. Error - {e}"
|
|
86
|
+
)
|
|
69
87
|
return images
|
|
70
88
|
|
|
71
89
|
|
|
72
90
|
@timeit
|
|
73
91
|
def load_images(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
92
|
+
neo4j_session: neo4j.Session,
|
|
93
|
+
data: List[Dict[str, Any]],
|
|
94
|
+
region: str,
|
|
95
|
+
current_aws_account_id: str,
|
|
96
|
+
update_tag: int,
|
|
79
97
|
) -> None:
|
|
80
98
|
# AMI IDs are unique to each AWS Region. Hence we make an 'ID' string that is a combo of ImageId and region
|
|
81
99
|
for image in data:
|
|
82
|
-
image[
|
|
100
|
+
image["ID"] = image["ImageId"] + "|" + region
|
|
83
101
|
load(
|
|
84
102
|
neo4j_session,
|
|
85
103
|
EC2ImageSchema(),
|
|
@@ -91,18 +109,29 @@ def load_images(
|
|
|
91
109
|
|
|
92
110
|
|
|
93
111
|
@timeit
|
|
94
|
-
def cleanup_images(
|
|
112
|
+
def cleanup_images(
|
|
113
|
+
neo4j_session: neo4j.Session,
|
|
114
|
+
common_job_parameters: Dict[str, Any],
|
|
115
|
+
) -> None:
|
|
95
116
|
cleanup_job = GraphJob.from_node_schema(EC2ImageSchema(), common_job_parameters)
|
|
96
117
|
cleanup_job.run(neo4j_session)
|
|
97
118
|
|
|
98
119
|
|
|
99
120
|
@timeit
|
|
100
121
|
def sync_ec2_images(
|
|
101
|
-
|
|
102
|
-
|
|
122
|
+
neo4j_session: neo4j.Session,
|
|
123
|
+
boto3_session: boto3.session.Session,
|
|
124
|
+
regions: List[str],
|
|
125
|
+
current_aws_account_id: str,
|
|
126
|
+
update_tag: int,
|
|
127
|
+
common_job_parameters: Dict,
|
|
103
128
|
) -> None:
|
|
104
129
|
for region in regions:
|
|
105
|
-
logger.info(
|
|
130
|
+
logger.info(
|
|
131
|
+
"Syncing images for region '%s' in account '%s'.",
|
|
132
|
+
region,
|
|
133
|
+
current_aws_account_id,
|
|
134
|
+
)
|
|
106
135
|
images_in_use = get_images_in_use(neo4j_session, region, current_aws_account_id)
|
|
107
136
|
data = get_images(boto3_session, region, images_in_use)
|
|
108
137
|
load_images(neo4j_session, data, region, current_aws_account_id, update_tag)
|
|
@@ -11,12 +11,18 @@ import neo4j
|
|
|
11
11
|
from cartography.client.core.tx import load
|
|
12
12
|
from cartography.graph.job import GraphJob
|
|
13
13
|
from cartography.intel.aws.ec2.util import get_botocore_config
|
|
14
|
-
from cartography.models.aws.ec2.auto_scaling_groups import
|
|
14
|
+
from cartography.models.aws.ec2.auto_scaling_groups import (
|
|
15
|
+
EC2InstanceAutoScalingGroupSchema,
|
|
16
|
+
)
|
|
15
17
|
from cartography.models.aws.ec2.instances import EC2InstanceSchema
|
|
16
18
|
from cartography.models.aws.ec2.keypair_instance import EC2KeyPairInstanceSchema
|
|
17
|
-
from cartography.models.aws.ec2.networkinterface_instance import
|
|
19
|
+
from cartography.models.aws.ec2.networkinterface_instance import (
|
|
20
|
+
EC2NetworkInterfaceInstanceSchema,
|
|
21
|
+
)
|
|
18
22
|
from cartography.models.aws.ec2.reservations import EC2ReservationSchema
|
|
19
|
-
from cartography.models.aws.ec2.securitygroup_instance import
|
|
23
|
+
from cartography.models.aws.ec2.securitygroup_instance import (
|
|
24
|
+
EC2SecurityGroupInstanceSchema,
|
|
25
|
+
)
|
|
20
26
|
from cartography.models.aws.ec2.subnet_instance import EC2SubnetInstanceSchema
|
|
21
27
|
from cartography.models.aws.ec2.volumes import EBSVolumeInstanceSchema
|
|
22
28
|
from cartography.util import aws_handle_regions
|
|
@@ -25,7 +31,8 @@ from cartography.util import timeit
|
|
|
25
31
|
logger = logging.getLogger(__name__)
|
|
26
32
|
|
|
27
33
|
Ec2Data = namedtuple(
|
|
28
|
-
|
|
34
|
+
"Ec2Data",
|
|
35
|
+
[
|
|
29
36
|
"reservation_list",
|
|
30
37
|
"instance_list",
|
|
31
38
|
"subnet_list",
|
|
@@ -40,15 +47,23 @@ Ec2Data = namedtuple(
|
|
|
40
47
|
@timeit
|
|
41
48
|
@aws_handle_regions
|
|
42
49
|
def get_ec2_instances(boto3_session: boto3.session.Session, region: str) -> List[Dict]:
|
|
43
|
-
client = boto3_session.client(
|
|
44
|
-
|
|
50
|
+
client = boto3_session.client(
|
|
51
|
+
"ec2",
|
|
52
|
+
region_name=region,
|
|
53
|
+
config=get_botocore_config(),
|
|
54
|
+
)
|
|
55
|
+
paginator = client.get_paginator("describe_instances")
|
|
45
56
|
reservations: List[Dict[str, Any]] = []
|
|
46
57
|
for page in paginator.paginate():
|
|
47
|
-
reservations.extend(page[
|
|
58
|
+
reservations.extend(page["Reservations"])
|
|
48
59
|
return reservations
|
|
49
60
|
|
|
50
61
|
|
|
51
|
-
def transform_ec2_instances(
|
|
62
|
+
def transform_ec2_instances(
|
|
63
|
+
reservations: List[Dict[str, Any]],
|
|
64
|
+
region: str,
|
|
65
|
+
current_aws_account_id: str,
|
|
66
|
+
) -> Ec2Data:
|
|
52
67
|
reservation_list = []
|
|
53
68
|
instance_list = []
|
|
54
69
|
subnet_list = []
|
|
@@ -58,92 +73,119 @@ def transform_ec2_instances(reservations: List[Dict[str, Any]], region: str, cur
|
|
|
58
73
|
instance_ebs_volumes_list = []
|
|
59
74
|
|
|
60
75
|
for reservation in reservations:
|
|
61
|
-
reservation_id = reservation[
|
|
62
|
-
reservation_list.append(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
reservation_id = reservation["ReservationId"]
|
|
77
|
+
reservation_list.append(
|
|
78
|
+
{
|
|
79
|
+
"RequesterId": reservation.get("RequesterId"),
|
|
80
|
+
"ReservationId": reservation["ReservationId"],
|
|
81
|
+
"OwnerId": reservation["OwnerId"],
|
|
82
|
+
},
|
|
83
|
+
)
|
|
84
|
+
for instance in reservation["Instances"]:
|
|
85
|
+
instance_id = instance["InstanceId"]
|
|
69
86
|
launch_time = instance.get("LaunchTime")
|
|
70
|
-
launch_time_unix =
|
|
87
|
+
launch_time_unix = (
|
|
88
|
+
str(time.mktime(launch_time.timetuple())) if launch_time else None
|
|
89
|
+
)
|
|
71
90
|
instance_list.append(
|
|
72
91
|
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
"InstanceId": instance_id,
|
|
93
|
+
"ReservationId": reservation_id,
|
|
94
|
+
"PublicDnsName": instance.get("PublicDnsName"),
|
|
95
|
+
"PublicIpAddress": instance.get("PublicIpAddress"),
|
|
96
|
+
"PrivateIpAddress": instance.get("PrivateIpAddress"),
|
|
97
|
+
"ImageId": instance.get("ImageId"),
|
|
98
|
+
"InstanceType": instance.get("InstanceType"),
|
|
99
|
+
"IamInstanceProfile": instance.get("IamInstanceProfile", {}).get(
|
|
100
|
+
"Arn",
|
|
101
|
+
),
|
|
102
|
+
"MonitoringState": instance.get("Monitoring", {}).get("State"),
|
|
103
|
+
"LaunchTime": instance.get("LaunchTime"),
|
|
104
|
+
"LaunchTimeUnix": launch_time_unix,
|
|
105
|
+
"State": instance.get("State", {}).get("Name"),
|
|
106
|
+
"AvailabilityZone": instance.get("Placement", {}).get(
|
|
107
|
+
"AvailabilityZone",
|
|
108
|
+
),
|
|
109
|
+
"Tenancy": instance.get("Placement", {}).get("Tenancy"),
|
|
110
|
+
"HostResourceGroupArn": instance.get("Placement", {}).get(
|
|
111
|
+
"HostResourceGroupArn",
|
|
112
|
+
),
|
|
113
|
+
"Platform": instance.get("Platform"),
|
|
114
|
+
"Architecture": instance.get("Architecture"),
|
|
115
|
+
"EbsOptimized": instance.get("EbsOptimized"),
|
|
116
|
+
"BootMode": instance.get("BootMode"),
|
|
117
|
+
"InstanceLifecycle": instance.get("InstanceLifecycle"),
|
|
118
|
+
"HibernationOptions": instance.get("HibernationOptions", {}).get(
|
|
119
|
+
"Configured",
|
|
120
|
+
),
|
|
94
121
|
},
|
|
95
122
|
)
|
|
96
123
|
|
|
97
|
-
subnet_id = instance.get(
|
|
124
|
+
subnet_id = instance.get("SubnetId")
|
|
98
125
|
if subnet_id:
|
|
99
126
|
subnet_list.append(
|
|
100
127
|
{
|
|
101
|
-
|
|
102
|
-
|
|
128
|
+
"SubnetId": subnet_id,
|
|
129
|
+
"InstanceId": instance_id,
|
|
103
130
|
},
|
|
104
131
|
)
|
|
105
132
|
|
|
106
133
|
if instance.get("KeyName"):
|
|
107
134
|
key_name = instance["KeyName"]
|
|
108
|
-
key_pair_arn =
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
135
|
+
key_pair_arn = (
|
|
136
|
+
f"arn:aws:ec2:{region}:{current_aws_account_id}:key-pair/{key_name}"
|
|
137
|
+
)
|
|
138
|
+
keypair_list.append(
|
|
139
|
+
{
|
|
140
|
+
"KeyPairArn": key_pair_arn,
|
|
141
|
+
"KeyName": key_name,
|
|
142
|
+
"InstanceId": instance_id,
|
|
143
|
+
},
|
|
144
|
+
)
|
|
114
145
|
|
|
115
146
|
if instance.get("SecurityGroups"):
|
|
116
147
|
for group in instance["SecurityGroups"]:
|
|
117
148
|
sg_list.append(
|
|
118
149
|
{
|
|
119
|
-
|
|
120
|
-
|
|
150
|
+
"GroupId": group["GroupId"],
|
|
151
|
+
"InstanceId": instance_id,
|
|
121
152
|
},
|
|
122
153
|
)
|
|
123
154
|
|
|
124
|
-
for network_interface in instance[
|
|
125
|
-
for security_group in network_interface.get(
|
|
126
|
-
network_interface_list.append(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
155
|
+
for network_interface in instance["NetworkInterfaces"]:
|
|
156
|
+
for security_group in network_interface.get("Groups", []):
|
|
157
|
+
network_interface_list.append(
|
|
158
|
+
{
|
|
159
|
+
"NetworkInterfaceId": network_interface[
|
|
160
|
+
"NetworkInterfaceId"
|
|
161
|
+
],
|
|
162
|
+
"Status": network_interface["Status"],
|
|
163
|
+
"MacAddress": network_interface["MacAddress"],
|
|
164
|
+
"Description": network_interface["Description"],
|
|
165
|
+
"PrivateDnsName": network_interface.get("PrivateDnsName"),
|
|
166
|
+
"PrivateIpAddress": network_interface["PrivateIpAddress"],
|
|
167
|
+
"InstanceId": instance_id,
|
|
168
|
+
"SubnetId": subnet_id,
|
|
169
|
+
"GroupId": security_group["GroupId"],
|
|
170
|
+
},
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
if (
|
|
174
|
+
"BlockDeviceMappings" in instance
|
|
175
|
+
and len(instance["BlockDeviceMappings"]) > 0
|
|
176
|
+
):
|
|
177
|
+
for mapping in instance["BlockDeviceMappings"]:
|
|
178
|
+
if "VolumeId" in mapping["Ebs"]:
|
|
179
|
+
instance_ebs_volumes_list.append(
|
|
180
|
+
{
|
|
181
|
+
"InstanceId": instance_id,
|
|
182
|
+
"VolumeId": mapping["Ebs"]["VolumeId"],
|
|
183
|
+
"DeleteOnTermination": mapping["Ebs"][
|
|
184
|
+
"DeleteOnTermination"
|
|
185
|
+
],
|
|
186
|
+
# 'SnapshotId': mapping['Ebs']['SnapshotId'], # TODO check on this
|
|
187
|
+
},
|
|
188
|
+
)
|
|
147
189
|
|
|
148
190
|
return Ec2Data(
|
|
149
191
|
reservation_list=reservation_list,
|
|
@@ -158,11 +200,11 @@ def transform_ec2_instances(reservations: List[Dict[str, Any]], region: str, cur
|
|
|
158
200
|
|
|
159
201
|
@timeit
|
|
160
202
|
def load_ec2_reservations(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
203
|
+
neo4j_session: neo4j.Session,
|
|
204
|
+
reservation_list: List[Dict[str, Any]],
|
|
205
|
+
region: str,
|
|
206
|
+
current_aws_account_id: str,
|
|
207
|
+
update_tag: int,
|
|
166
208
|
) -> None:
|
|
167
209
|
load(
|
|
168
210
|
neo4j_session,
|
|
@@ -176,11 +218,11 @@ def load_ec2_reservations(
|
|
|
176
218
|
|
|
177
219
|
@timeit
|
|
178
220
|
def load_ec2_subnets(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
221
|
+
neo4j_session: neo4j.Session,
|
|
222
|
+
subnet_list: List[Dict[str, Any]],
|
|
223
|
+
region: str,
|
|
224
|
+
current_aws_account_id: str,
|
|
225
|
+
update_tag: int,
|
|
184
226
|
) -> None:
|
|
185
227
|
load(
|
|
186
228
|
neo4j_session,
|
|
@@ -194,11 +236,11 @@ def load_ec2_subnets(
|
|
|
194
236
|
|
|
195
237
|
@timeit
|
|
196
238
|
def load_ec2_keypair_instances(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
239
|
+
neo4j_session: neo4j.Session,
|
|
240
|
+
key_pair_list: List[Dict[str, Any]],
|
|
241
|
+
region: str,
|
|
242
|
+
current_aws_account_id: str,
|
|
243
|
+
update_tag: int,
|
|
202
244
|
) -> None:
|
|
203
245
|
# Load EC2 keypairs as known by describe-instances.
|
|
204
246
|
load(
|
|
@@ -213,11 +255,11 @@ def load_ec2_keypair_instances(
|
|
|
213
255
|
|
|
214
256
|
@timeit
|
|
215
257
|
def load_ec2_security_groups(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
258
|
+
neo4j_session: neo4j.Session,
|
|
259
|
+
sg_list: List[Dict[str, Any]],
|
|
260
|
+
region: str,
|
|
261
|
+
current_aws_account_id: str,
|
|
262
|
+
update_tag: int,
|
|
221
263
|
) -> None:
|
|
222
264
|
load(
|
|
223
265
|
neo4j_session,
|
|
@@ -231,11 +273,11 @@ def load_ec2_security_groups(
|
|
|
231
273
|
|
|
232
274
|
@timeit
|
|
233
275
|
def load_ec2_network_interfaces(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
276
|
+
neo4j_session: neo4j.Session,
|
|
277
|
+
network_interface_list: List[Dict[str, Any]],
|
|
278
|
+
region: str,
|
|
279
|
+
current_aws_account_id: str,
|
|
280
|
+
update_tag: int,
|
|
239
281
|
) -> None:
|
|
240
282
|
load(
|
|
241
283
|
neo4j_session,
|
|
@@ -249,11 +291,11 @@ def load_ec2_network_interfaces(
|
|
|
249
291
|
|
|
250
292
|
@timeit
|
|
251
293
|
def load_ec2_instance_nodes(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
294
|
+
neo4j_session: neo4j.Session,
|
|
295
|
+
data: List[Dict],
|
|
296
|
+
region: str,
|
|
297
|
+
current_aws_account_id: str,
|
|
298
|
+
update_tag: int,
|
|
257
299
|
) -> None:
|
|
258
300
|
load(
|
|
259
301
|
neo4j_session,
|
|
@@ -267,11 +309,11 @@ def load_ec2_instance_nodes(
|
|
|
267
309
|
|
|
268
310
|
@timeit
|
|
269
311
|
def load_ec2_instance_ebs_volumes(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
312
|
+
neo4j_session: neo4j.Session,
|
|
313
|
+
ebs_data: List[Dict[str, Any]],
|
|
314
|
+
region: str,
|
|
315
|
+
current_aws_account_id: str,
|
|
316
|
+
update_tag: int,
|
|
275
317
|
) -> None:
|
|
276
318
|
load(
|
|
277
319
|
neo4j_session,
|
|
@@ -284,46 +326,102 @@ def load_ec2_instance_ebs_volumes(
|
|
|
284
326
|
|
|
285
327
|
|
|
286
328
|
def load_ec2_instance_data(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
329
|
+
neo4j_session: neo4j.Session,
|
|
330
|
+
region: str,
|
|
331
|
+
current_aws_account_id: str,
|
|
332
|
+
update_tag: int,
|
|
333
|
+
reservation_list: List[Dict[str, Any]],
|
|
334
|
+
instance_list: List[Dict[str, Any]],
|
|
335
|
+
subnet_list: List[Dict[str, Any]],
|
|
336
|
+
sg_list: List[Dict[str, Any]],
|
|
337
|
+
key_pair_list: List[Dict[str, Any]],
|
|
338
|
+
nic_list: List[Dict[str, Any]],
|
|
339
|
+
ebs_volumes_list: List[Dict[str, Any]],
|
|
298
340
|
) -> None:
|
|
299
|
-
load_ec2_reservations(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
341
|
+
load_ec2_reservations(
|
|
342
|
+
neo4j_session,
|
|
343
|
+
reservation_list,
|
|
344
|
+
region,
|
|
345
|
+
current_aws_account_id,
|
|
346
|
+
update_tag,
|
|
347
|
+
)
|
|
348
|
+
load_ec2_instance_nodes(
|
|
349
|
+
neo4j_session,
|
|
350
|
+
instance_list,
|
|
351
|
+
region,
|
|
352
|
+
current_aws_account_id,
|
|
353
|
+
update_tag,
|
|
354
|
+
)
|
|
355
|
+
load_ec2_subnets(
|
|
356
|
+
neo4j_session,
|
|
357
|
+
subnet_list,
|
|
358
|
+
region,
|
|
359
|
+
current_aws_account_id,
|
|
360
|
+
update_tag,
|
|
361
|
+
)
|
|
362
|
+
load_ec2_security_groups(
|
|
363
|
+
neo4j_session,
|
|
364
|
+
sg_list,
|
|
365
|
+
region,
|
|
366
|
+
current_aws_account_id,
|
|
367
|
+
update_tag,
|
|
368
|
+
)
|
|
369
|
+
load_ec2_keypair_instances(
|
|
370
|
+
neo4j_session,
|
|
371
|
+
key_pair_list,
|
|
372
|
+
region,
|
|
373
|
+
current_aws_account_id,
|
|
374
|
+
update_tag,
|
|
375
|
+
)
|
|
376
|
+
load_ec2_network_interfaces(
|
|
377
|
+
neo4j_session,
|
|
378
|
+
nic_list,
|
|
379
|
+
region,
|
|
380
|
+
current_aws_account_id,
|
|
381
|
+
update_tag,
|
|
382
|
+
)
|
|
383
|
+
load_ec2_instance_ebs_volumes(
|
|
384
|
+
neo4j_session,
|
|
385
|
+
ebs_volumes_list,
|
|
386
|
+
region,
|
|
387
|
+
current_aws_account_id,
|
|
388
|
+
update_tag,
|
|
389
|
+
)
|
|
306
390
|
|
|
307
391
|
|
|
308
392
|
@timeit
|
|
309
|
-
def cleanup(
|
|
393
|
+
def cleanup(
|
|
394
|
+
neo4j_session: neo4j.Session,
|
|
395
|
+
common_job_parameters: Dict[str, Any],
|
|
396
|
+
) -> None:
|
|
310
397
|
logger.debug("Running EC2 instance cleanup")
|
|
311
|
-
GraphJob.from_node_schema(EC2ReservationSchema(), common_job_parameters).run(
|
|
312
|
-
|
|
313
|
-
|
|
398
|
+
GraphJob.from_node_schema(EC2ReservationSchema(), common_job_parameters).run(
|
|
399
|
+
neo4j_session,
|
|
400
|
+
)
|
|
401
|
+
GraphJob.from_node_schema(EC2InstanceSchema(), common_job_parameters).run(
|
|
402
|
+
neo4j_session,
|
|
403
|
+
)
|
|
404
|
+
GraphJob.from_node_schema(
|
|
405
|
+
EC2InstanceAutoScalingGroupSchema(),
|
|
406
|
+
common_job_parameters,
|
|
407
|
+
).run(neo4j_session)
|
|
314
408
|
|
|
315
409
|
|
|
316
410
|
@timeit
|
|
317
411
|
def sync_ec2_instances(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
412
|
+
neo4j_session: neo4j.Session,
|
|
413
|
+
boto3_session: boto3.session.Session,
|
|
414
|
+
regions: List[str],
|
|
415
|
+
current_aws_account_id: str,
|
|
416
|
+
update_tag: int,
|
|
417
|
+
common_job_parameters: Dict[str, Any],
|
|
324
418
|
) -> None:
|
|
325
419
|
for region in regions:
|
|
326
|
-
logger.info(
|
|
420
|
+
logger.info(
|
|
421
|
+
"Syncing EC2 instances for region '%s' in account '%s'.",
|
|
422
|
+
region,
|
|
423
|
+
current_aws_account_id,
|
|
424
|
+
)
|
|
327
425
|
reservations = get_ec2_instances(boto3_session, region)
|
|
328
426
|
ec2_data = transform_ec2_instances(reservations, region, current_aws_account_id)
|
|
329
427
|
load_ec2_instance_data(
|