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
|
@@ -7,7 +7,9 @@ import neo4j
|
|
|
7
7
|
from azure.core.exceptions import HttpResponseError
|
|
8
8
|
from azure.mgmt.resource import SubscriptionClient
|
|
9
9
|
|
|
10
|
-
from cartography.
|
|
10
|
+
from cartography.client.core.tx import load
|
|
11
|
+
from cartography.graph.job import GraphJob
|
|
12
|
+
from cartography.models.azure.subscription import AzureSubscriptionSchema
|
|
11
13
|
from cartography.util import timeit
|
|
12
14
|
|
|
13
15
|
from .util.credentials import Credentials
|
|
@@ -18,19 +20,16 @@ logger = logging.getLogger(__name__)
|
|
|
18
20
|
def get_all_azure_subscriptions(credentials: Credentials) -> List[Dict]:
|
|
19
21
|
try:
|
|
20
22
|
# Create the client
|
|
21
|
-
client = SubscriptionClient(credentials.
|
|
23
|
+
client = SubscriptionClient(credentials.credential)
|
|
22
24
|
|
|
23
25
|
# Get all the accessible subscriptions
|
|
24
26
|
subs = list(client.subscriptions.list())
|
|
25
27
|
|
|
26
28
|
except HttpResponseError as e:
|
|
27
|
-
|
|
28
|
-
f"
|
|
29
|
-
The provided credentials do not have access to any subscriptions
|
|
30
|
-
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
return []
|
|
29
|
+
raise RuntimeError(
|
|
30
|
+
f"Failed to fetch subscriptions for the credentials. "
|
|
31
|
+
f"The provided credentials do not have access to any subscriptions: {e}",
|
|
32
|
+
) from e
|
|
34
33
|
|
|
35
34
|
subscriptions = []
|
|
36
35
|
for sub in subs:
|
|
@@ -52,19 +51,16 @@ def get_current_azure_subscription(
|
|
|
52
51
|
) -> List[Dict]:
|
|
53
52
|
try:
|
|
54
53
|
# Create the client
|
|
55
|
-
client = SubscriptionClient(credentials.
|
|
54
|
+
client = SubscriptionClient(credentials.credential)
|
|
56
55
|
|
|
57
56
|
# Get all the accessible subscriptions
|
|
58
57
|
sub = client.subscriptions.get(subscription_id)
|
|
59
58
|
|
|
60
59
|
except HttpResponseError as e:
|
|
61
|
-
|
|
62
|
-
f"
|
|
63
|
-
The provided credentials do not have access to this subscription: {subscription_id}
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
return []
|
|
60
|
+
raise RuntimeError(
|
|
61
|
+
f"Failed to fetch subscription for the credentials. "
|
|
62
|
+
f"The provided credentials do not have access to this subscription: {subscription_id}: {e}",
|
|
63
|
+
) from e
|
|
68
64
|
|
|
69
65
|
return [
|
|
70
66
|
{
|
|
@@ -82,36 +78,18 @@ def load_azure_subscriptions(
|
|
|
82
78
|
subscriptions: List[Dict],
|
|
83
79
|
update_tag: int,
|
|
84
80
|
) -> None:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
SET as.lastupdated = $update_tag, as.name = $SUBSCRIPTION_NAME, as.state = $SUBSCRIPTION_STATE
|
|
93
|
-
WITH as, at
|
|
94
|
-
MERGE (at)-[r:RESOURCE]->(as)
|
|
95
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
96
|
-
SET r.lastupdated = $update_tag;
|
|
97
|
-
"""
|
|
98
|
-
for sub in subscriptions:
|
|
99
|
-
neo4j_session.run(
|
|
100
|
-
query,
|
|
101
|
-
TENANT_ID=tenant_id,
|
|
102
|
-
SUBSCRIPTION_ID=sub["subscriptionId"],
|
|
103
|
-
SUBSCRIPTION_PATH=sub["id"],
|
|
104
|
-
SUBSCRIPTION_NAME=sub["displayName"],
|
|
105
|
-
SUBSCRIPTION_STATE=sub["state"],
|
|
106
|
-
update_tag=update_tag,
|
|
107
|
-
)
|
|
81
|
+
load(
|
|
82
|
+
neo4j_session,
|
|
83
|
+
AzureSubscriptionSchema(),
|
|
84
|
+
subscriptions,
|
|
85
|
+
lastupdated=update_tag,
|
|
86
|
+
TENANT_ID=tenant_id,
|
|
87
|
+
)
|
|
108
88
|
|
|
109
89
|
|
|
110
90
|
def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
111
|
-
|
|
112
|
-
"azure_subscriptions_cleanup.json",
|
|
91
|
+
GraphJob.from_node_schema(AzureSubscriptionSchema(), common_job_parameters).run(
|
|
113
92
|
neo4j_session,
|
|
114
|
-
common_job_parameters,
|
|
115
93
|
)
|
|
116
94
|
|
|
117
95
|
|
|
@@ -1,58 +1,67 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Dict
|
|
3
|
+
from typing import Optional
|
|
3
4
|
|
|
4
5
|
import neo4j
|
|
5
6
|
|
|
6
|
-
from cartography.
|
|
7
|
-
from cartography.
|
|
7
|
+
from cartography.client.core.tx import load
|
|
8
|
+
from cartography.graph.job import GraphJob
|
|
9
|
+
from cartography.models.azure.principal import AzurePrincipalSchema
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
# Import the new, separated schemas
|
|
12
|
+
from cartography.models.azure.tenant import AzureTenantSchema
|
|
13
|
+
from cartography.util import timeit
|
|
10
14
|
|
|
11
15
|
logger = logging.getLogger(__name__)
|
|
12
16
|
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
return credentials.get_tenant_id()
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
@timeit
|
|
18
19
|
def load_azure_tenant(
|
|
19
20
|
neo4j_session: neo4j.Session,
|
|
20
21
|
tenant_id: str,
|
|
21
|
-
current_user: str,
|
|
22
|
+
current_user: Optional[str],
|
|
22
23
|
update_tag: int,
|
|
23
24
|
) -> None:
|
|
24
|
-
query = """
|
|
25
|
-
MERGE (at:AzureTenant{id: $TENANT_ID})
|
|
26
|
-
ON CREATE SET at.firstseen = timestamp()
|
|
27
|
-
SET at.lastupdated = $update_tag
|
|
28
|
-
WITH at
|
|
29
|
-
MERGE (ap:AzurePrincipal{id: $CURRENT_USER})
|
|
30
|
-
ON CREATE SET ap.email = $CURRENT_USER, ap.firstseen = timestamp()
|
|
31
|
-
SET ap.lastupdated = $update_tag
|
|
32
|
-
WITH at, ap
|
|
33
|
-
MERGE (at)-[r:RESOURCE]->(ap)
|
|
34
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
35
|
-
SET r.lastupdated = $update_tag;
|
|
36
25
|
"""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
update_tag=update_tag,
|
|
42
|
-
)
|
|
26
|
+
Ingest the Azure Tenant and, if available, the Azure Principal into Neo4j.
|
|
27
|
+
"""
|
|
28
|
+
tenant_data = {"id": tenant_id}
|
|
29
|
+
load(neo4j_session, AzureTenantSchema(), [tenant_data], lastupdated=update_tag)
|
|
43
30
|
|
|
31
|
+
if current_user:
|
|
32
|
+
principal_data = {"id": current_user}
|
|
33
|
+
load(
|
|
34
|
+
neo4j_session,
|
|
35
|
+
AzurePrincipalSchema(),
|
|
36
|
+
[principal_data],
|
|
37
|
+
lastupdated=update_tag,
|
|
38
|
+
TENANT_ID=tenant_id,
|
|
39
|
+
)
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
|
|
42
|
+
@timeit
|
|
43
|
+
def cleanup_azure_tenant(
|
|
44
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict
|
|
45
|
+
) -> None:
|
|
46
|
+
"""
|
|
47
|
+
Delete stale Azure Tenants and Principals.
|
|
48
|
+
"""
|
|
49
|
+
GraphJob.from_node_schema(AzureTenantSchema(), common_job_parameters).run(
|
|
50
|
+
neo4j_session
|
|
51
|
+
)
|
|
52
|
+
GraphJob.from_node_schema(AzurePrincipalSchema(), common_job_parameters).run(
|
|
53
|
+
neo4j_session
|
|
54
|
+
)
|
|
47
55
|
|
|
48
56
|
|
|
49
57
|
@timeit
|
|
50
58
|
def sync(
|
|
51
59
|
neo4j_session: neo4j.Session,
|
|
52
60
|
tenant_id: str,
|
|
53
|
-
current_user: str,
|
|
61
|
+
current_user: Optional[str],
|
|
54
62
|
update_tag: int,
|
|
55
63
|
common_job_parameters: Dict,
|
|
56
64
|
) -> None:
|
|
65
|
+
logger.info("Syncing Azure tenant '%s'.", tenant_id)
|
|
57
66
|
load_azure_tenant(neo4j_session, tenant_id, current_user, update_tag)
|
|
58
|
-
|
|
67
|
+
cleanup_azure_tenant(neo4j_session, common_job_parameters)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
logger = logging.getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_resource_group_from_id(resource_id: str) -> str:
|
|
7
|
+
"""
|
|
8
|
+
Helper function to parse the resource group name from a full resource ID string.
|
|
9
|
+
e.g. /subscriptions/sub_id/resourceGroups/rg_name/providers/...
|
|
10
|
+
"""
|
|
11
|
+
parts = resource_id.lower().split("/")
|
|
12
|
+
rg_index = parts.index("resourcegroups")
|
|
13
|
+
return parts[rg_index + 1]
|
|
@@ -1,222 +1,97 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from datetime import datetime
|
|
3
|
-
from datetime import timedelta
|
|
4
2
|
from typing import Any
|
|
5
3
|
from typing import Optional
|
|
6
4
|
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
from azure.common.credentials import get_azure_cli_credentials
|
|
10
|
-
from azure.common.credentials import get_cli_profile
|
|
11
|
-
from azure.core.exceptions import HttpResponseError
|
|
5
|
+
import jwt
|
|
6
|
+
from azure.identity import AzureCliCredential
|
|
12
7
|
from azure.identity import ClientSecretCredential
|
|
13
|
-
from
|
|
8
|
+
from azure.mgmt.resource import SubscriptionClient
|
|
14
9
|
|
|
15
10
|
logger = logging.getLogger(__name__)
|
|
16
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_tenant_id_from_token(credential: Any) -> str:
|
|
14
|
+
"""
|
|
15
|
+
A helper function to get the tenant ID from the claims in an access token.
|
|
16
|
+
"""
|
|
17
|
+
token = credential.get_token("https://management.azure.com/.default")
|
|
18
|
+
decoded_token = jwt.decode(token.token, options={"verify_signature": False})
|
|
19
|
+
return decoded_token.get("tid", "")
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
class Credentials:
|
|
23
|
+
"""
|
|
24
|
+
A simple data container for the credential object and its associated IDs.
|
|
25
|
+
"""
|
|
20
26
|
|
|
21
27
|
def __init__(
|
|
22
28
|
self,
|
|
23
|
-
|
|
24
|
-
aad_graph_credentials: Any,
|
|
29
|
+
credential: Any,
|
|
25
30
|
tenant_id: Optional[str] = None,
|
|
26
31
|
subscription_id: Optional[str] = None,
|
|
27
|
-
context: Optional[adal.AuthenticationContext] = None,
|
|
28
|
-
current_user: Optional[str] = None,
|
|
29
32
|
) -> None:
|
|
30
|
-
self.
|
|
31
|
-
self.aad_graph_credentials = (
|
|
32
|
-
aad_graph_credentials # Azure AD Graph API credentials
|
|
33
|
-
)
|
|
33
|
+
self.credential = credential
|
|
34
34
|
self.tenant_id = tenant_id
|
|
35
35
|
self.subscription_id = subscription_id
|
|
36
|
-
self.context = context
|
|
37
|
-
self.current_user = current_user
|
|
38
|
-
|
|
39
|
-
def get_current_user(self) -> Optional[str]:
|
|
40
|
-
return self.current_user
|
|
41
|
-
|
|
42
|
-
def get_tenant_id(self) -> Any:
|
|
43
|
-
if self.tenant_id:
|
|
44
|
-
return self.tenant_id
|
|
45
|
-
elif "tenant_id" in self.aad_graph_credentials.token:
|
|
46
|
-
return self.aad_graph_credentials.token["tenant_id"]
|
|
47
|
-
else:
|
|
48
|
-
# This is a last resort, e.g. for MSI authentication
|
|
49
|
-
try:
|
|
50
|
-
h = {
|
|
51
|
-
"Authorization": "Bearer {}".format(
|
|
52
|
-
self.arm_credentials.token["access_token"],
|
|
53
|
-
),
|
|
54
|
-
}
|
|
55
|
-
r = requests.get(
|
|
56
|
-
"https://management.azure.com/tenants?api-version=2020-01-01",
|
|
57
|
-
headers=h,
|
|
58
|
-
)
|
|
59
|
-
r2 = r.json()
|
|
60
|
-
return r2.get("value")[0].get("tenantId")
|
|
61
|
-
except requests.ConnectionError as e:
|
|
62
|
-
logger.error(f"Unable to infer tenant ID: {e}")
|
|
63
|
-
return None
|
|
64
|
-
|
|
65
|
-
def get_credentials(self, resource: str) -> Any:
|
|
66
|
-
if resource == "arm":
|
|
67
|
-
self.arm_credentials = self.get_fresh_credentials(self.arm_credentials)
|
|
68
|
-
return self.arm_credentials
|
|
69
|
-
elif resource == "aad_graph":
|
|
70
|
-
self.aad_graph_credentials = self.get_fresh_credentials(
|
|
71
|
-
self.aad_graph_credentials,
|
|
72
|
-
)
|
|
73
|
-
return self.aad_graph_credentials
|
|
74
|
-
else:
|
|
75
|
-
raise Exception("Invalid credentials resource type")
|
|
76
|
-
|
|
77
|
-
def get_fresh_credentials(self, credentials: Any) -> Any:
|
|
78
|
-
"""
|
|
79
|
-
Check if credentials are outdated and if so refresh them.
|
|
80
|
-
"""
|
|
81
|
-
if self.context and hasattr(credentials, "token"):
|
|
82
|
-
expiration_datetime = datetime.fromtimestamp(
|
|
83
|
-
credentials.token["expires_on"],
|
|
84
|
-
)
|
|
85
|
-
current_datetime = datetime.now()
|
|
86
|
-
expiration_delta = expiration_datetime - current_datetime
|
|
87
|
-
if expiration_delta < timedelta(minutes=5):
|
|
88
|
-
return self.refresh_credential(credentials)
|
|
89
|
-
return credentials
|
|
90
|
-
|
|
91
|
-
def refresh_credential(self, credentials: Any) -> Any:
|
|
92
|
-
"""
|
|
93
|
-
Refresh credentials
|
|
94
|
-
"""
|
|
95
|
-
logger.debug("Refreshing credentials")
|
|
96
|
-
authority_uri = AUTHORITY_HOST_URI + "/" + self.get_tenant_id()
|
|
97
|
-
if self.context:
|
|
98
|
-
existing_cache = self.context.cache
|
|
99
|
-
context = adal.AuthenticationContext(authority_uri, cache=existing_cache)
|
|
100
|
-
|
|
101
|
-
else:
|
|
102
|
-
context = adal.AuthenticationContext(authority_uri)
|
|
103
|
-
|
|
104
|
-
new_token = context.acquire_token(
|
|
105
|
-
credentials.token["resource"],
|
|
106
|
-
credentials.token["user_id"],
|
|
107
|
-
credentials.token["_client_id"],
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
new_credentials = AADTokenCredentials(
|
|
111
|
-
new_token,
|
|
112
|
-
credentials.token.get("_client_id"),
|
|
113
|
-
)
|
|
114
|
-
return new_credentials
|
|
115
36
|
|
|
116
37
|
|
|
117
38
|
class Authenticator:
|
|
118
39
|
|
|
119
|
-
def authenticate_cli(self) -> Credentials:
|
|
40
|
+
def authenticate_cli(self) -> Optional[Credentials]:
|
|
120
41
|
"""
|
|
121
|
-
Implements authentication
|
|
42
|
+
Implements authentication using the Azure CLI with the modern library.
|
|
122
43
|
"""
|
|
44
|
+
logging.getLogger("urllib3").setLevel(logging.ERROR)
|
|
45
|
+
logging.getLogger(
|
|
46
|
+
"azure.core.pipeline.policies.http_logging_policy",
|
|
47
|
+
).setLevel(logging.ERROR)
|
|
123
48
|
try:
|
|
49
|
+
credential = AzureCliCredential()
|
|
124
50
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
logging.getLogger("msrestazure.azure_active_directory").setLevel(
|
|
129
|
-
logging.ERROR,
|
|
130
|
-
)
|
|
131
|
-
logging.getLogger("urllib3").setLevel(logging.ERROR)
|
|
132
|
-
logging.getLogger(
|
|
133
|
-
"azure.core.pipeline.policies.http_logging_policy",
|
|
134
|
-
).setLevel(logging.ERROR)
|
|
51
|
+
subscription_client = SubscriptionClient(credential)
|
|
52
|
+
subscription = next(subscription_client.subscriptions.list())
|
|
53
|
+
subscription_id = subscription.subscription_id
|
|
135
54
|
|
|
136
|
-
|
|
137
|
-
with_tenant=True,
|
|
138
|
-
)
|
|
139
|
-
aad_graph_credentials, placeholder_1, placeholder_2 = (
|
|
140
|
-
get_azure_cli_credentials(
|
|
141
|
-
with_tenant=True,
|
|
142
|
-
resource="https://graph.windows.net",
|
|
143
|
-
)
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
profile = get_cli_profile()
|
|
55
|
+
tenant_id = _get_tenant_id_from_token(credential)
|
|
147
56
|
|
|
148
57
|
return Credentials(
|
|
149
|
-
|
|
150
|
-
aad_graph_credentials,
|
|
58
|
+
credential=credential,
|
|
151
59
|
tenant_id=tenant_id,
|
|
152
|
-
current_user=profile.get_current_account_user(),
|
|
153
60
|
subscription_id=subscription_id,
|
|
154
61
|
)
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
):
|
|
161
|
-
logger.error(
|
|
162
|
-
f"You are likely authenticating with a Microsoft Account. \
|
|
163
|
-
This authentication mode only supports Azure Active Directory principal authentication.\
|
|
164
|
-
{e}",
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
raise e
|
|
62
|
+
except Exception as e:
|
|
63
|
+
logger.error(
|
|
64
|
+
f"Failed to authenticate with Azure CLI. Have you run 'az login'? Details: {e}"
|
|
65
|
+
)
|
|
66
|
+
return None
|
|
168
67
|
|
|
169
68
|
def authenticate_sp(
|
|
170
69
|
self,
|
|
171
70
|
tenant_id: Optional[str] = None,
|
|
172
71
|
client_id: Optional[str] = None,
|
|
173
72
|
client_secret: Optional[str] = None,
|
|
174
|
-
|
|
73
|
+
subscription_id: Optional[str] = None,
|
|
74
|
+
) -> Optional[Credentials]:
|
|
175
75
|
"""
|
|
176
|
-
Implements authentication
|
|
76
|
+
Implements authentication using a Service Principal with the modern library.
|
|
177
77
|
"""
|
|
178
78
|
try:
|
|
179
|
-
|
|
180
|
-
# Set logging level to error for libraries as otherwise generates a lot of warnings
|
|
181
|
-
logging.getLogger("adal-python").setLevel(logging.ERROR)
|
|
182
|
-
logging.getLogger("msrest").setLevel(logging.ERROR)
|
|
183
|
-
logging.getLogger("msrestazure.azure_active_directory").setLevel(
|
|
184
|
-
logging.ERROR,
|
|
185
|
-
)
|
|
186
|
-
logging.getLogger("urllib3").setLevel(logging.ERROR)
|
|
187
|
-
logging.getLogger(
|
|
188
|
-
"azure.core.pipeline.policies.http_logging_policy",
|
|
189
|
-
).setLevel(logging.ERROR)
|
|
190
|
-
|
|
191
|
-
arm_credentials = ClientSecretCredential(
|
|
192
|
-
client_id=client_id,
|
|
193
|
-
client_secret=client_secret,
|
|
194
|
-
tenant_id=tenant_id,
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
aad_graph_credentials = ClientSecretCredential(
|
|
79
|
+
credential = ClientSecretCredential(
|
|
198
80
|
client_id=client_id,
|
|
199
81
|
client_secret=client_secret,
|
|
200
82
|
tenant_id=tenant_id,
|
|
201
|
-
resource="https://graph.windows.net",
|
|
202
83
|
)
|
|
203
|
-
|
|
204
84
|
return Credentials(
|
|
205
|
-
|
|
206
|
-
aad_graph_credentials,
|
|
85
|
+
credential=credential,
|
|
207
86
|
tenant_id=tenant_id,
|
|
208
|
-
|
|
87
|
+
subscription_id=subscription_id,
|
|
209
88
|
)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
{e}",
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
raise e
|
|
89
|
+
except Exception as e:
|
|
90
|
+
logger.error(
|
|
91
|
+
(
|
|
92
|
+
"Failed to authenticate with Service Principal. "
|
|
93
|
+
"Please ensure the tenant ID, client ID, and client secret are correct. Details: %s"
|
|
94
|
+
),
|
|
95
|
+
e,
|
|
96
|
+
)
|
|
97
|
+
return None
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
logger = logging.getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def transform_tags(
|
|
7
|
+
resource_list: list[dict], subscription_id: str, resource_id_field: str = "id"
|
|
8
|
+
) -> list[dict]:
|
|
9
|
+
"""
|
|
10
|
+
Transforms tags from a list of Azure resources into a standardized list of tag dictionaries.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
resource_list: List of Azure resources with tags
|
|
14
|
+
subscription_id: The Azure subscription ID to scope the tags
|
|
15
|
+
resource_id_field: Field name containing the resource ID (default: "id")
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
List of tag dictionaries with subscription-scoped IDs
|
|
19
|
+
"""
|
|
20
|
+
tags_list = []
|
|
21
|
+
for resource in resource_list:
|
|
22
|
+
resource_id = resource.get(resource_id_field)
|
|
23
|
+
tags = resource.get("tags")
|
|
24
|
+
|
|
25
|
+
if not resource_id or not tags:
|
|
26
|
+
continue
|
|
27
|
+
|
|
28
|
+
for key, value in tags.items():
|
|
29
|
+
# Generate the deterministic ID scoped to subscription: "{subscription_id}|{key}:{value}"
|
|
30
|
+
tag_id = f"{subscription_id}|{key}:{value}"
|
|
31
|
+
tags_list.append(
|
|
32
|
+
{
|
|
33
|
+
"id": tag_id,
|
|
34
|
+
"key": key,
|
|
35
|
+
"value": value,
|
|
36
|
+
"subscription_id": subscription_id,
|
|
37
|
+
"resource_id": resource_id,
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return tags_list
|
|
@@ -3,6 +3,7 @@ from typing import List
|
|
|
3
3
|
|
|
4
4
|
import neo4j
|
|
5
5
|
|
|
6
|
+
from cartography.client.core.tx import run_write_query
|
|
6
7
|
from cartography.config import Config
|
|
7
8
|
from cartography.util import load_resource_binary
|
|
8
9
|
|
|
@@ -23,4 +24,4 @@ def run(neo4j_session: neo4j.Session, config: Config) -> None:
|
|
|
23
24
|
logger.info("Creating indexes for cartography node types.")
|
|
24
25
|
for statement in get_index_statements():
|
|
25
26
|
logger.debug("Executing statement: %s", statement)
|
|
26
|
-
neo4j_session
|
|
27
|
+
run_write_query(neo4j_session, statement)
|
|
@@ -6,6 +6,7 @@ import neo4j
|
|
|
6
6
|
from falconpy.oauth2 import OAuth2
|
|
7
7
|
from falconpy.spotlight_vulnerabilities import Spotlight_Vulnerabilities
|
|
8
8
|
|
|
9
|
+
from cartography.client.core.tx import run_write_query
|
|
9
10
|
from cartography.util import timeit
|
|
10
11
|
|
|
11
12
|
logger = logging.getLogger(__name__)
|
|
@@ -79,7 +80,8 @@ def load_vulnerability_data(
|
|
|
79
80
|
cves.append(cve)
|
|
80
81
|
vuln["host_info_local_ip"] = item.get("host_info", {}).get("local_ip")
|
|
81
82
|
vulns.append(vuln)
|
|
82
|
-
|
|
83
|
+
run_write_query(
|
|
84
|
+
neo4j_session,
|
|
83
85
|
ingestion_cypher_query,
|
|
84
86
|
Vulnerabilities=vulns,
|
|
85
87
|
update_tag=update_tag,
|
|
@@ -106,7 +108,8 @@ def _load_cves(neo4j_session: neo4j.Session, data: List[Dict], update_tag: int)
|
|
|
106
108
|
ON CREATE SET hc.firstseen = timestamp()
|
|
107
109
|
SET hc.lastupdated = $update_tag
|
|
108
110
|
"""
|
|
109
|
-
|
|
111
|
+
run_write_query(
|
|
112
|
+
neo4j_session,
|
|
110
113
|
ingestion_cypher_query,
|
|
111
114
|
cves=data,
|
|
112
115
|
update_tag=update_tag,
|
cartography/intel/dns.py
CHANGED
|
@@ -8,6 +8,7 @@ import dns.rdatatype
|
|
|
8
8
|
import dns.resolver
|
|
9
9
|
import neo4j
|
|
10
10
|
|
|
11
|
+
from cartography.client.core.tx import run_write_query
|
|
11
12
|
from cartography.util import timeit
|
|
12
13
|
|
|
13
14
|
logger = logging.getLogger(__name__)
|
|
@@ -104,7 +105,8 @@ def _link_ip_to_A_record(
|
|
|
104
105
|
SET r.lastupdated = $update_tag
|
|
105
106
|
"""
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
run_write_query(
|
|
109
|
+
neo4j_session,
|
|
108
110
|
ingest,
|
|
109
111
|
ParentId=parent_record,
|
|
110
112
|
IP_LIST=ip_list,
|
|
@@ -151,7 +153,8 @@ def ingest_dns_record(
|
|
|
151
153
|
|
|
152
154
|
record_id = f"{name}+{type}"
|
|
153
155
|
|
|
154
|
-
|
|
156
|
+
run_write_query(
|
|
157
|
+
neo4j_session,
|
|
155
158
|
template.safe_substitute(
|
|
156
159
|
record_label=record_label,
|
|
157
160
|
dns_node_additional_label=dns_node_additional_label,
|