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
|
@@ -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_internet_gateways(
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
def get_internet_gateways(
|
|
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_internet_gateways()["InternetGateways"]
|
|
21
29
|
|
|
22
30
|
|
|
23
31
|
@timeit
|
|
24
32
|
def load_internet_gateways(
|
|
25
|
-
neo4j_session: neo4j.Session,
|
|
26
|
-
|
|
33
|
+
neo4j_session: neo4j.Session,
|
|
34
|
+
internet_gateways: List[Dict],
|
|
35
|
+
region: str,
|
|
36
|
+
current_aws_account_id: str,
|
|
37
|
+
update_tag: int,
|
|
27
38
|
) -> None:
|
|
28
39
|
logger.info("Loading %d Internet Gateways in %s.", len(internet_gateways), region)
|
|
29
40
|
# TODO: Right now this won't work in non-AWS commercial (GovCloud, China) as partition is hardcoded
|
|
@@ -64,17 +75,35 @@ def load_internet_gateways(
|
|
|
64
75
|
@timeit
|
|
65
76
|
def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
66
77
|
logger.debug("Running Internet Gateway cleanup job.")
|
|
67
|
-
run_cleanup_job(
|
|
78
|
+
run_cleanup_job(
|
|
79
|
+
"aws_import_internet_gateways_cleanup.json",
|
|
80
|
+
neo4j_session,
|
|
81
|
+
common_job_parameters,
|
|
82
|
+
)
|
|
68
83
|
|
|
69
84
|
|
|
70
85
|
@timeit
|
|
71
86
|
def sync_internet_gateways(
|
|
72
|
-
neo4j_session: neo4j.Session,
|
|
73
|
-
|
|
87
|
+
neo4j_session: neo4j.Session,
|
|
88
|
+
boto3_session: boto3.session.Session,
|
|
89
|
+
regions: List[str],
|
|
90
|
+
current_aws_account_id: str,
|
|
91
|
+
update_tag: int,
|
|
92
|
+
common_job_parameters: Dict,
|
|
74
93
|
) -> None:
|
|
75
94
|
for region in regions:
|
|
76
|
-
logger.info(
|
|
95
|
+
logger.info(
|
|
96
|
+
"Syncing Internet Gateways for region '%s' in account '%s'.",
|
|
97
|
+
region,
|
|
98
|
+
current_aws_account_id,
|
|
99
|
+
)
|
|
77
100
|
internet_gateways = get_internet_gateways(boto3_session, region)
|
|
78
|
-
load_internet_gateways(
|
|
101
|
+
load_internet_gateways(
|
|
102
|
+
neo4j_session,
|
|
103
|
+
internet_gateways,
|
|
104
|
+
region,
|
|
105
|
+
current_aws_account_id,
|
|
106
|
+
update_tag,
|
|
107
|
+
)
|
|
79
108
|
|
|
80
109
|
cleanup(neo4j_session, common_job_parameters)
|
|
@@ -17,34 +17,43 @@ logger = logging.getLogger(__name__)
|
|
|
17
17
|
|
|
18
18
|
@timeit
|
|
19
19
|
@aws_handle_regions
|
|
20
|
-
def get_ec2_key_pairs(
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
def get_ec2_key_pairs(
|
|
21
|
+
boto3_session: boto3.session.Session,
|
|
22
|
+
region: str,
|
|
23
|
+
) -> list[dict[str, Any]]:
|
|
24
|
+
client = boto3_session.client(
|
|
25
|
+
"ec2",
|
|
26
|
+
region_name=region,
|
|
27
|
+
config=get_botocore_config(),
|
|
28
|
+
)
|
|
29
|
+
return client.describe_key_pairs()["KeyPairs"]
|
|
23
30
|
|
|
24
31
|
|
|
25
32
|
def transform_ec2_key_pairs(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
key_pairs: list[dict[str, Any]],
|
|
34
|
+
region: str,
|
|
35
|
+
current_aws_account_id: str,
|
|
29
36
|
) -> list[dict[str, Any]]:
|
|
30
37
|
transformed_key_pairs = []
|
|
31
38
|
for key_pair in key_pairs:
|
|
32
39
|
key_name = key_pair["KeyName"]
|
|
33
|
-
transformed_key_pairs.append(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
transformed_key_pairs.append(
|
|
41
|
+
{
|
|
42
|
+
"KeyPairArn": f"arn:aws:ec2:{region}:{current_aws_account_id}:key-pair/{key_name}",
|
|
43
|
+
"KeyName": key_name,
|
|
44
|
+
"KeyFingerprint": key_pair.get("KeyFingerprint"),
|
|
45
|
+
},
|
|
46
|
+
)
|
|
38
47
|
return transformed_key_pairs
|
|
39
48
|
|
|
40
49
|
|
|
41
50
|
@timeit
|
|
42
51
|
def load_ec2_key_pairs(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
neo4j_session: neo4j.Session,
|
|
53
|
+
data: list[dict[str, Any]],
|
|
54
|
+
region: str,
|
|
55
|
+
current_aws_account_id: str,
|
|
56
|
+
update_tag: int,
|
|
48
57
|
) -> None:
|
|
49
58
|
# Load EC2 keypairs as known by describe-key-pairs
|
|
50
59
|
logger.info(f"Loading {len(data)} EC2 keypairs for region '{region}' into graph.")
|
|
@@ -59,8 +68,13 @@ def load_ec2_key_pairs(
|
|
|
59
68
|
|
|
60
69
|
|
|
61
70
|
@timeit
|
|
62
|
-
def cleanup_ec2_key_pairs(
|
|
63
|
-
|
|
71
|
+
def cleanup_ec2_key_pairs(
|
|
72
|
+
neo4j_session: neo4j.Session,
|
|
73
|
+
common_job_parameters: Dict,
|
|
74
|
+
) -> None:
|
|
75
|
+
GraphJob.from_node_schema(EC2KeyPairSchema(), common_job_parameters).run(
|
|
76
|
+
neo4j_session,
|
|
77
|
+
)
|
|
64
78
|
|
|
65
79
|
|
|
66
80
|
@timeit
|
|
@@ -73,8 +87,18 @@ def sync_ec2_key_pairs(
|
|
|
73
87
|
common_job_parameters: dict[str, Any],
|
|
74
88
|
) -> None:
|
|
75
89
|
for region in regions:
|
|
76
|
-
logger.info(
|
|
90
|
+
logger.info(
|
|
91
|
+
"Syncing EC2 key pairs for region '%s' in account '%s'.",
|
|
92
|
+
region,
|
|
93
|
+
current_aws_account_id,
|
|
94
|
+
)
|
|
77
95
|
data = get_ec2_key_pairs(boto3_session, region)
|
|
78
96
|
transformed_data = transform_ec2_key_pairs(data, region, current_aws_account_id)
|
|
79
|
-
load_ec2_key_pairs(
|
|
97
|
+
load_ec2_key_pairs(
|
|
98
|
+
neo4j_session,
|
|
99
|
+
transformed_data,
|
|
100
|
+
region,
|
|
101
|
+
current_aws_account_id,
|
|
102
|
+
update_tag,
|
|
103
|
+
)
|
|
80
104
|
cleanup_ec2_key_pairs(neo4j_session, common_job_parameters)
|
|
@@ -5,14 +5,17 @@ import boto3
|
|
|
5
5
|
import botocore
|
|
6
6
|
import neo4j
|
|
7
7
|
|
|
8
|
-
from .util import get_botocore_config
|
|
9
8
|
from cartography.client.core.tx import load
|
|
10
9
|
from cartography.graph.job import GraphJob
|
|
11
|
-
from cartography.models.aws.ec2.launch_template_versions import
|
|
10
|
+
from cartography.models.aws.ec2.launch_template_versions import (
|
|
11
|
+
LaunchTemplateVersionSchema,
|
|
12
|
+
)
|
|
12
13
|
from cartography.models.aws.ec2.launch_templates import LaunchTemplateSchema
|
|
13
14
|
from cartography.util import aws_handle_regions
|
|
14
15
|
from cartography.util import timeit
|
|
15
16
|
|
|
17
|
+
from .util import get_botocore_config
|
|
18
|
+
|
|
16
19
|
logger = logging.getLogger(__name__)
|
|
17
20
|
|
|
18
21
|
|
|
@@ -22,11 +25,13 @@ def get_launch_templates(
|
|
|
22
25
|
boto3_session: boto3.session.Session,
|
|
23
26
|
region: str,
|
|
24
27
|
) -> list[dict[str, Any]]:
|
|
25
|
-
client = boto3_session.client(
|
|
26
|
-
|
|
28
|
+
client = boto3_session.client(
|
|
29
|
+
"ec2", region_name=region, config=get_botocore_config()
|
|
30
|
+
)
|
|
31
|
+
paginator = client.get_paginator("describe_launch_templates")
|
|
27
32
|
templates: list[dict[str, Any]] = []
|
|
28
33
|
for page in paginator.paginate():
|
|
29
|
-
paginated_templates = page[
|
|
34
|
+
paginated_templates = page["LaunchTemplates"]
|
|
30
35
|
templates.extend(paginated_templates)
|
|
31
36
|
return templates
|
|
32
37
|
|
|
@@ -40,8 +45,10 @@ def get_launch_template_versions(
|
|
|
40
45
|
) -> list[dict[str, Any]]:
|
|
41
46
|
template_versions: list[dict[str, Any]] = []
|
|
42
47
|
for template in launch_templates:
|
|
43
|
-
launch_template_id = template[
|
|
44
|
-
versions = get_launch_template_versions_by_template(
|
|
48
|
+
launch_template_id = template["LaunchTemplateId"]
|
|
49
|
+
versions = get_launch_template_versions_by_template(
|
|
50
|
+
boto3_session, launch_template_id, region
|
|
51
|
+
)
|
|
45
52
|
template_versions.extend(versions)
|
|
46
53
|
|
|
47
54
|
return template_versions
|
|
@@ -50,46 +57,54 @@ def get_launch_template_versions(
|
|
|
50
57
|
@timeit
|
|
51
58
|
@aws_handle_regions
|
|
52
59
|
def get_launch_template_versions_by_template(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
boto3_session: boto3.session.Session,
|
|
61
|
+
launch_template_id: str,
|
|
62
|
+
region: str,
|
|
56
63
|
) -> list[dict[str, Any]]:
|
|
57
|
-
client = boto3_session.client(
|
|
58
|
-
|
|
64
|
+
client = boto3_session.client(
|
|
65
|
+
"ec2", region_name=region, config=get_botocore_config()
|
|
66
|
+
)
|
|
67
|
+
v_paginator = client.get_paginator("describe_launch_template_versions")
|
|
59
68
|
template_versions = []
|
|
60
69
|
try:
|
|
61
70
|
for versions in v_paginator.paginate(LaunchTemplateId=launch_template_id):
|
|
62
|
-
template_versions.extend(versions[
|
|
71
|
+
template_versions.extend(versions["LaunchTemplateVersions"])
|
|
63
72
|
except botocore.exceptions.ClientError as e:
|
|
64
|
-
error_code = e.response[
|
|
65
|
-
if error_code ==
|
|
66
|
-
logger.warning(
|
|
73
|
+
error_code = e.response["Error"]["Code"]
|
|
74
|
+
if error_code == "InvalidLaunchTemplateId.NotFound":
|
|
75
|
+
logger.warning(
|
|
76
|
+
"Launch template %s no longer exists in region %s",
|
|
77
|
+
launch_template_id,
|
|
78
|
+
region,
|
|
79
|
+
)
|
|
67
80
|
else:
|
|
68
81
|
raise
|
|
69
82
|
return template_versions
|
|
70
83
|
|
|
71
84
|
|
|
72
|
-
def transform_launch_templates(
|
|
73
|
-
|
|
85
|
+
def transform_launch_templates(
|
|
86
|
+
templates: list[dict[str, Any]], versions: list[dict[str, Any]]
|
|
87
|
+
) -> list[dict[str, Any]]:
|
|
88
|
+
valid_template_ids = {v["LaunchTemplateId"] for v in versions}
|
|
74
89
|
result: list[dict[str, Any]] = []
|
|
75
90
|
for template in templates:
|
|
76
|
-
if template[
|
|
91
|
+
if template["LaunchTemplateId"] not in valid_template_ids:
|
|
77
92
|
continue
|
|
78
93
|
|
|
79
94
|
current = template.copy()
|
|
80
95
|
# Convert CreateTime to timestamp string
|
|
81
|
-
current[
|
|
96
|
+
current["CreateTime"] = str(int(current["CreateTime"].timestamp()))
|
|
82
97
|
result.append(current)
|
|
83
98
|
return result
|
|
84
99
|
|
|
85
100
|
|
|
86
101
|
@timeit
|
|
87
102
|
def load_launch_templates(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
103
|
+
neo4j_session: neo4j.Session,
|
|
104
|
+
data: list[dict[str, Any]],
|
|
105
|
+
region: str,
|
|
106
|
+
current_aws_account_id: str,
|
|
107
|
+
update_tag: int,
|
|
93
108
|
) -> None:
|
|
94
109
|
load(
|
|
95
110
|
neo4j_session,
|
|
@@ -101,41 +116,45 @@ def load_launch_templates(
|
|
|
101
116
|
)
|
|
102
117
|
|
|
103
118
|
|
|
104
|
-
def transform_launch_template_versions(
|
|
119
|
+
def transform_launch_template_versions(
|
|
120
|
+
versions: list[dict[str, Any]],
|
|
121
|
+
) -> list[dict[str, Any]]:
|
|
105
122
|
result: list[dict[str, Any]] = []
|
|
106
123
|
for version in versions:
|
|
107
124
|
current = version.copy()
|
|
108
125
|
|
|
109
126
|
# Reformat some fields
|
|
110
|
-
current[
|
|
111
|
-
current[
|
|
127
|
+
current["Id"] = f"{version['LaunchTemplateId']}-{version['VersionNumber']}"
|
|
128
|
+
current["CreateTime"] = str(int(version["CreateTime"].timestamp()))
|
|
112
129
|
|
|
113
130
|
# Handle the nested object returned from boto
|
|
114
|
-
ltd = version[
|
|
115
|
-
current[
|
|
116
|
-
current[
|
|
117
|
-
current[
|
|
118
|
-
current[
|
|
119
|
-
current[
|
|
120
|
-
current[
|
|
121
|
-
current[
|
|
122
|
-
current[
|
|
123
|
-
current[
|
|
124
|
-
current[
|
|
125
|
-
current[
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
ltd = version["LaunchTemplateData"]
|
|
132
|
+
current["KernelId"] = ltd.get("KernelId")
|
|
133
|
+
current["EbsOptimized"] = ltd.get("EbsOptimized")
|
|
134
|
+
current["IamInstanceProfileArn"] = ltd.get("IamInstanceProfileArn")
|
|
135
|
+
current["IamInstanceProfileName"] = ltd.get("IamInstanceProfileName")
|
|
136
|
+
current["ImageId"] = ltd.get("ImageId")
|
|
137
|
+
current["InstanceType"] = ltd.get("InstanceType")
|
|
138
|
+
current["KeyName"] = ltd.get("KeyName")
|
|
139
|
+
current["MonitoringEnabled"] = ltd.get("MonitoringEnabled")
|
|
140
|
+
current["RamdiskId"] = ltd.get("RamdiskId")
|
|
141
|
+
current["DisableApiTermination"] = ltd.get("DisableApiTermination")
|
|
142
|
+
current["InstanceInitiatedShutDownBehavior"] = ltd.get(
|
|
143
|
+
"InstanceInitiatedShutDownBehavior",
|
|
144
|
+
)
|
|
145
|
+
current["SecurityGroupIds"] = ltd.get("SecurityGroupIds")
|
|
146
|
+
current["SecurityGroups"] = ltd.get("SecurityGroups")
|
|
128
147
|
result.append(current)
|
|
129
148
|
return result
|
|
130
149
|
|
|
131
150
|
|
|
132
151
|
@timeit
|
|
133
152
|
def load_launch_template_versions(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
153
|
+
neo4j_session: neo4j.Session,
|
|
154
|
+
data: list[dict[str, Any]],
|
|
155
|
+
region: str,
|
|
156
|
+
current_aws_account_id: str,
|
|
157
|
+
update_tag: int,
|
|
139
158
|
) -> None:
|
|
140
159
|
load(
|
|
141
160
|
neo4j_session,
|
|
@@ -148,35 +167,58 @@ def load_launch_template_versions(
|
|
|
148
167
|
|
|
149
168
|
|
|
150
169
|
@timeit
|
|
151
|
-
def cleanup(
|
|
170
|
+
def cleanup(
|
|
171
|
+
neo4j_session: neo4j.Session,
|
|
172
|
+
common_job_parameters: dict[str, Any],
|
|
173
|
+
) -> None:
|
|
152
174
|
logger.info("Running launch template cleanup job.")
|
|
153
|
-
cleanup_job = GraphJob.from_node_schema(
|
|
175
|
+
cleanup_job = GraphJob.from_node_schema(
|
|
176
|
+
LaunchTemplateSchema(),
|
|
177
|
+
common_job_parameters,
|
|
178
|
+
)
|
|
154
179
|
cleanup_job.run(neo4j_session)
|
|
155
180
|
|
|
156
|
-
cleanup_job = GraphJob.from_node_schema(
|
|
181
|
+
cleanup_job = GraphJob.from_node_schema(
|
|
182
|
+
LaunchTemplateVersionSchema(),
|
|
183
|
+
common_job_parameters,
|
|
184
|
+
)
|
|
157
185
|
cleanup_job.run(neo4j_session)
|
|
158
186
|
|
|
159
187
|
|
|
160
188
|
@timeit
|
|
161
189
|
def sync_ec2_launch_templates(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
190
|
+
neo4j_session: neo4j.Session,
|
|
191
|
+
boto3_session: boto3.session.Session,
|
|
192
|
+
regions: list[str],
|
|
193
|
+
current_aws_account_id: str,
|
|
194
|
+
update_tag: int,
|
|
195
|
+
common_job_parameters: dict[str, Any],
|
|
168
196
|
) -> None:
|
|
169
197
|
for region in regions:
|
|
170
|
-
logger.info(
|
|
198
|
+
logger.info(
|
|
199
|
+
f"Syncing launch templates for region '{region}' in account '{current_aws_account_id}'."
|
|
200
|
+
)
|
|
171
201
|
templates = get_launch_templates(boto3_session, region)
|
|
172
202
|
versions = get_launch_template_versions(boto3_session, region, templates)
|
|
173
203
|
|
|
174
204
|
# Transform and load the templates that have versions
|
|
175
205
|
transformed_templates = transform_launch_templates(templates, versions)
|
|
176
|
-
load_launch_templates(
|
|
206
|
+
load_launch_templates(
|
|
207
|
+
neo4j_session,
|
|
208
|
+
transformed_templates,
|
|
209
|
+
region,
|
|
210
|
+
current_aws_account_id,
|
|
211
|
+
update_tag,
|
|
212
|
+
)
|
|
177
213
|
|
|
178
214
|
# Transform and load the versions
|
|
179
215
|
transformed_versions = transform_launch_template_versions(versions)
|
|
180
|
-
load_launch_template_versions(
|
|
216
|
+
load_launch_template_versions(
|
|
217
|
+
neo4j_session,
|
|
218
|
+
transformed_versions,
|
|
219
|
+
region,
|
|
220
|
+
current_aws_account_id,
|
|
221
|
+
update_tag,
|
|
222
|
+
)
|
|
181
223
|
|
|
182
224
|
cleanup(neo4j_session, common_job_parameters)
|