cartography 0.104.0rc2__py3-none-any.whl → 0.123.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.
- cartography/_version.py +16 -3
- cartography/cli.py +466 -5
- cartography/client/aws/__init__.py +19 -0
- cartography/client/aws/ecr.py +51 -0
- cartography/client/core/tx.py +357 -8
- cartography/config.py +153 -0
- cartography/data/azure_permission_relationships.yaml +20 -0
- cartography/data/gcp_permission_relationships.yaml +21 -0
- cartography/data/indexes.cypher +0 -186
- cartography/data/jobs/analysis/aws_ec2_keypair_analysis.json +2 -2
- cartography/data/jobs/analysis/keycloak_inheritance.json +30 -0
- cartography/data/jobs/cleanup/gcp_compute_vpc_cleanup.json +0 -12
- cartography/data/jobs/cleanup/github_repos_cleanup.json +2 -0
- cartography/driftdetect/cli.py +3 -2
- cartography/graph/cleanupbuilder.py +198 -41
- cartography/graph/job.py +54 -6
- cartography/graph/querybuilder.py +528 -27
- cartography/graph/statement.py +5 -1
- cartography/intel/airbyte/__init__.py +105 -0
- cartography/intel/airbyte/connections.py +120 -0
- cartography/intel/airbyte/destinations.py +81 -0
- cartography/intel/airbyte/organizations.py +59 -0
- cartography/intel/airbyte/sources.py +78 -0
- cartography/intel/airbyte/tags.py +64 -0
- cartography/intel/airbyte/users.py +106 -0
- cartography/intel/airbyte/util.py +122 -0
- cartography/intel/airbyte/workspaces.py +63 -0
- cartography/intel/aws/__init__.py +24 -9
- cartography/intel/aws/acm.py +124 -0
- cartography/intel/aws/apigateway.py +253 -22
- cartography/intel/aws/apigatewayv2.py +116 -0
- cartography/intel/aws/cloudtrail.py +17 -39
- cartography/intel/aws/cloudtrail_management_events.py +962 -0
- cartography/intel/aws/cloudwatch.py +150 -4
- cartography/intel/aws/codebuild.py +132 -0
- cartography/intel/aws/cognito.py +201 -0
- cartography/intel/aws/config.py +7 -3
- cartography/intel/aws/ec2/elastic_ip_addresses.py +3 -1
- cartography/intel/aws/ec2/instances.py +25 -1
- cartography/intel/aws/ec2/internet_gateways.py +4 -2
- cartography/intel/aws/ec2/load_balancer_v2s.py +11 -5
- cartography/intel/aws/ec2/network_interfaces.py +5 -1
- cartography/intel/aws/ec2/reserved_instances.py +3 -1
- cartography/intel/aws/ec2/security_groups.py +140 -122
- cartography/intel/aws/ec2/snapshots.py +47 -84
- cartography/intel/aws/ec2/subnets.py +37 -63
- cartography/intel/aws/ec2/tgw.py +11 -5
- cartography/intel/aws/ec2/volumes.py +1 -1
- cartography/intel/aws/ec2/vpc.py +140 -124
- cartography/intel/aws/ec2/vpc_peerings.py +262 -125
- cartography/intel/aws/ecr.py +269 -98
- cartography/intel/aws/ecr_image_layers.py +923 -0
- cartography/intel/aws/ecs.py +251 -380
- cartography/intel/aws/efs.py +179 -11
- cartography/intel/aws/elasticache.py +102 -79
- cartography/intel/aws/elasticsearch.py +13 -4
- cartography/intel/aws/eventbridge.py +164 -0
- cartography/intel/aws/glue.py +181 -0
- cartography/intel/aws/guardduty.py +443 -0
- cartography/intel/aws/iam.py +750 -493
- cartography/intel/aws/identitycenter.py +605 -83
- cartography/intel/aws/inspector.py +221 -105
- cartography/intel/aws/kms.py +173 -201
- cartography/intel/aws/lambda_function.py +272 -189
- cartography/intel/aws/organizations.py +10 -9
- cartography/intel/aws/permission_relationships.py +10 -20
- cartography/intel/aws/rds.py +337 -446
- cartography/intel/aws/redshift.py +9 -4
- cartography/intel/aws/resourcegroupstaggingapi.py +78 -19
- cartography/intel/aws/resources.py +18 -0
- cartography/intel/aws/route53.py +386 -332
- cartography/intel/aws/s3.py +322 -14
- cartography/intel/aws/secretsmanager.py +81 -49
- cartography/intel/aws/securityhub.py +3 -1
- cartography/intel/aws/sns.py +62 -2
- cartography/intel/aws/sqs.py +36 -90
- cartography/intel/aws/ssm.py +3 -5
- cartography/intel/azure/__init__.py +202 -48
- cartography/intel/azure/aks.py +175 -0
- cartography/intel/azure/app_service.py +105 -0
- cartography/intel/azure/compute.py +59 -112
- cartography/intel/azure/container_instances.py +95 -0
- cartography/intel/azure/cosmosdb.py +222 -361
- cartography/intel/azure/data_factory.py +85 -0
- cartography/intel/azure/data_factory_dataset.py +128 -0
- cartography/intel/azure/data_factory_linked_service.py +119 -0
- cartography/intel/azure/data_factory_pipeline.py +142 -0
- cartography/intel/azure/data_lake.py +124 -0
- cartography/intel/azure/event_grid.py +94 -0
- cartography/intel/azure/functions.py +124 -0
- cartography/intel/azure/load_balancers.py +263 -0
- cartography/intel/azure/logic_apps.py +101 -0
- cartography/intel/azure/monitor.py +105 -0
- cartography/intel/azure/network.py +467 -0
- cartography/intel/azure/permission_relationships.py +466 -0
- cartography/intel/azure/rbac.py +309 -0
- cartography/intel/azure/resource_groups.py +82 -0
- cartography/intel/azure/security_center.py +106 -0
- cartography/intel/azure/sql.py +145 -292
- cartography/intel/azure/storage.py +185 -262
- cartography/intel/azure/subscription.py +21 -43
- cartography/intel/azure/tenant.py +39 -30
- cartography/intel/azure/util/common.py +13 -0
- cartography/intel/azure/util/credentials.py +49 -174
- cartography/intel/azure/util/tag.py +41 -0
- cartography/intel/create_indexes.py +2 -1
- cartography/intel/crowdstrike/spotlight.py +5 -2
- cartography/intel/dns.py +5 -2
- cartography/intel/entra/__init__.py +100 -1
- cartography/intel/entra/app_role_assignments.py +284 -0
- cartography/intel/entra/applications.py +182 -0
- cartography/intel/entra/federation/__init__.py +0 -0
- cartography/intel/entra/federation/aws_identity_center.py +77 -0
- cartography/intel/entra/groups.py +198 -0
- cartography/intel/entra/ou.py +48 -24
- cartography/intel/entra/service_principals.py +217 -0
- cartography/intel/entra/users.py +105 -57
- cartography/intel/gcp/__init__.py +334 -396
- cartography/intel/gcp/bigtable_app_profile.py +101 -0
- cartography/intel/gcp/bigtable_backup.py +91 -0
- cartography/intel/gcp/bigtable_cluster.py +93 -0
- cartography/intel/gcp/bigtable_instance.py +86 -0
- cartography/intel/gcp/bigtable_table.py +87 -0
- cartography/intel/gcp/cai.py +292 -0
- cartography/intel/gcp/clients.py +112 -0
- cartography/intel/gcp/compute.py +128 -119
- cartography/intel/gcp/crm/__init__.py +0 -0
- cartography/intel/gcp/crm/folders.py +114 -0
- cartography/intel/gcp/crm/orgs.py +70 -0
- cartography/intel/gcp/crm/projects.py +120 -0
- cartography/intel/gcp/dns.py +83 -169
- cartography/intel/gcp/gke.py +72 -113
- cartography/intel/gcp/iam.py +111 -91
- cartography/intel/gcp/permission_relationships.py +394 -0
- cartography/intel/gcp/policy_bindings.py +225 -0
- cartography/intel/gcp/storage.py +75 -159
- cartography/intel/github/__init__.py +62 -25
- cartography/intel/github/commits.py +423 -0
- cartography/intel/github/repos.py +463 -85
- cartography/intel/github/teams.py +3 -3
- cartography/intel/github/users.py +5 -0
- cartography/intel/github/util.py +12 -0
- cartography/intel/googleworkspace/__init__.py +193 -0
- cartography/intel/googleworkspace/devices.py +254 -0
- cartography/intel/googleworkspace/groups.py +568 -0
- cartography/intel/googleworkspace/oauth_apps.py +259 -0
- cartography/intel/googleworkspace/tenant.py +85 -0
- cartography/intel/googleworkspace/users.py +138 -0
- cartography/intel/gsuite/__init__.py +17 -9
- cartography/intel/gsuite/groups.py +291 -0
- cartography/intel/gsuite/users.py +142 -0
- cartography/intel/jamf/computers.py +7 -1
- cartography/intel/keycloak/__init__.py +153 -0
- cartography/intel/keycloak/authenticationexecutions.py +322 -0
- cartography/intel/keycloak/authenticationflows.py +77 -0
- cartography/intel/keycloak/clients.py +187 -0
- cartography/intel/keycloak/groups.py +126 -0
- cartography/intel/keycloak/identityproviders.py +94 -0
- cartography/intel/keycloak/organizations.py +163 -0
- cartography/intel/keycloak/realms.py +61 -0
- cartography/intel/keycloak/roles.py +202 -0
- cartography/intel/keycloak/scopes.py +73 -0
- cartography/intel/keycloak/users.py +70 -0
- cartography/intel/keycloak/util.py +47 -0
- cartography/intel/kubernetes/__init__.py +60 -14
- cartography/intel/kubernetes/clusters.py +86 -0
- cartography/intel/kubernetes/eks.py +402 -0
- cartography/intel/kubernetes/namespaces.py +59 -57
- cartography/intel/kubernetes/pods.py +168 -75
- cartography/intel/kubernetes/rbac.py +597 -0
- cartography/intel/kubernetes/secrets.py +95 -45
- cartography/intel/kubernetes/services.py +131 -67
- cartography/intel/kubernetes/util.py +142 -14
- cartography/intel/oci/iam.py +23 -9
- cartography/intel/oci/organizations.py +3 -1
- cartography/intel/oci/utils.py +28 -5
- cartography/intel/okta/applications.py +15 -5
- cartography/intel/okta/awssaml.py +14 -10
- cartography/intel/okta/factors.py +3 -1
- cartography/intel/okta/groups.py +5 -2
- cartography/intel/okta/organization.py +3 -1
- cartography/intel/okta/origins.py +3 -1
- cartography/intel/okta/roles.py +5 -2
- cartography/intel/okta/users.py +10 -2
- cartography/intel/ontology/__init__.py +44 -0
- cartography/intel/ontology/devices.py +54 -0
- cartography/intel/ontology/users.py +54 -0
- cartography/intel/ontology/utils.py +176 -0
- cartography/intel/pagerduty/escalation_policies.py +13 -6
- cartography/intel/pagerduty/schedules.py +9 -4
- cartography/intel/pagerduty/services.py +7 -3
- cartography/intel/pagerduty/teams.py +5 -2
- cartography/intel/pagerduty/users.py +3 -1
- cartography/intel/pagerduty/vendors.py +3 -1
- cartography/intel/scaleway/__init__.py +127 -0
- cartography/intel/scaleway/iam/__init__.py +0 -0
- cartography/intel/scaleway/iam/apikeys.py +71 -0
- cartography/intel/scaleway/iam/applications.py +71 -0
- cartography/intel/scaleway/iam/groups.py +71 -0
- cartography/intel/scaleway/iam/users.py +71 -0
- cartography/intel/scaleway/instances/__init__.py +0 -0
- cartography/intel/scaleway/instances/flexibleips.py +86 -0
- cartography/intel/scaleway/instances/instances.py +92 -0
- cartography/intel/scaleway/projects.py +79 -0
- cartography/intel/scaleway/storage/__init__.py +0 -0
- cartography/intel/scaleway/storage/snapshots.py +86 -0
- cartography/intel/scaleway/storage/volumes.py +84 -0
- cartography/intel/scaleway/utils.py +37 -0
- cartography/intel/sentinelone/__init__.py +75 -0
- cartography/intel/sentinelone/account.py +140 -0
- cartography/intel/sentinelone/agent.py +139 -0
- cartography/intel/sentinelone/api.py +124 -0
- cartography/intel/sentinelone/application.py +248 -0
- cartography/intel/sentinelone/cve.py +119 -0
- cartography/intel/sentinelone/utils.py +28 -0
- cartography/intel/slack/__init__.py +78 -0
- cartography/intel/slack/channels.py +80 -0
- cartography/intel/slack/groups.py +90 -0
- cartography/intel/slack/teams.py +65 -0
- cartography/intel/slack/users.py +57 -0
- cartography/intel/slack/utils.py +29 -0
- cartography/intel/spacelift/__init__.py +161 -0
- cartography/intel/spacelift/account.py +73 -0
- cartography/intel/spacelift/ec2_ownership.py +280 -0
- cartography/intel/spacelift/runs.py +463 -0
- cartography/intel/spacelift/spaces.py +112 -0
- cartography/intel/spacelift/stacks.py +119 -0
- cartography/intel/spacelift/util.py +122 -0
- cartography/intel/spacelift/workerpools.py +131 -0
- cartography/intel/spacelift/workers.py +128 -0
- cartography/intel/trivy/__init__.py +272 -0
- cartography/intel/trivy/scanner.py +386 -0
- cartography/models/airbyte/__init__.py +0 -0
- cartography/models/airbyte/connection.py +138 -0
- cartography/models/airbyte/destination.py +75 -0
- cartography/models/airbyte/organization.py +19 -0
- cartography/models/airbyte/source.py +75 -0
- cartography/models/airbyte/stream.py +74 -0
- cartography/models/airbyte/tag.py +69 -0
- cartography/models/airbyte/user.py +115 -0
- cartography/models/airbyte/workspace.py +46 -0
- cartography/models/anthropic/apikey.py +4 -0
- cartography/models/anthropic/user.py +4 -0
- cartography/models/aws/acm/__init__.py +0 -0
- cartography/models/aws/acm/certificate.py +75 -0
- cartography/models/aws/apigateway/__init__.py +0 -0
- cartography/models/aws/apigateway/apigatewaydeployment.py +74 -0
- cartography/models/aws/apigateway/apigatewayintegration.py +79 -0
- cartography/models/aws/apigateway/apigatewaymethod.py +74 -0
- cartography/models/aws/apigatewayv2/__init__.py +0 -0
- cartography/models/aws/apigatewayv2/apigatewayv2.py +53 -0
- cartography/models/aws/cloudtrail/management_events.py +153 -0
- cartography/models/aws/cloudtrail/trail.py +45 -0
- cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
- cartography/models/aws/cloudwatch/metric_alarm.py +53 -0
- cartography/models/aws/codebuild/__init__.py +0 -0
- cartography/models/aws/codebuild/project.py +49 -0
- cartography/models/aws/cognito/__init__.py +0 -0
- cartography/models/aws/cognito/identity_pool.py +70 -0
- cartography/models/aws/cognito/user_pool.py +47 -0
- cartography/models/aws/dynamodb/tables.py +2 -0
- cartography/models/aws/ec2/instances.py +25 -1
- cartography/models/aws/ec2/networkinterfaces.py +4 -0
- cartography/models/aws/ec2/security_group_rules.py +109 -0
- cartography/models/aws/ec2/security_groups.py +90 -0
- cartography/models/aws/ec2/snapshots.py +58 -0
- cartography/models/aws/ec2/subnet_instance.py +2 -0
- cartography/models/aws/ec2/subnet_networkinterface.py +2 -0
- cartography/models/aws/ec2/subnets.py +65 -0
- cartography/models/aws/ec2/volumes.py +20 -0
- cartography/models/aws/ec2/vpc.py +46 -0
- cartography/models/aws/ec2/vpc_cidr.py +102 -0
- cartography/models/aws/ec2/vpc_peering.py +157 -0
- cartography/models/aws/ecr/__init__.py +0 -0
- cartography/models/aws/ecr/image.py +146 -0
- cartography/models/aws/ecr/image_layer.py +107 -0
- cartography/models/aws/ecr/repository.py +72 -0
- cartography/models/aws/ecr/repository_image.py +95 -0
- cartography/models/aws/ecs/__init__.py +0 -0
- cartography/models/aws/ecs/clusters.py +64 -0
- cartography/models/aws/ecs/container_definitions.py +93 -0
- cartography/models/aws/ecs/container_instances.py +84 -0
- cartography/models/aws/ecs/containers.py +101 -0
- cartography/models/aws/ecs/services.py +134 -0
- cartography/models/aws/ecs/task_definitions.py +135 -0
- cartography/models/aws/ecs/tasks.py +134 -0
- cartography/models/aws/efs/access_point.py +77 -0
- cartography/models/aws/efs/file_system.py +60 -0
- cartography/models/aws/efs/mount_target.py +29 -2
- cartography/models/aws/elasticache/__init__.py +0 -0
- cartography/models/aws/elasticache/cluster.py +65 -0
- cartography/models/aws/elasticache/topic.py +67 -0
- cartography/models/aws/eventbridge/__init__.py +0 -0
- cartography/models/aws/eventbridge/rule.py +77 -0
- cartography/models/aws/eventbridge/target.py +71 -0
- cartography/models/aws/glue/__init__.py +0 -0
- cartography/models/aws/glue/connection.py +51 -0
- cartography/models/aws/glue/job.py +69 -0
- cartography/models/aws/guardduty/__init__.py +1 -0
- cartography/models/aws/guardduty/detectors.py +50 -0
- cartography/models/aws/guardduty/findings.py +121 -0
- cartography/models/aws/iam/access_key.py +103 -0
- cartography/models/aws/iam/account_role.py +24 -0
- cartography/models/aws/iam/federated_principal.py +60 -0
- cartography/models/aws/iam/group.py +60 -0
- cartography/models/aws/iam/group_membership.py +27 -0
- cartography/models/aws/iam/inline_policy.py +78 -0
- cartography/models/aws/iam/managed_policy.py +51 -0
- cartography/models/aws/iam/policy_statement.py +57 -0
- cartography/models/aws/iam/role.py +83 -0
- cartography/models/aws/iam/root_principal.py +52 -0
- cartography/models/aws/iam/service_principal.py +30 -0
- cartography/models/aws/iam/sts_assumerole_allow.py +38 -0
- cartography/models/aws/iam/user.py +59 -0
- cartography/models/aws/identitycenter/awsidentitycenter.py +1 -0
- cartography/models/aws/identitycenter/awspermissionset.py +70 -0
- cartography/models/aws/identitycenter/awssogroup.py +70 -0
- cartography/models/aws/identitycenter/awsssouser.py +49 -9
- cartography/models/aws/inspector/findings.py +37 -0
- cartography/models/aws/inspector/packages.py +1 -31
- cartography/models/aws/kms/__init__.py +0 -0
- cartography/models/aws/kms/aliases.py +86 -0
- cartography/models/aws/kms/grants.py +65 -0
- cartography/models/aws/kms/keys.py +88 -0
- cartography/models/aws/lambda_function/__init__.py +0 -0
- cartography/models/aws/lambda_function/alias.py +74 -0
- cartography/models/aws/lambda_function/event_source_mapping.py +88 -0
- cartography/models/aws/lambda_function/lambda_function.py +91 -0
- cartography/models/aws/lambda_function/layer.py +72 -0
- cartography/models/aws/rds/__init__.py +0 -0
- cartography/models/aws/rds/cluster.py +91 -0
- cartography/models/aws/rds/event_subscription.py +146 -0
- cartography/models/aws/rds/instance.py +156 -0
- cartography/models/aws/rds/snapshot.py +108 -0
- cartography/models/aws/rds/subnet_group.py +101 -0
- cartography/models/aws/route53/__init__.py +0 -0
- cartography/models/aws/route53/dnsrecord.py +235 -0
- cartography/models/aws/route53/nameserver.py +63 -0
- cartography/models/aws/route53/subzone.py +40 -0
- cartography/models/aws/route53/zone.py +47 -0
- cartography/models/aws/s3/notification.py +24 -0
- cartography/models/aws/secretsmanager/secret.py +106 -0
- cartography/models/aws/secretsmanager/secret_version.py +0 -2
- cartography/models/aws/sns/topic_subscription.py +74 -0
- cartography/models/aws/sqs/__init__.py +0 -0
- cartography/models/aws/sqs/queue.py +89 -0
- cartography/models/azure/__init__.py +0 -0
- cartography/models/azure/aks_cluster.py +54 -0
- cartography/models/azure/aks_nodepool.py +54 -0
- cartography/models/azure/app_service.py +59 -0
- cartography/models/azure/container_instance.py +57 -0
- cartography/models/azure/cosmosdb/__init__.py +0 -0
- cartography/models/azure/cosmosdb/account.py +77 -0
- cartography/models/azure/cosmosdb/accountfailoverpolicy.py +77 -0
- cartography/models/azure/cosmosdb/cassandrakeyspace.py +82 -0
- cartography/models/azure/cosmosdb/cassandratable.py +81 -0
- cartography/models/azure/cosmosdb/corspolicy.py +74 -0
- cartography/models/azure/cosmosdb/dblocation.py +120 -0
- cartography/models/azure/cosmosdb/mongodbcollection.py +82 -0
- cartography/models/azure/cosmosdb/mongodbdatabase.py +78 -0
- cartography/models/azure/cosmosdb/privateendpointconnection.py +81 -0
- cartography/models/azure/cosmosdb/sqlcontainer.py +88 -0
- cartography/models/azure/cosmosdb/sqldatabase.py +78 -0
- cartography/models/azure/cosmosdb/tableresource.py +76 -0
- cartography/models/azure/cosmosdb/virtualnetworkrule.py +78 -0
- cartography/models/azure/data_factory/__init__.py +0 -0
- cartography/models/azure/data_factory/data_factory.py +51 -0
- cartography/models/azure/data_factory/data_factory_dataset.py +94 -0
- cartography/models/azure/data_factory/data_factory_linked_service.py +78 -0
- cartography/models/azure/data_factory/data_factory_pipeline.py +93 -0
- cartography/models/azure/data_lake_filesystem.py +51 -0
- cartography/models/azure/event_grid_topic.py +57 -0
- cartography/models/azure/function_app.py +59 -0
- cartography/models/azure/load_balancer/__init__.py +0 -0
- cartography/models/azure/load_balancer/load_balancer.py +49 -0
- cartography/models/azure/load_balancer/load_balancer_backend_pool.py +73 -0
- cartography/models/azure/load_balancer/load_balancer_frontend_ip.py +75 -0
- cartography/models/azure/load_balancer/load_balancer_inbound_nat_rule.py +78 -0
- cartography/models/azure/load_balancer/load_balancer_rule.py +108 -0
- cartography/models/azure/logic_apps.py +56 -0
- cartography/models/azure/monitor.py +54 -0
- cartography/models/azure/network_interface.py +112 -0
- cartography/models/azure/network_security_group.py +50 -0
- cartography/models/azure/permission_relationships.py +60 -0
- cartography/models/azure/principal.py +41 -0
- cartography/models/azure/public_ip_address.py +50 -0
- cartography/models/azure/rbac.py +268 -0
- cartography/models/azure/resource_groups.py +52 -0
- cartography/models/azure/security_center.py +50 -0
- cartography/models/azure/sql/__init__.py +0 -0
- cartography/models/azure/sql/databasethreatdetectionpolicy.py +85 -0
- cartography/models/azure/sql/elasticpool.py +77 -0
- cartography/models/azure/sql/failovergroup.py +73 -0
- cartography/models/azure/sql/recoverabledatabase.py +75 -0
- cartography/models/azure/sql/replicationlink.py +81 -0
- cartography/models/azure/sql/restorabledroppeddatabase.py +82 -0
- cartography/models/azure/sql/restorepoint.py +74 -0
- cartography/models/azure/sql/serveradadministrator.py +74 -0
- cartography/models/azure/sql/serverdnsalias.py +71 -0
- cartography/models/azure/sql/sqldatabase.py +85 -0
- cartography/models/azure/sql/sqlserver.py +50 -0
- cartography/models/azure/sql/transparentdataencryption.py +76 -0
- cartography/models/azure/storage/__init__.py +0 -0
- cartography/models/azure/storage/account.py +59 -0
- cartography/models/azure/storage/blobcontainer.py +85 -0
- cartography/models/azure/storage/blobservice.py +71 -0
- cartography/models/azure/storage/fileservice.py +71 -0
- cartography/models/azure/storage/fileshare.py +82 -0
- cartography/models/azure/storage/queue.py +71 -0
- cartography/models/azure/storage/queueservice.py +73 -0
- cartography/models/azure/storage/table.py +72 -0
- cartography/models/azure/storage/tableservice.py +73 -0
- cartography/models/azure/subnet.py +101 -0
- cartography/models/azure/subscription.py +47 -0
- cartography/models/azure/tags/__init__.py +0 -0
- cartography/models/azure/tags/storage_tag.py +40 -0
- cartography/models/azure/tags/tag.py +37 -0
- cartography/models/azure/tenant.py +17 -0
- cartography/models/azure/virtual_network.py +49 -0
- cartography/models/azure/vm/__init__.py +0 -0
- cartography/models/azure/vm/datadisk.py +80 -0
- cartography/models/azure/vm/disk.py +55 -0
- cartography/models/azure/vm/snapshot.py +56 -0
- cartography/models/azure/vm/virtualmachine.py +59 -0
- cartography/models/bigfix/bigfix_computer.py +1 -1
- cartography/models/cloudflare/member.py +4 -0
- cartography/models/core/common.py +1 -0
- cartography/models/core/nodes.py +15 -2
- cartography/models/core/relationships.py +44 -0
- cartography/models/crowdstrike/hosts.py +1 -1
- cartography/models/digitalocean/droplet.py +2 -0
- cartography/models/duo/endpoint.py +1 -1
- cartography/models/duo/phone.py +2 -2
- cartography/models/duo/user.py +4 -0
- cartography/models/entra/app_role_assignment.py +115 -0
- cartography/models/entra/application.py +49 -0
- cartography/models/entra/entra_user_to_aws_sso.py +41 -0
- cartography/models/entra/group.py +117 -0
- cartography/models/entra/service_principal.py +104 -0
- cartography/models/entra/user.py +42 -51
- cartography/models/gcp/__init__.py +0 -0
- cartography/models/gcp/bigtable/__init__.py +0 -0
- cartography/models/gcp/bigtable/app_profile.py +94 -0
- cartography/models/gcp/bigtable/backup.py +91 -0
- cartography/models/gcp/bigtable/cluster.py +73 -0
- cartography/models/gcp/bigtable/instance.py +52 -0
- cartography/models/gcp/bigtable/table.py +69 -0
- cartography/models/gcp/compute/__init__.py +0 -0
- cartography/models/gcp/compute/subnet.py +74 -0
- cartography/models/gcp/compute/vpc.py +50 -0
- cartography/models/gcp/crm/__init__.py +0 -0
- cartography/models/gcp/crm/folders.py +98 -0
- cartography/models/gcp/crm/organizations.py +21 -0
- cartography/models/gcp/crm/projects.py +100 -0
- cartography/models/gcp/dns.py +109 -0
- cartography/models/gcp/gke.py +69 -0
- cartography/models/gcp/iam.py +3 -0
- cartography/models/gcp/permission_relationships.py +61 -0
- cartography/models/gcp/policy_bindings.py +93 -0
- cartography/models/gcp/storage/__init__.py +0 -0
- cartography/models/gcp/storage/bucket.py +119 -0
- cartography/models/github/commits.py +63 -0
- cartography/models/github/dependencies.py +73 -0
- cartography/models/github/manifests.py +49 -0
- cartography/models/github/users.py +10 -0
- cartography/models/googleworkspace/__init__.py +0 -0
- cartography/models/googleworkspace/device.py +132 -0
- cartography/models/googleworkspace/group.py +382 -0
- cartography/models/googleworkspace/oauth_app.py +124 -0
- cartography/models/googleworkspace/tenant.py +30 -0
- cartography/models/googleworkspace/user.py +113 -0
- cartography/models/gsuite/__init__.py +0 -0
- cartography/models/gsuite/group.py +218 -0
- cartography/models/gsuite/tenant.py +29 -0
- cartography/models/gsuite/user.py +107 -0
- cartography/models/kandji/device.py +1 -2
- cartography/models/keycloak/__init__.py +0 -0
- cartography/models/keycloak/authenticationexecution.py +160 -0
- cartography/models/keycloak/authenticationflow.py +54 -0
- cartography/models/keycloak/client.py +179 -0
- cartography/models/keycloak/group.py +101 -0
- cartography/models/keycloak/identityprovider.py +89 -0
- cartography/models/keycloak/organization.py +116 -0
- cartography/models/keycloak/organizationdomain.py +73 -0
- cartography/models/keycloak/realm.py +173 -0
- cartography/models/keycloak/role.py +126 -0
- cartography/models/keycloak/scope.py +73 -0
- cartography/models/keycloak/user.py +55 -0
- cartography/models/kubernetes/__init__.py +0 -0
- cartography/models/kubernetes/clusterrolebindings.py +138 -0
- cartography/models/kubernetes/clusterroles.py +52 -0
- cartography/models/kubernetes/clusters.py +26 -0
- cartography/models/kubernetes/containers.py +133 -0
- cartography/models/kubernetes/groups.py +107 -0
- cartography/models/kubernetes/namespaces.py +51 -0
- cartography/models/kubernetes/oidc.py +51 -0
- cartography/models/kubernetes/pods.py +80 -0
- cartography/models/kubernetes/rolebindings.py +159 -0
- cartography/models/kubernetes/roles.py +76 -0
- cartography/models/kubernetes/secrets.py +79 -0
- cartography/models/kubernetes/serviceaccounts.py +77 -0
- cartography/models/kubernetes/services.py +108 -0
- cartography/models/kubernetes/users.py +105 -0
- cartography/models/lastpass/user.py +4 -0
- cartography/models/ontology/__init__.py +0 -0
- cartography/models/ontology/device.py +137 -0
- cartography/models/ontology/mapping/__init__.py +76 -0
- cartography/models/ontology/mapping/data/__init__.py +0 -0
- cartography/models/ontology/mapping/data/apikeys.py +93 -0
- cartography/models/ontology/mapping/data/computeinstance.py +95 -0
- cartography/models/ontology/mapping/data/containers.py +88 -0
- cartography/models/ontology/mapping/data/databases.py +182 -0
- cartography/models/ontology/mapping/data/devices.py +194 -0
- cartography/models/ontology/mapping/data/thirdpartyapps.py +140 -0
- cartography/models/ontology/mapping/data/useraccounts.py +416 -0
- cartography/models/ontology/mapping/data/users.py +63 -0
- cartography/models/ontology/mapping/specs.py +85 -0
- cartography/models/ontology/user.py +51 -0
- cartography/models/openai/adminapikey.py +4 -0
- cartography/models/openai/apikey.py +4 -0
- cartography/models/openai/user.py +4 -0
- cartography/models/scaleway/__init__.py +0 -0
- cartography/models/scaleway/iam/__init__.py +0 -0
- cartography/models/scaleway/iam/apikey.py +100 -0
- cartography/models/scaleway/iam/application.py +52 -0
- cartography/models/scaleway/iam/group.py +95 -0
- cartography/models/scaleway/iam/user.py +64 -0
- cartography/models/scaleway/instance/__init__.py +0 -0
- cartography/models/scaleway/instance/flexibleip.py +52 -0
- cartography/models/scaleway/instance/instance.py +120 -0
- cartography/models/scaleway/organization.py +19 -0
- cartography/models/scaleway/project.py +48 -0
- cartography/models/scaleway/storage/__init__.py +0 -0
- cartography/models/scaleway/storage/snapshot.py +78 -0
- cartography/models/scaleway/storage/volume.py +51 -0
- cartography/models/sentinelone/__init__.py +1 -0
- cartography/models/sentinelone/account.py +40 -0
- cartography/models/sentinelone/agent.py +50 -0
- cartography/models/sentinelone/application.py +44 -0
- cartography/models/sentinelone/application_version.py +96 -0
- cartography/models/sentinelone/cve.py +73 -0
- cartography/models/slack/__init__.py +0 -0
- cartography/models/slack/channels.py +92 -0
- cartography/models/slack/group.py +129 -0
- cartography/models/slack/team.py +22 -0
- cartography/models/slack/user.py +62 -0
- cartography/models/snipeit/asset.py +2 -0
- cartography/models/snipeit/user.py +4 -0
- cartography/models/spacelift/__init__.py +0 -0
- cartography/models/spacelift/cloudtrailevent.py +120 -0
- cartography/models/spacelift/run.py +162 -0
- cartography/models/spacelift/space.py +131 -0
- cartography/models/spacelift/spaceliftaccount.py +31 -0
- cartography/models/spacelift/spaceliftgitcommit.py +157 -0
- cartography/models/spacelift/stack.py +96 -0
- cartography/models/spacelift/user.py +63 -0
- cartography/models/spacelift/worker.py +97 -0
- cartography/models/spacelift/workerpool.py +90 -0
- cartography/models/tailscale/device.py +2 -1
- cartography/models/tailscale/user.py +6 -1
- cartography/models/trivy/__init__.py +0 -0
- cartography/models/trivy/findings.py +66 -0
- cartography/models/trivy/fix.py +66 -0
- cartography/models/trivy/package.py +71 -0
- cartography/rules/README.md +1 -0
- cartography/rules/__init__.py +0 -0
- cartography/rules/cli.py +261 -0
- cartography/rules/data/__init__.py +0 -0
- cartography/rules/data/rules/__init__.py +46 -0
- cartography/rules/data/rules/cloud_security_product_deactivated.py +49 -0
- cartography/rules/data/rules/compute_instance_exposed.py +51 -0
- cartography/rules/data/rules/database_instance_exposed.py +53 -0
- cartography/rules/data/rules/delegation_boundary_modifiable.py +90 -0
- cartography/rules/data/rules/identity_administration_privileges.py +100 -0
- cartography/rules/data/rules/inactive_user_active_accounts.py +48 -0
- cartography/rules/data/rules/malicious_npm_dependencies_shai_hulud.py +2222 -0
- cartography/rules/data/rules/mfa_missing.py +46 -0
- cartography/rules/data/rules/object_storage_public.py +100 -0
- cartography/rules/data/rules/policy_administration_privileges.py +104 -0
- cartography/rules/data/rules/unmanaged_accounts.py +43 -0
- cartography/rules/data/rules/workload_identity_admin_capabilities.py +193 -0
- cartography/rules/formatters.py +108 -0
- cartography/rules/runners.py +216 -0
- cartography/rules/spec/__init__.py +0 -0
- cartography/rules/spec/model.py +267 -0
- cartography/rules/spec/result.py +38 -0
- cartography/sync.py +25 -5
- cartography/util.py +101 -31
- {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/METADATA +61 -22
- cartography-0.123.0.dist-info/RECORD +856 -0
- {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/entry_points.txt +1 -0
- cartography/data/jobs/cleanup/aws_dns_cleanup.json +0 -65
- cartography/data/jobs/cleanup/aws_import_account_access_key_cleanup.json +0 -17
- cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json +0 -24
- cartography/data/jobs/cleanup/aws_import_groups_cleanup.json +0 -13
- cartography/data/jobs/cleanup/aws_import_identity_center_cleanup.json +0 -16
- cartography/data/jobs/cleanup/aws_import_lambda_cleanup.json +0 -50
- cartography/data/jobs/cleanup/aws_import_principals_cleanup.json +0 -30
- cartography/data/jobs/cleanup/aws_import_rds_clusters_cleanup.json +0 -23
- cartography/data/jobs/cleanup/aws_import_rds_instances_cleanup.json +0 -47
- cartography/data/jobs/cleanup/aws_import_rds_snapshots_cleanup.json +0 -23
- cartography/data/jobs/cleanup/aws_import_roles_cleanup.json +0 -13
- cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -8
- cartography/data/jobs/cleanup/aws_import_snapshots_cleanup.json +0 -30
- cartography/data/jobs/cleanup/aws_import_users_cleanup.json +0 -8
- cartography/data/jobs/cleanup/aws_import_vpc_cleanup.json +0 -23
- cartography/data/jobs/cleanup/aws_import_vpc_peering_cleanup.json +0 -45
- cartography/data/jobs/cleanup/aws_kms_details.json +0 -10
- cartography/data/jobs/cleanup/azure_cosmosdb_cassandra_keyspace_cleanup.json +0 -25
- cartography/data/jobs/cleanup/azure_cosmosdb_cors_details.json +0 -15
- cartography/data/jobs/cleanup/azure_cosmosdb_mongodb_database_cleanup.json +0 -25
- cartography/data/jobs/cleanup/azure_cosmosdb_sql_database_cleanup.json +0 -25
- cartography/data/jobs/cleanup/azure_cosmosdb_table_resources_cleanup.json +0 -15
- cartography/data/jobs/cleanup/azure_database_account_cleanup.json +0 -85
- cartography/data/jobs/cleanup/azure_import_disks_cleanup.json +0 -15
- cartography/data/jobs/cleanup/azure_import_snapshots_cleanup.json +0 -15
- cartography/data/jobs/cleanup/azure_import_virtual_machines_cleanup.json +0 -25
- cartography/data/jobs/cleanup/azure_sql_server_cleanup.json +0 -125
- cartography/data/jobs/cleanup/azure_storage_account_cleanup.json +0 -95
- cartography/data/jobs/cleanup/azure_subscriptions_cleanup.json +0 -14
- cartography/data/jobs/cleanup/azure_tenant_cleanup.json +0 -9
- cartography/data/jobs/cleanup/gcp_compute_vpc_subnet_cleanup.json +0 -35
- cartography/data/jobs/cleanup/gcp_crm_folder_cleanup.json +0 -23
- cartography/data/jobs/cleanup/gcp_crm_organization_cleanup.json +0 -17
- cartography/data/jobs/cleanup/gcp_crm_project_cleanup.json +0 -23
- cartography/data/jobs/cleanup/gcp_dns_cleanup.json +0 -29
- cartography/data/jobs/cleanup/gcp_gke_cluster_cleanup.json +0 -17
- cartography/data/jobs/cleanup/gcp_storage_bucket_cleanup.json +0 -29
- cartography/data/jobs/cleanup/gsuite_ingest_groups_cleanup.json +0 -23
- cartography/data/jobs/cleanup/gsuite_ingest_users_cleanup.json +0 -11
- cartography/data/jobs/cleanup/kubernetes_import_cleanup.json +0 -70
- cartography/intel/gcp/crm.py +0 -355
- cartography/intel/gsuite/api.py +0 -342
- cartography-0.104.0rc2.dist-info/RECORD +0 -455
- /cartography/data/jobs/{analysis → scoped_analysis}/aws_s3acl_analysis.json +0 -0
- /cartography/models/aws/{apigateway.py → apigateway/apigateway.py} +0 -0
- /cartography/models/aws/{apigatewaycertificate.py → apigateway/apigatewaycertificate.py} +0 -0
- /cartography/models/aws/{apigatewayresource.py → apigateway/apigatewayresource.py} +0 -0
- /cartography/models/aws/{apigatewaystage.py → apigateway/apigatewaystage.py} +0 -0
- {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/WHEEL +0 -0
- {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from typing import Generator
|
|
3
|
+
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
# Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
|
|
7
|
+
_TIMEOUT = (60, 60)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_paginated(
|
|
11
|
+
api_session: requests.Session,
|
|
12
|
+
endpoint: str,
|
|
13
|
+
items_per_page: int = 100,
|
|
14
|
+
params: dict[str, Any] | None = None,
|
|
15
|
+
) -> Generator[dict[str, Any], None, None]:
|
|
16
|
+
"""Fetch paginated results from a REST API endpoint.
|
|
17
|
+
|
|
18
|
+
This function handles pagination by making multiple requests to the API
|
|
19
|
+
until all pages of results have been retrieved.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
api_session (requests.Session): The requests session to use for making API calls.
|
|
23
|
+
endpoint (str): The API endpoint to fetch data from.
|
|
24
|
+
items_per_page (int, optional): The number of items to retrieve per page. Defaults to 100.
|
|
25
|
+
params (dict[str, Any] | None, optional): Additional query parameters to include in the request. Defaults to None.
|
|
26
|
+
|
|
27
|
+
Yields:
|
|
28
|
+
Generator[dict[str, Any], None, None]: A generator that yields the individual items from the paginated response.
|
|
29
|
+
"""
|
|
30
|
+
has_more = True
|
|
31
|
+
offset = 0
|
|
32
|
+
while has_more:
|
|
33
|
+
if params is None:
|
|
34
|
+
payload = {}
|
|
35
|
+
else:
|
|
36
|
+
payload = params.copy()
|
|
37
|
+
payload["first"] = offset
|
|
38
|
+
payload["max"] = items_per_page
|
|
39
|
+
req = api_session.get(endpoint, params=payload, timeout=_TIMEOUT)
|
|
40
|
+
req.raise_for_status()
|
|
41
|
+
data = req.json()
|
|
42
|
+
if not data:
|
|
43
|
+
break
|
|
44
|
+
yield from data
|
|
45
|
+
if len(data) < items_per_page:
|
|
46
|
+
has_more = False
|
|
47
|
+
offset += len(data)
|
|
@@ -1,41 +1,87 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
+
import boto3
|
|
3
4
|
from neo4j import Session
|
|
4
5
|
|
|
5
6
|
from cartography.config import Config
|
|
7
|
+
from cartography.intel.kubernetes.clusters import sync_kubernetes_cluster
|
|
8
|
+
from cartography.intel.kubernetes.eks import sync as sync_eks
|
|
6
9
|
from cartography.intel.kubernetes.namespaces import sync_namespaces
|
|
7
10
|
from cartography.intel.kubernetes.pods import sync_pods
|
|
11
|
+
from cartography.intel.kubernetes.rbac import sync_kubernetes_rbac
|
|
8
12
|
from cartography.intel.kubernetes.secrets import sync_secrets
|
|
9
13
|
from cartography.intel.kubernetes.services import sync_services
|
|
10
14
|
from cartography.intel.kubernetes.util import get_k8s_clients
|
|
11
|
-
from cartography.util import run_cleanup_job
|
|
12
15
|
from cartography.util import timeit
|
|
13
16
|
|
|
14
17
|
logger = logging.getLogger(__name__)
|
|
15
18
|
|
|
16
19
|
|
|
20
|
+
def get_region_from_arn(arn: str) -> str:
|
|
21
|
+
"""
|
|
22
|
+
Extract AWS region from EKS cluster ARN.
|
|
23
|
+
Example: arn:aws:eks:us-east-1:205930638578:cluster/infra-test-eks → us-east-1
|
|
24
|
+
"""
|
|
25
|
+
parts = arn.split(":")
|
|
26
|
+
if len(parts) < 6 or parts[2] != "eks":
|
|
27
|
+
raise ValueError(f"Invalid EKS cluster ARN: {arn}")
|
|
28
|
+
return parts[3]
|
|
29
|
+
|
|
30
|
+
|
|
17
31
|
@timeit
|
|
18
32
|
def start_k8s_ingestion(session: Session, config: Config) -> None:
|
|
33
|
+
if not config.update_tag:
|
|
34
|
+
logger.error("Cartography update tag not provided.")
|
|
35
|
+
return
|
|
19
36
|
|
|
20
|
-
common_job_parameters = {"UPDATE_TAG": config.update_tag}
|
|
21
37
|
if not config.k8s_kubeconfig:
|
|
22
|
-
logger.error("kubeconfig not
|
|
38
|
+
logger.error("Kubernetes kubeconfig not provided.")
|
|
23
39
|
return
|
|
24
40
|
|
|
41
|
+
common_job_parameters = {"UPDATE_TAG": config.update_tag}
|
|
42
|
+
|
|
25
43
|
for client in get_k8s_clients(config.k8s_kubeconfig):
|
|
26
44
|
logger.info(f"Syncing data for k8s cluster {client.name}...")
|
|
27
45
|
try:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
cluster_info = sync_kubernetes_cluster(
|
|
47
|
+
session,
|
|
48
|
+
client,
|
|
49
|
+
config.update_tag,
|
|
50
|
+
common_job_parameters,
|
|
51
|
+
)
|
|
52
|
+
common_job_parameters["CLUSTER_ID"] = cluster_info.get("id")
|
|
53
|
+
|
|
54
|
+
sync_namespaces(session, client, config.update_tag, common_job_parameters)
|
|
55
|
+
sync_kubernetes_rbac(
|
|
56
|
+
session, client, config.update_tag, common_job_parameters
|
|
57
|
+
)
|
|
58
|
+
if config.managed_kubernetes == "eks":
|
|
59
|
+
# EKS identity provider sync
|
|
60
|
+
boto3_session = boto3.Session()
|
|
61
|
+
region = get_region_from_arn(cluster_info.get("id", ""))
|
|
62
|
+
sync_eks(
|
|
63
|
+
session,
|
|
64
|
+
client,
|
|
65
|
+
boto3_session,
|
|
66
|
+
region,
|
|
67
|
+
config.update_tag,
|
|
68
|
+
cluster_info.get("id", ""),
|
|
69
|
+
cluster_info.get("name", ""),
|
|
70
|
+
)
|
|
71
|
+
all_pods = sync_pods(
|
|
72
|
+
session,
|
|
73
|
+
client,
|
|
74
|
+
config.update_tag,
|
|
75
|
+
common_job_parameters,
|
|
76
|
+
)
|
|
77
|
+
sync_secrets(session, client, config.update_tag, common_job_parameters)
|
|
78
|
+
sync_services(
|
|
79
|
+
session,
|
|
80
|
+
client,
|
|
81
|
+
all_pods,
|
|
82
|
+
config.update_tag,
|
|
83
|
+
common_job_parameters,
|
|
84
|
+
)
|
|
32
85
|
except Exception:
|
|
33
86
|
logger.exception(f"Failed to sync data for k8s cluster {client.name}...")
|
|
34
87
|
raise
|
|
35
|
-
|
|
36
|
-
run_cleanup_job(
|
|
37
|
-
"kubernetes_import_cleanup.json",
|
|
38
|
-
session,
|
|
39
|
-
common_job_parameters,
|
|
40
|
-
package="cartography.data.jobs.cleanup",
|
|
41
|
-
)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import neo4j
|
|
5
|
+
from kubernetes.client.models import V1Namespace
|
|
6
|
+
from kubernetes.client.models import VersionInfo
|
|
7
|
+
|
|
8
|
+
from cartography.client.core.tx import load
|
|
9
|
+
from cartography.intel.kubernetes.util import get_epoch
|
|
10
|
+
from cartography.intel.kubernetes.util import K8sClient
|
|
11
|
+
from cartography.models.kubernetes.clusters import KubernetesClusterSchema
|
|
12
|
+
from cartography.util import timeit
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@timeit
|
|
18
|
+
def get_kubernetes_cluster_namespace(client: K8sClient) -> V1Namespace:
|
|
19
|
+
return client.core.read_namespace("kube-system")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@timeit
|
|
23
|
+
def get_kubernetes_cluster_version(client: K8sClient) -> VersionInfo:
|
|
24
|
+
return client.version.get_code()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def transform_kubernetes_cluster(
|
|
28
|
+
client: K8sClient,
|
|
29
|
+
namespace: V1Namespace,
|
|
30
|
+
version: VersionInfo,
|
|
31
|
+
) -> list[dict[str, Any]]:
|
|
32
|
+
cluster = {
|
|
33
|
+
"id": namespace.metadata.uid,
|
|
34
|
+
"creation_timestamp": get_epoch(namespace.metadata.creation_timestamp),
|
|
35
|
+
"external_id": client.external_id,
|
|
36
|
+
"name": client.name,
|
|
37
|
+
"git_version": version.git_version,
|
|
38
|
+
"version_major": version.major,
|
|
39
|
+
"version_minor": version.minor,
|
|
40
|
+
"go_version": version.go_version,
|
|
41
|
+
"compiler": version.compiler,
|
|
42
|
+
"platform": version.platform,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return [cluster]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def load_kubernetes_cluster(
|
|
49
|
+
neo4j_session: neo4j.Session,
|
|
50
|
+
cluster_data: list[dict[str, Any]],
|
|
51
|
+
update_tag: int,
|
|
52
|
+
) -> None:
|
|
53
|
+
logger.info(
|
|
54
|
+
"Loading '{}' Kubernetes cluster into graph".format(cluster_data[0].get("name"))
|
|
55
|
+
)
|
|
56
|
+
load(
|
|
57
|
+
neo4j_session,
|
|
58
|
+
KubernetesClusterSchema(),
|
|
59
|
+
cluster_data,
|
|
60
|
+
lastupdated=update_tag,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# cleaning up the kubernetes cluster node is currently not supported
|
|
65
|
+
# def cleanup(
|
|
66
|
+
# neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
67
|
+
# ) -> None:
|
|
68
|
+
# logger.debug("Running cleanup job for KubernetesCluster")
|
|
69
|
+
# run_cleanup_job(
|
|
70
|
+
# "kubernetes_cluster_cleanup.json", neo4j_session, common_job_parameters
|
|
71
|
+
# )
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@timeit
|
|
75
|
+
def sync_kubernetes_cluster(
|
|
76
|
+
neo4j_session: neo4j.Session,
|
|
77
|
+
client: K8sClient,
|
|
78
|
+
update_tag: int,
|
|
79
|
+
common_job_parameters: dict[str, Any],
|
|
80
|
+
) -> dict[str, Any]:
|
|
81
|
+
namespace = get_kubernetes_cluster_namespace(client)
|
|
82
|
+
version = get_kubernetes_cluster_version(client)
|
|
83
|
+
cluster_info = transform_kubernetes_cluster(client, namespace, version)
|
|
84
|
+
|
|
85
|
+
load_kubernetes_cluster(neo4j_session, cluster_info, update_tag)
|
|
86
|
+
return cluster_info[0]
|
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import boto3
|
|
7
|
+
import neo4j
|
|
8
|
+
import yaml
|
|
9
|
+
from kubernetes.client.models import V1ConfigMap
|
|
10
|
+
|
|
11
|
+
from cartography.client.core.tx import load
|
|
12
|
+
from cartography.graph.job import GraphJob
|
|
13
|
+
from cartography.intel.kubernetes.util import K8sClient
|
|
14
|
+
from cartography.models.kubernetes.groups import KubernetesGroupSchema
|
|
15
|
+
from cartography.models.kubernetes.oidc import KubernetesOIDCProviderSchema
|
|
16
|
+
from cartography.models.kubernetes.users import KubernetesUserSchema
|
|
17
|
+
from cartography.util import aws_handle_regions
|
|
18
|
+
from cartography.util import timeit
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@timeit
|
|
24
|
+
def get_aws_auth_configmap(client: K8sClient) -> V1ConfigMap:
|
|
25
|
+
"""
|
|
26
|
+
Get aws-auth ConfigMap from kube-system namespace.
|
|
27
|
+
"""
|
|
28
|
+
logger.info(f"Retrieving aws-auth ConfigMap from cluster {client.name}")
|
|
29
|
+
return client.core.read_namespaced_config_map(
|
|
30
|
+
name="aws-auth", namespace="kube-system"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def parse_aws_auth_map(configmap: V1ConfigMap) -> Dict[str, List[Dict[str, Any]]]:
|
|
35
|
+
"""
|
|
36
|
+
Parse mapRoles and mapUsers from aws-auth ConfigMap.
|
|
37
|
+
|
|
38
|
+
:param configmap: V1ConfigMap containing aws-auth data
|
|
39
|
+
:return: Dictionary with 'roles' and 'users' keys containing their respective mappings
|
|
40
|
+
"""
|
|
41
|
+
result: Dict[str, List[Dict[str, Any]]] = {"roles": [], "users": []}
|
|
42
|
+
|
|
43
|
+
# Parse mapRoles
|
|
44
|
+
if "mapRoles" in configmap.data:
|
|
45
|
+
map_roles_yaml = configmap.data["mapRoles"]
|
|
46
|
+
role_mappings = yaml.safe_load(map_roles_yaml) or []
|
|
47
|
+
|
|
48
|
+
# Filter out templated entries for now (https://github.com/cartography-cncf/cartography/issues/1854)
|
|
49
|
+
filtered_role_mappings = []
|
|
50
|
+
for mapping in role_mappings:
|
|
51
|
+
username = mapping.get("username", "")
|
|
52
|
+
if "{{" in username:
|
|
53
|
+
logger.debug(f"Skipping templated username in mapRoles: {username}")
|
|
54
|
+
continue
|
|
55
|
+
filtered_role_mappings.append(mapping)
|
|
56
|
+
|
|
57
|
+
result["roles"] = filtered_role_mappings
|
|
58
|
+
logger.info(
|
|
59
|
+
f"Parsed {len(filtered_role_mappings)} role mappings from aws-auth ConfigMap"
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
logger.info("No mapRoles found in aws-auth ConfigMap")
|
|
63
|
+
|
|
64
|
+
# Parse mapUsers
|
|
65
|
+
if "mapUsers" in configmap.data:
|
|
66
|
+
map_users_yaml = configmap.data["mapUsers"]
|
|
67
|
+
user_mappings = yaml.safe_load(map_users_yaml) or []
|
|
68
|
+
|
|
69
|
+
filtered_user_mappings = []
|
|
70
|
+
for mapping in user_mappings:
|
|
71
|
+
username = mapping.get("username", "")
|
|
72
|
+
if "{{" in username:
|
|
73
|
+
logger.debug(f"Skipping templated username in mapUsers: {username}")
|
|
74
|
+
continue
|
|
75
|
+
filtered_user_mappings.append(mapping)
|
|
76
|
+
|
|
77
|
+
result["users"] = filtered_user_mappings
|
|
78
|
+
logger.info(
|
|
79
|
+
f"Parsed {len(filtered_user_mappings)} user mappings from aws-auth ConfigMap"
|
|
80
|
+
)
|
|
81
|
+
else:
|
|
82
|
+
logger.info("No mapUsers found in aws-auth ConfigMap")
|
|
83
|
+
|
|
84
|
+
return result
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def transform_aws_auth_mappings(
|
|
88
|
+
auth_mappings: Dict[str, List[Dict[str, Any]]], cluster_name: str
|
|
89
|
+
) -> Dict[str, List[Dict[str, Any]]]:
|
|
90
|
+
"""
|
|
91
|
+
Transform both role and user mappings from aws-auth ConfigMap into combined user/group data.
|
|
92
|
+
"""
|
|
93
|
+
all_users = []
|
|
94
|
+
all_groups = []
|
|
95
|
+
|
|
96
|
+
# Process role mappings if they exist
|
|
97
|
+
if auth_mappings.get("roles"):
|
|
98
|
+
for mapping in auth_mappings.get("roles", []):
|
|
99
|
+
role_arn = mapping.get("rolearn")
|
|
100
|
+
username = mapping.get("username")
|
|
101
|
+
group_names = mapping.get("groups", [])
|
|
102
|
+
|
|
103
|
+
if not role_arn:
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
# Create user data with AWS role relationship (only if username is provided)
|
|
107
|
+
if username:
|
|
108
|
+
all_users.append(
|
|
109
|
+
{
|
|
110
|
+
"id": f"{cluster_name}/{username}",
|
|
111
|
+
"name": username,
|
|
112
|
+
"cluster_name": cluster_name,
|
|
113
|
+
"aws_role_arn": role_arn,
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Create group data with AWS role relationship for each group
|
|
118
|
+
for group_name in group_names:
|
|
119
|
+
all_groups.append(
|
|
120
|
+
{
|
|
121
|
+
"id": f"{cluster_name}/{group_name}",
|
|
122
|
+
"name": group_name,
|
|
123
|
+
"cluster_name": cluster_name,
|
|
124
|
+
"aws_role_arn": role_arn,
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Process user mappings if they exist
|
|
129
|
+
if auth_mappings.get("users"):
|
|
130
|
+
for mapping in auth_mappings.get("users", []):
|
|
131
|
+
user_arn = mapping.get("userarn")
|
|
132
|
+
username = mapping.get("username")
|
|
133
|
+
group_names = mapping.get("groups", [])
|
|
134
|
+
|
|
135
|
+
if not user_arn:
|
|
136
|
+
continue
|
|
137
|
+
|
|
138
|
+
# Create user data with AWS user relationship (only if username is provided)
|
|
139
|
+
if username:
|
|
140
|
+
all_users.append(
|
|
141
|
+
{
|
|
142
|
+
"id": f"{cluster_name}/{username}",
|
|
143
|
+
"name": username,
|
|
144
|
+
"cluster_name": cluster_name,
|
|
145
|
+
"aws_user_arn": user_arn,
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Create group data with AWS user relationship for each group
|
|
150
|
+
for group_name in group_names:
|
|
151
|
+
all_groups.append(
|
|
152
|
+
{
|
|
153
|
+
"id": f"{cluster_name}/{group_name}",
|
|
154
|
+
"name": group_name,
|
|
155
|
+
"cluster_name": cluster_name,
|
|
156
|
+
"aws_user_arn": user_arn,
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# Count entries with vs without usernames for visibility
|
|
161
|
+
role_entries_with_username = sum(
|
|
162
|
+
1 for mapping in auth_mappings.get("roles", []) if mapping.get("username")
|
|
163
|
+
)
|
|
164
|
+
user_entries_with_username = sum(
|
|
165
|
+
1 for mapping in auth_mappings.get("users", []) if mapping.get("username")
|
|
166
|
+
)
|
|
167
|
+
total_entries_with_username = (
|
|
168
|
+
role_entries_with_username + user_entries_with_username
|
|
169
|
+
)
|
|
170
|
+
total_entries = len(auth_mappings.get("roles", [])) + len(
|
|
171
|
+
auth_mappings.get("users", [])
|
|
172
|
+
)
|
|
173
|
+
entries_without_username = total_entries - total_entries_with_username
|
|
174
|
+
|
|
175
|
+
logger.info(
|
|
176
|
+
f"Transformed {len(all_users)} users (from {total_entries_with_username} entries with usernames) "
|
|
177
|
+
f"and {len(all_groups)} groups from {len(auth_mappings.get('roles', []))} role mappings "
|
|
178
|
+
f"and {len(auth_mappings.get('users', []))} user mappings "
|
|
179
|
+
f"({entries_without_username} entries without usernames created groups only)"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return {"users": all_users, "groups": all_groups}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@timeit
|
|
186
|
+
@aws_handle_regions
|
|
187
|
+
def get_oidc_provider(
|
|
188
|
+
boto3_session: boto3.session.Session,
|
|
189
|
+
region: str,
|
|
190
|
+
cluster_name: str,
|
|
191
|
+
) -> List[Dict[str, Any]]:
|
|
192
|
+
"""
|
|
193
|
+
Get external OIDC identity provider configurations for an EKS cluster.
|
|
194
|
+
|
|
195
|
+
Returns raw AWS API responses for configured external identity providers.
|
|
196
|
+
"""
|
|
197
|
+
client = boto3_session.client("eks", region_name=region)
|
|
198
|
+
oidc_providers = []
|
|
199
|
+
|
|
200
|
+
# Extract just the cluster name from ARN if needed
|
|
201
|
+
# ARN format: arn:aws:eks:region:account:cluster/cluster-name
|
|
202
|
+
if cluster_name.startswith("arn:aws:eks:"):
|
|
203
|
+
cluster_name = cluster_name.split("/")[-1]
|
|
204
|
+
|
|
205
|
+
# Get configured external identity provider configs
|
|
206
|
+
configs_response = client.list_identity_provider_configs(clusterName=cluster_name)
|
|
207
|
+
|
|
208
|
+
for config in configs_response["identityProviderConfigs"]:
|
|
209
|
+
if config["type"] == "oidc":
|
|
210
|
+
# Get detailed config for this OIDC provider
|
|
211
|
+
detail_response = client.describe_identity_provider_config(
|
|
212
|
+
clusterName=cluster_name,
|
|
213
|
+
identityProviderConfig={"type": "oidc", "name": config["name"]},
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
oidc_providers.append(detail_response["identityProviderConfig"]["oidc"])
|
|
217
|
+
|
|
218
|
+
return oidc_providers
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def transform_oidc_provider(
|
|
222
|
+
oidc_providers: List[Dict[str, Any]],
|
|
223
|
+
cluster_name: str,
|
|
224
|
+
) -> List[Dict[str, Any]]:
|
|
225
|
+
"""
|
|
226
|
+
Transform raw AWS OIDC provider data into standardized format.
|
|
227
|
+
|
|
228
|
+
Takes raw AWS API responses and creates OIDC provider nodes that match
|
|
229
|
+
the KubernetesOIDCProvider data model for infrastructure metadata.
|
|
230
|
+
"""
|
|
231
|
+
transformed_providers = []
|
|
232
|
+
|
|
233
|
+
for provider in oidc_providers:
|
|
234
|
+
# Extract fields from raw AWS API response
|
|
235
|
+
provider_name = provider["identityProviderConfigName"]
|
|
236
|
+
issuer_url = provider["issuerUrl"]
|
|
237
|
+
|
|
238
|
+
# Create a unique ID for the external OIDC provider
|
|
239
|
+
# Format: cluster_name/oidc/provider_name
|
|
240
|
+
provider_id = f"{cluster_name}/oidc/{provider_name}"
|
|
241
|
+
|
|
242
|
+
transformed_provider = {
|
|
243
|
+
"id": provider_id,
|
|
244
|
+
"issuer_url": issuer_url,
|
|
245
|
+
"cluster_name": cluster_name,
|
|
246
|
+
"k8s_platform": "eks",
|
|
247
|
+
"client_id": provider.get("clientId", ""),
|
|
248
|
+
"status": provider.get("status", "UNKNOWN"),
|
|
249
|
+
"name": provider_name,
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
transformed_providers.append(transformed_provider)
|
|
253
|
+
|
|
254
|
+
return transformed_providers
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def load_oidc_provider(
|
|
258
|
+
neo4j_session: neo4j.Session,
|
|
259
|
+
oidc_providers: List[Dict[str, Any]],
|
|
260
|
+
update_tag: int,
|
|
261
|
+
cluster_id: str,
|
|
262
|
+
cluster_name: str,
|
|
263
|
+
) -> None:
|
|
264
|
+
"""
|
|
265
|
+
Load OIDC providers and their relationships to users and groups into Neo4j.
|
|
266
|
+
"""
|
|
267
|
+
logger.info(f"Loading {len(oidc_providers)} EKS OIDC providers")
|
|
268
|
+
load(
|
|
269
|
+
neo4j_session,
|
|
270
|
+
KubernetesOIDCProviderSchema(),
|
|
271
|
+
oidc_providers,
|
|
272
|
+
lastupdated=update_tag,
|
|
273
|
+
CLUSTER_ID=cluster_id,
|
|
274
|
+
CLUSTER_NAME=cluster_name,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def load_aws_auth_mappings(
|
|
279
|
+
neo4j_session: neo4j.Session,
|
|
280
|
+
users: List[Dict[str, Any]],
|
|
281
|
+
groups: List[Dict[str, Any]],
|
|
282
|
+
update_tag: int,
|
|
283
|
+
cluster_id: str,
|
|
284
|
+
cluster_name: str,
|
|
285
|
+
) -> None:
|
|
286
|
+
"""
|
|
287
|
+
Load Kubernetes Users/Groups with AWS Role and User relationships into Neo4j using schema-based loading.
|
|
288
|
+
"""
|
|
289
|
+
logger.info(f"Loading {len(users)} Kubernetes Users with AWS mappings")
|
|
290
|
+
|
|
291
|
+
# Load Kubernetes Users with AWS relationships
|
|
292
|
+
if users:
|
|
293
|
+
load(
|
|
294
|
+
neo4j_session,
|
|
295
|
+
KubernetesUserSchema(),
|
|
296
|
+
users,
|
|
297
|
+
lastupdated=update_tag,
|
|
298
|
+
CLUSTER_ID=cluster_id,
|
|
299
|
+
CLUSTER_NAME=cluster_name,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
logger.info(f"Loading {len(groups)} Kubernetes Groups with AWS mappings")
|
|
303
|
+
|
|
304
|
+
# Load Kubernetes Groups with AWS relationships
|
|
305
|
+
if groups:
|
|
306
|
+
load(
|
|
307
|
+
neo4j_session,
|
|
308
|
+
KubernetesGroupSchema(),
|
|
309
|
+
groups,
|
|
310
|
+
lastupdated=update_tag,
|
|
311
|
+
CLUSTER_ID=cluster_id,
|
|
312
|
+
CLUSTER_NAME=cluster_name,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def cleanup(
|
|
317
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
318
|
+
) -> None:
|
|
319
|
+
logger.debug("Running cleanup job for EKS AWS Role and User relationships")
|
|
320
|
+
|
|
321
|
+
cleanup_job = GraphJob.from_node_schema(
|
|
322
|
+
KubernetesUserSchema(), common_job_parameters
|
|
323
|
+
)
|
|
324
|
+
cleanup_job.run(neo4j_session)
|
|
325
|
+
|
|
326
|
+
cleanup_job = GraphJob.from_node_schema(
|
|
327
|
+
KubernetesGroupSchema(), common_job_parameters
|
|
328
|
+
)
|
|
329
|
+
cleanup_job.run(neo4j_session)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def sync(
|
|
333
|
+
neo4j_session: neo4j.Session,
|
|
334
|
+
k8s_client: K8sClient,
|
|
335
|
+
boto3_session: boto3.session.Session,
|
|
336
|
+
region: str,
|
|
337
|
+
update_tag: int,
|
|
338
|
+
cluster_id: str,
|
|
339
|
+
cluster_name: str,
|
|
340
|
+
) -> None:
|
|
341
|
+
"""
|
|
342
|
+
Sync EKS identity providers:
|
|
343
|
+
1. AWS IAM role and user mappings (aws-auth ConfigMap)
|
|
344
|
+
2. External OIDC providers (EKS API)
|
|
345
|
+
"""
|
|
346
|
+
logger.info(f"Starting EKS identity provider sync for cluster {cluster_name}")
|
|
347
|
+
|
|
348
|
+
# 1. Sync AWS IAM mappings (aws-auth ConfigMap)
|
|
349
|
+
logger.info("Syncing AWS IAM mappings from aws-auth ConfigMap")
|
|
350
|
+
configmap = get_aws_auth_configmap(k8s_client)
|
|
351
|
+
auth_mappings = parse_aws_auth_map(configmap)
|
|
352
|
+
|
|
353
|
+
# Transform and load both role and user mappings
|
|
354
|
+
if auth_mappings.get("roles") or auth_mappings.get("users"):
|
|
355
|
+
transformed_data = transform_aws_auth_mappings(auth_mappings, cluster_name)
|
|
356
|
+
load_aws_auth_mappings(
|
|
357
|
+
neo4j_session,
|
|
358
|
+
transformed_data["users"],
|
|
359
|
+
transformed_data["groups"],
|
|
360
|
+
update_tag,
|
|
361
|
+
cluster_id,
|
|
362
|
+
cluster_name,
|
|
363
|
+
)
|
|
364
|
+
logger.info(
|
|
365
|
+
f"Successfully synced {len(auth_mappings.get('roles', []))} AWS IAM role mappings "
|
|
366
|
+
f"and {len(auth_mappings.get('users', []))} AWS IAM user mappings"
|
|
367
|
+
)
|
|
368
|
+
else:
|
|
369
|
+
logger.info("No role or user mappings found in aws-auth ConfigMap")
|
|
370
|
+
|
|
371
|
+
# 2. Sync External OIDC providers (EKS API)
|
|
372
|
+
logger.info("Syncing external OIDC providers from EKS API")
|
|
373
|
+
|
|
374
|
+
# Get OIDC providers from EKS API
|
|
375
|
+
oidc_provider = get_oidc_provider(boto3_session, region, cluster_name)
|
|
376
|
+
|
|
377
|
+
if oidc_provider:
|
|
378
|
+
# Transform OIDC providers (infrastructure metadata only)
|
|
379
|
+
transformed_oidc_provider = transform_oidc_provider(oidc_provider, cluster_name)
|
|
380
|
+
|
|
381
|
+
# Load OIDC providers
|
|
382
|
+
load_oidc_provider(
|
|
383
|
+
neo4j_session,
|
|
384
|
+
transformed_oidc_provider,
|
|
385
|
+
update_tag,
|
|
386
|
+
cluster_id,
|
|
387
|
+
cluster_name,
|
|
388
|
+
)
|
|
389
|
+
logger.info(f"Successfully synced {len(oidc_provider)} external OIDC provider")
|
|
390
|
+
else:
|
|
391
|
+
logger.info("No external OIDC provider found for cluster")
|
|
392
|
+
|
|
393
|
+
# Cleanup
|
|
394
|
+
common_job_parameters = {
|
|
395
|
+
"UPDATE_TAG": update_tag,
|
|
396
|
+
"CLUSTER_ID": cluster_id,
|
|
397
|
+
}
|
|
398
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
399
|
+
|
|
400
|
+
logger.info(
|
|
401
|
+
f"Successfully completed EKS identity provider sync for cluster {cluster_name}"
|
|
402
|
+
)
|