cartography 0.93.0rc1__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/__main__.py +1 -2
- cartography/_version.py +34 -0
- cartography/cli.py +903 -225
- cartography/client/aws/__init__.py +19 -0
- cartography/client/aws/ecr.py +51 -0
- cartography/client/core/tx.py +400 -27
- cartography/config.py +215 -10
- cartography/data/azure_permission_relationships.yaml +20 -0
- cartography/data/gcp_permission_relationships.yaml +21 -0
- cartography/data/indexes.cypher +1 -200
- cartography/data/jobs/analysis/aws_ec2_asset_exposure.json +17 -2
- cartography/data/jobs/analysis/aws_ec2_keypair_analysis.json +2 -2
- cartography/data/jobs/analysis/gcp_compute_asset_inet_exposure.json +1 -1
- cartography/data/jobs/analysis/keycloak_inheritance.json +30 -0
- cartography/data/jobs/cleanup/crowdstrike_import_cleanup.json +0 -5
- cartography/data/jobs/cleanup/gcp_compute_vpc_cleanup.json +0 -12
- cartography/data/jobs/cleanup/github_repos_cleanup.json +27 -0
- cartography/data/jobs/scoped_analysis/aws_ec2_iaminstanceprofile.json +15 -0
- cartography/data/jobs/scoped_analysis/semgrep_sca_risk_analysis.json +13 -13
- cartography/driftdetect/__main__.py +1 -2
- cartography/driftdetect/add_shortcut.py +10 -2
- cartography/driftdetect/cli.py +72 -75
- cartography/driftdetect/detect_deviations.py +7 -3
- cartography/driftdetect/get_states.py +20 -8
- cartography/driftdetect/model.py +5 -5
- cartography/driftdetect/serializers.py +8 -6
- cartography/driftdetect/storage.py +2 -2
- cartography/graph/cleanupbuilder.py +255 -35
- cartography/graph/job.py +104 -20
- cartography/graph/querybuilder.py +689 -91
- cartography/graph/statement.py +49 -36
- 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/analysis.py +4 -1
- cartography/intel/anthropic/__init__.py +62 -0
- cartography/intel/anthropic/apikeys.py +72 -0
- cartography/intel/anthropic/users.py +75 -0
- cartography/intel/anthropic/util.py +51 -0
- cartography/intel/anthropic/workspaces.py +95 -0
- cartography/intel/aws/__init__.py +137 -59
- cartography/intel/aws/acm.py +124 -0
- cartography/intel/aws/apigateway.py +482 -217
- cartography/intel/aws/apigatewayv2.py +116 -0
- cartography/intel/aws/cloudtrail.py +105 -0
- cartography/intel/aws/cloudtrail_management_events.py +962 -0
- cartography/intel/aws/cloudwatch.py +239 -0
- cartography/intel/aws/codebuild.py +132 -0
- cartography/intel/aws/cognito.py +201 -0
- cartography/intel/aws/config.py +63 -23
- cartography/intel/aws/dynamodb.py +108 -40
- cartography/intel/aws/ec2/__init__.py +2 -2
- cartography/intel/aws/ec2/auto_scaling_groups.py +254 -189
- cartography/intel/aws/ec2/elastic_ip_addresses.py +44 -14
- cartography/intel/aws/ec2/images.py +74 -39
- cartography/intel/aws/ec2/instances.py +262 -137
- cartography/intel/aws/ec2/internet_gateways.py +44 -13
- cartography/intel/aws/ec2/key_pairs.py +72 -39
- cartography/intel/aws/ec2/launch_templates.py +143 -66
- cartography/intel/aws/ec2/load_balancer_v2s.py +119 -45
- cartography/intel/aws/ec2/load_balancers.py +165 -147
- cartography/intel/aws/ec2/network_acls.py +233 -0
- cartography/intel/aws/ec2/network_interfaces.py +150 -87
- cartography/intel/aws/ec2/reserved_instances.py +48 -17
- cartography/intel/aws/ec2/route_tables.py +327 -0
- cartography/intel/aws/ec2/security_groups.py +189 -121
- cartography/intel/aws/ec2/snapshots.py +93 -91
- cartography/intel/aws/ec2/subnets.py +70 -58
- cartography/intel/aws/ec2/tgw.py +111 -39
- cartography/intel/aws/ec2/util.py +1 -1
- cartography/intel/aws/ec2/volumes.py +69 -41
- cartography/intel/aws/ec2/vpc.py +157 -116
- cartography/intel/aws/ec2/vpc_peerings.py +317 -121
- cartography/intel/aws/ecr.py +336 -93
- cartography/intel/aws/ecr_image_layers.py +923 -0
- cartography/intel/aws/ecs.py +310 -403
- cartography/intel/aws/efs.py +261 -0
- cartography/intel/aws/eks.py +55 -29
- cartography/intel/aws/elasticache.py +130 -83
- cartography/intel/aws/elasticsearch.py +70 -24
- cartography/intel/aws/emr.py +61 -23
- 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 +978 -464
- cartography/intel/aws/iam_instance_profiles.py +73 -0
- cartography/intel/aws/identitycenter.py +847 -0
- cartography/intel/aws/inspector.py +330 -133
- cartography/intel/aws/kms.py +235 -209
- cartography/intel/aws/lambda_function.py +328 -176
- cartography/intel/aws/organizations.py +40 -19
- cartography/intel/aws/permission_relationships.py +144 -68
- cartography/intel/aws/rds.py +467 -412
- cartography/intel/aws/redshift.py +116 -50
- cartography/intel/aws/resourcegroupstaggingapi.py +198 -82
- cartography/intel/aws/resources.py +80 -42
- cartography/intel/aws/route53.py +419 -318
- cartography/intel/aws/s3.py +489 -96
- cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
- cartography/intel/aws/secretsmanager.py +217 -40
- cartography/intel/aws/securityhub.py +23 -10
- cartography/intel/aws/sns.py +226 -0
- cartography/intel/aws/sqs.py +74 -96
- cartography/intel/aws/ssm.py +142 -33
- cartography/intel/aws/util/arns.py +7 -7
- cartography/intel/aws/util/common.py +31 -4
- cartography/intel/azure/__init__.py +259 -46
- cartography/intel/azure/aks.py +175 -0
- cartography/intel/azure/app_service.py +105 -0
- cartography/intel/azure/compute.py +141 -120
- cartography/intel/azure/container_instances.py +95 -0
- cartography/intel/azure/cosmosdb.py +706 -519
- 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 +436 -392
- cartography/intel/azure/storage.py +467 -335
- cartography/intel/azure/subscription.py +49 -55
- cartography/intel/azure/tenant.py +46 -28
- cartography/intel/azure/util/common.py +13 -0
- cartography/intel/azure/util/credentials.py +58 -143
- cartography/intel/azure/util/tag.py +41 -0
- cartography/intel/bigfix/__init__.py +2 -2
- cartography/intel/bigfix/computers.py +93 -65
- cartography/intel/cloudflare/__init__.py +74 -0
- cartography/intel/cloudflare/accounts.py +57 -0
- cartography/intel/cloudflare/dnsrecords.py +64 -0
- cartography/intel/cloudflare/members.py +75 -0
- cartography/intel/cloudflare/roles.py +65 -0
- cartography/intel/cloudflare/zones.py +64 -0
- cartography/intel/create_indexes.py +5 -3
- cartography/intel/crowdstrike/__init__.py +26 -12
- cartography/intel/crowdstrike/endpoints.py +17 -45
- cartography/intel/crowdstrike/spotlight.py +13 -5
- cartography/intel/cve/__init__.py +91 -26
- cartography/intel/cve/feed.py +77 -56
- cartography/intel/digitalocean/__init__.py +22 -13
- cartography/intel/digitalocean/compute.py +75 -108
- cartography/intel/digitalocean/management.py +44 -80
- cartography/intel/digitalocean/platform.py +48 -43
- cartography/intel/dns.py +41 -12
- cartography/intel/duo/__init__.py +21 -16
- cartography/intel/duo/api_host.py +14 -9
- cartography/intel/duo/endpoints.py +50 -45
- cartography/intel/duo/groups.py +18 -14
- cartography/intel/duo/phones.py +37 -34
- cartography/intel/duo/tokens.py +26 -23
- cartography/intel/duo/users.py +54 -50
- cartography/intel/duo/web_authn_credentials.py +30 -25
- cartography/intel/entra/__init__.py +160 -0
- 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 +136 -0
- cartography/intel/entra/service_principals.py +217 -0
- cartography/intel/entra/users.py +259 -0
- cartography/intel/gcp/__init__.py +381 -175
- 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 +521 -325
- 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 +134 -179
- cartography/intel/gcp/gke.py +100 -107
- cartography/intel/gcp/iam.py +262 -0
- cartography/intel/gcp/permission_relationships.py +394 -0
- cartography/intel/gcp/policy_bindings.py +225 -0
- cartography/intel/gcp/storage.py +103 -158
- cartography/intel/github/__init__.py +66 -27
- cartography/intel/github/commits.py +423 -0
- cartography/intel/github/repos.py +871 -160
- cartography/intel/github/teams.py +386 -53
- cartography/intel/github/users.py +214 -49
- cartography/intel/github/util.py +50 -35
- 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 +101 -42
- cartography/intel/gsuite/groups.py +291 -0
- cartography/intel/gsuite/users.py +142 -0
- cartography/intel/jamf/__init__.py +19 -1
- cartography/intel/jamf/computers.py +37 -8
- cartography/intel/jamf/util.py +7 -2
- cartography/intel/kandji/__init__.py +6 -3
- cartography/intel/kandji/devices.py +40 -10
- 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 +60 -55
- cartography/intel/kubernetes/pods.py +171 -75
- cartography/intel/kubernetes/rbac.py +597 -0
- cartography/intel/kubernetes/secrets.py +95 -45
- cartography/intel/kubernetes/services.py +131 -63
- cartography/intel/kubernetes/util.py +142 -14
- cartography/intel/lastpass/__init__.py +2 -2
- cartography/intel/lastpass/users.py +23 -12
- cartography/intel/oci/__init__.py +44 -11
- cartography/intel/oci/iam.py +157 -47
- cartography/intel/oci/organizations.py +16 -7
- cartography/intel/oci/utils.py +71 -25
- cartography/intel/okta/__init__.py +66 -15
- cartography/intel/okta/applications.py +57 -25
- cartography/intel/okta/awssaml.py +105 -41
- cartography/intel/okta/factors.py +19 -5
- cartography/intel/okta/groups.py +61 -31
- cartography/intel/okta/organization.py +8 -2
- cartography/intel/okta/origins.py +9 -3
- cartography/intel/okta/roles.py +20 -7
- cartography/intel/okta/users.py +31 -10
- cartography/intel/okta/utils.py +6 -4
- 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/openai/__init__.py +86 -0
- cartography/intel/openai/adminapikeys.py +89 -0
- cartography/intel/openai/apikeys.py +96 -0
- cartography/intel/openai/projects.py +97 -0
- cartography/intel/openai/serviceaccounts.py +82 -0
- cartography/intel/openai/users.py +75 -0
- cartography/intel/openai/util.py +45 -0
- cartography/intel/pagerduty/__init__.py +8 -7
- cartography/intel/pagerduty/escalation_policies.py +31 -12
- cartography/intel/pagerduty/schedules.py +21 -8
- cartography/intel/pagerduty/services.py +18 -7
- cartography/intel/pagerduty/teams.py +13 -5
- cartography/intel/pagerduty/users.py +6 -2
- cartography/intel/pagerduty/vendors.py +6 -2
- 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/semgrep/__init__.py +30 -5
- cartography/intel/semgrep/dependencies.py +255 -0
- cartography/intel/semgrep/deployment.py +69 -0
- cartography/intel/semgrep/findings.py +157 -117
- 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/snipeit/__init__.py +44 -0
- cartography/intel/snipeit/asset.py +80 -0
- cartography/intel/snipeit/user.py +78 -0
- cartography/intel/snipeit/util.py +40 -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/tailscale/__init__.py +77 -0
- cartography/intel/tailscale/acls.py +146 -0
- cartography/intel/tailscale/devices.py +127 -0
- cartography/intel/tailscale/postureintegrations.py +81 -0
- cartography/intel/tailscale/tailnets.py +76 -0
- cartography/intel/tailscale/users.py +80 -0
- cartography/intel/tailscale/utils.py +132 -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/__init__.py +0 -0
- cartography/models/anthropic/apikey.py +94 -0
- cartography/models/anthropic/organization.py +19 -0
- cartography/models/anthropic/user.py +52 -0
- cartography/models/anthropic/workspace.py +90 -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/apigateway.py +51 -0
- cartography/models/aws/apigateway/apigatewaycertificate.py +72 -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/apigateway/apigatewayresource.py +70 -0
- cartography/models/aws/apigateway/apigatewaystage.py +75 -0
- cartography/models/aws/apigatewayv2/__init__.py +0 -0
- cartography/models/aws/apigatewayv2/apigatewayv2.py +53 -0
- cartography/models/aws/cloudtrail/__init__.py +0 -0
- cartography/models/aws/cloudtrail/management_events.py +153 -0
- cartography/models/aws/cloudtrail/trail.py +106 -0
- cartography/models/aws/cloudwatch/__init__.py +0 -0
- cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
- cartography/models/aws/cloudwatch/loggroup.py +52 -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/gsi.py +30 -22
- cartography/models/aws/dynamodb/tables.py +27 -17
- cartography/models/aws/ec2/auto_scaling_groups.py +224 -0
- cartography/models/aws/ec2/images.py +36 -34
- cartography/models/aws/ec2/instances.py +85 -38
- cartography/models/aws/ec2/keypair.py +59 -0
- cartography/models/aws/ec2/keypair_instance.py +76 -0
- cartography/models/aws/ec2/launch_configurations.py +59 -0
- cartography/models/aws/ec2/launch_template_versions.py +48 -38
- cartography/models/aws/ec2/launch_templates.py +21 -17
- cartography/models/aws/ec2/load_balancer_listeners.py +72 -0
- cartography/models/aws/ec2/load_balancers.py +112 -0
- cartography/models/aws/ec2/network_acl_rules.py +106 -0
- cartography/models/aws/ec2/network_acls.py +95 -0
- cartography/models/aws/ec2/networkinterface_instance.py +52 -39
- cartography/models/aws/ec2/networkinterfaces.py +57 -37
- cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
- cartography/models/aws/ec2/reservations.py +18 -14
- cartography/models/aws/ec2/route_table_associations.py +97 -0
- cartography/models/aws/ec2/route_tables.py +128 -0
- cartography/models/aws/ec2/routes.py +85 -0
- cartography/models/aws/ec2/security_group_rules.py +109 -0
- cartography/models/aws/ec2/security_groups.py +90 -0
- cartography/models/aws/ec2/securitygroup_instance.py +29 -20
- cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
- cartography/models/aws/ec2/snapshots.py +58 -0
- cartography/models/aws/ec2/subnet_instance.py +26 -19
- cartography/models/aws/ec2/subnet_networkinterface.py +42 -31
- cartography/models/aws/ec2/subnets.py +65 -0
- cartography/models/aws/ec2/volumes.py +67 -40
- 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/__init__.py +0 -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 +79 -0
- cartography/models/aws/eks/clusters.py +23 -21
- 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/emr.py +32 -30
- 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/__init__.py +0 -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/instanceprofile.py +76 -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/__init__.py +0 -0
- cartography/models/aws/identitycenter/awsidentitycenter.py +49 -0
- cartography/models/aws/identitycenter/awspermissionset.py +162 -0
- cartography/models/aws/identitycenter/awssogroup.py +70 -0
- cartography/models/aws/identitycenter/awsssouser.py +110 -0
- cartography/models/aws/inspector/findings.py +124 -58
- cartography/models/aws/inspector/packages.py +18 -42
- 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/__init__.py +0 -0
- cartography/models/aws/s3/account_public_access_block.py +51 -0
- cartography/models/aws/s3/notification.py +24 -0
- cartography/models/aws/secretsmanager/__init__.py +0 -0
- cartography/models/aws/secretsmanager/secret.py +106 -0
- cartography/models/aws/secretsmanager/secret_version.py +114 -0
- cartography/models/aws/sns/__init__.py +0 -0
- cartography/models/aws/sns/topic.py +50 -0
- 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/aws/ssm/instance_information.py +51 -39
- cartography/models/aws/ssm/instance_patch.py +32 -26
- cartography/models/aws/ssm/parameters.py +84 -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 +42 -38
- cartography/models/bigfix/bigfix_root.py +3 -3
- cartography/models/cloudflare/__init__.py +0 -0
- cartography/models/cloudflare/account.py +25 -0
- cartography/models/cloudflare/dnsrecord.py +55 -0
- cartography/models/cloudflare/member.py +86 -0
- cartography/models/cloudflare/role.py +44 -0
- cartography/models/cloudflare/zone.py +59 -0
- cartography/models/core/common.py +53 -2
- cartography/models/core/nodes.py +20 -4
- cartography/models/core/relationships.py +58 -6
- cartography/models/crowdstrike/__init__.py +0 -0
- cartography/models/crowdstrike/hosts.py +51 -0
- cartography/models/cve/cve.py +34 -32
- cartography/models/cve/cve_feed.py +6 -6
- cartography/models/digitalocean/__init__.py +0 -0
- cartography/models/digitalocean/account.py +21 -0
- cartography/models/digitalocean/droplet.py +58 -0
- cartography/models/digitalocean/project.py +48 -0
- cartography/models/duo/api_host.py +3 -3
- cartography/models/duo/endpoint.py +43 -41
- cartography/models/duo/group.py +14 -14
- cartography/models/duo/phone.py +27 -27
- cartography/models/duo/token.py +16 -16
- cartography/models/duo/user.py +50 -44
- cartography/models/duo/web_authn_credential.py +27 -19
- cartography/models/entra/__init__.py +0 -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/ou.py +48 -0
- cartography/models/entra/service_principal.py +104 -0
- cartography/models/entra/tenant.py +39 -0
- cartography/models/entra/user.py +90 -0
- 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 +73 -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/orgs.py +27 -0
- cartography/models/github/teams.py +74 -22
- cartography/models/github/users.py +149 -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 +22 -17
- cartography/models/kandji/tenant.py +6 -4
- 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/tenant.py +3 -3
- cartography/models/lastpass/user.py +36 -28
- 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/__init__.py +0 -0
- cartography/models/openai/adminapikey.py +94 -0
- cartography/models/openai/apikey.py +88 -0
- cartography/models/openai/organization.py +17 -0
- cartography/models/openai/project.py +89 -0
- cartography/models/openai/serviceaccount.py +50 -0
- cartography/models/openai/user.py +53 -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/semgrep/dependencies.py +102 -0
- cartography/models/semgrep/deployment.py +5 -5
- cartography/models/semgrep/findings.py +58 -40
- cartography/models/semgrep/locations.py +27 -21
- 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/__init__.py +0 -0
- cartography/models/snipeit/asset.py +92 -0
- cartography/models/snipeit/tenant.py +19 -0
- cartography/models/snipeit/user.py +60 -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/__init__.py +0 -0
- cartography/models/tailscale/device.py +96 -0
- cartography/models/tailscale/group.py +86 -0
- cartography/models/tailscale/postureintegration.py +58 -0
- cartography/models/tailscale/tag.py +102 -0
- cartography/models/tailscale/tailnet.py +29 -0
- cartography/models/tailscale/user.py +57 -0
- 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/stats.py +4 -4
- cartography/sync.py +137 -31
- cartography/util.py +187 -77
- cartography-0.123.0.dist-info/METADATA +230 -0
- cartography-0.123.0.dist-info/RECORD +856 -0
- {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/WHEEL +1 -1
- {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/entry_points.txt +1 -0
- {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info/licenses}/LICENSE +1 -1
- cartography/data/jobs/analysis/aws_ec2_iaminstance.json +0 -10
- cartography/data/jobs/analysis/aws_ec2_iaminstanceprofile.json +0 -10
- cartography/data/jobs/cleanup/aws_apigateway_details.json +0 -10
- 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_apigateway_cleanup.json +0 -45
- 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_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/crxcavator_import_cleanup.json +0 -18
- 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/github_users_cleanup.json +0 -23
- 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/crxcavator/__init__.py +0 -44
- cartography/intel/crxcavator/crxcavator.py +0 -329
- cartography/intel/gcp/crm.py +0 -302
- cartography/intel/gsuite/api.py +0 -284
- cartography/models/aws/ec2/keypairs.py +0 -64
- cartography-0.93.0rc1.dist-info/METADATA +0 -55
- cartography-0.93.0rc1.dist-info/NOTICE +0 -4
- cartography-0.93.0rc1.dist-info/RECORD +0 -341
- /cartography/data/jobs/{analysis → scoped_analysis}/aws_s3acl_analysis.json +0 -0
- {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,847 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import boto3
|
|
5
|
+
import botocore.exceptions
|
|
6
|
+
import neo4j
|
|
7
|
+
|
|
8
|
+
from cartography.client.core.tx import load
|
|
9
|
+
from cartography.client.core.tx import load_matchlinks
|
|
10
|
+
from cartography.client.core.tx import read_list_of_dicts_tx
|
|
11
|
+
from cartography.graph.job import GraphJob
|
|
12
|
+
from cartography.models.aws.identitycenter.awsidentitycenter import (
|
|
13
|
+
AWSIdentityCenterInstanceSchema,
|
|
14
|
+
)
|
|
15
|
+
from cartography.models.aws.identitycenter.awspermissionset import (
|
|
16
|
+
AWSPermissionSetSchema,
|
|
17
|
+
)
|
|
18
|
+
from cartography.models.aws.identitycenter.awspermissionset import (
|
|
19
|
+
AWSRoleToSSOGroupMatchLink,
|
|
20
|
+
)
|
|
21
|
+
from cartography.models.aws.identitycenter.awspermissionset import (
|
|
22
|
+
AWSRoleToSSOUserMatchLink,
|
|
23
|
+
)
|
|
24
|
+
from cartography.models.aws.identitycenter.awssogroup import AWSSSOGroupSchema
|
|
25
|
+
from cartography.models.aws.identitycenter.awsssouser import AWSSSOUserSchema
|
|
26
|
+
from cartography.util import aws_handle_regions
|
|
27
|
+
from cartography.util import timeit
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _is_permission_set_sync_unsupported_error(
|
|
33
|
+
error: botocore.exceptions.ClientError,
|
|
34
|
+
) -> bool:
|
|
35
|
+
"""Return True when the Identity Center instance does not support permission sets."""
|
|
36
|
+
error_info = error.response.get("Error", {})
|
|
37
|
+
if error_info.get("Code") != "ValidationException":
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
message = error_info.get("Message", "").lower()
|
|
41
|
+
return "not supported for this identity center instance" in message
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@timeit
|
|
45
|
+
@aws_handle_regions
|
|
46
|
+
def get_identity_center_instances(
|
|
47
|
+
boto3_session: boto3.session.Session,
|
|
48
|
+
region: str,
|
|
49
|
+
) -> list[dict[str, Any]]:
|
|
50
|
+
"""
|
|
51
|
+
Get all AWS IAM Identity Center instances in the current region
|
|
52
|
+
"""
|
|
53
|
+
client = boto3_session.client("sso-admin", region_name=region)
|
|
54
|
+
instances = []
|
|
55
|
+
|
|
56
|
+
paginator = client.get_paginator("list_instances")
|
|
57
|
+
for page in paginator.paginate():
|
|
58
|
+
instances.extend(page.get("Instances", []))
|
|
59
|
+
|
|
60
|
+
return instances
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@timeit
|
|
64
|
+
def load_identity_center_instances(
|
|
65
|
+
neo4j_session: neo4j.Session,
|
|
66
|
+
instance_data: list[dict[str, Any]],
|
|
67
|
+
region: str,
|
|
68
|
+
current_aws_account_id: str,
|
|
69
|
+
aws_update_tag: int,
|
|
70
|
+
) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Load Identity Center instances into the graph
|
|
73
|
+
"""
|
|
74
|
+
logger.info(
|
|
75
|
+
f"Loading {len(instance_data)} Identity Center instances for region {region}",
|
|
76
|
+
)
|
|
77
|
+
load(
|
|
78
|
+
neo4j_session,
|
|
79
|
+
AWSIdentityCenterInstanceSchema(),
|
|
80
|
+
instance_data,
|
|
81
|
+
lastupdated=aws_update_tag,
|
|
82
|
+
Region=region,
|
|
83
|
+
AWS_ID=current_aws_account_id,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@timeit
|
|
88
|
+
@aws_handle_regions
|
|
89
|
+
def get_permission_sets(
|
|
90
|
+
boto3_session: boto3.session.Session,
|
|
91
|
+
instance_arn: str,
|
|
92
|
+
region: str,
|
|
93
|
+
) -> list[dict[str, Any]]:
|
|
94
|
+
"""
|
|
95
|
+
Get all permission sets for a given Identity Center instance
|
|
96
|
+
"""
|
|
97
|
+
client = boto3_session.client("sso-admin", region_name=region)
|
|
98
|
+
permission_sets = []
|
|
99
|
+
|
|
100
|
+
paginator = client.get_paginator("list_permission_sets")
|
|
101
|
+
for page in paginator.paginate(InstanceArn=instance_arn):
|
|
102
|
+
# Get detailed info for each permission set
|
|
103
|
+
for arn in page.get("PermissionSets", []):
|
|
104
|
+
details = client.describe_permission_set(
|
|
105
|
+
InstanceArn=instance_arn,
|
|
106
|
+
PermissionSetArn=arn,
|
|
107
|
+
)
|
|
108
|
+
permission_set = details.get("PermissionSet", {})
|
|
109
|
+
if permission_set:
|
|
110
|
+
permission_sets.append(permission_set)
|
|
111
|
+
|
|
112
|
+
return permission_sets
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def transform_permission_sets(
|
|
116
|
+
permission_sets: list[dict[str, Any]],
|
|
117
|
+
region: str,
|
|
118
|
+
) -> list[dict[str, Any]]:
|
|
119
|
+
"""
|
|
120
|
+
Transform permission sets by adding the RoleHint based on region.
|
|
121
|
+
|
|
122
|
+
AWS SSO roles in us-east-1 don't include region in the ARN path,
|
|
123
|
+
but roles in other regions do: /aws-reserved/sso.amazonaws.com/{region}/AWSReservedSSO_*
|
|
124
|
+
"""
|
|
125
|
+
for permission_set in permission_sets:
|
|
126
|
+
if region == "us-east-1":
|
|
127
|
+
permission_set["RoleHint"] = (
|
|
128
|
+
f":role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_{permission_set.get('Name')}"
|
|
129
|
+
)
|
|
130
|
+
else:
|
|
131
|
+
permission_set["RoleHint"] = (
|
|
132
|
+
f":role/aws-reserved/sso.amazonaws.com/{region}/AWSReservedSSO_{permission_set.get('Name')}"
|
|
133
|
+
)
|
|
134
|
+
return permission_sets
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@timeit
|
|
138
|
+
def load_permission_sets(
|
|
139
|
+
neo4j_session: neo4j.Session,
|
|
140
|
+
permission_sets: list[dict[str, Any]],
|
|
141
|
+
instance_arn: str,
|
|
142
|
+
region: str,
|
|
143
|
+
aws_account_id: str,
|
|
144
|
+
aws_update_tag: int,
|
|
145
|
+
) -> None:
|
|
146
|
+
"""
|
|
147
|
+
Load Identity Center permission sets into the graph
|
|
148
|
+
"""
|
|
149
|
+
logger.info(
|
|
150
|
+
f"Loading {len(permission_sets)} permission sets for instance {instance_arn} in region {region}",
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
load(
|
|
154
|
+
neo4j_session,
|
|
155
|
+
AWSPermissionSetSchema(),
|
|
156
|
+
permission_sets,
|
|
157
|
+
lastupdated=aws_update_tag,
|
|
158
|
+
InstanceArn=instance_arn,
|
|
159
|
+
Region=region,
|
|
160
|
+
AWS_ID=aws_account_id,
|
|
161
|
+
_sub_resource_label="AWSAccount",
|
|
162
|
+
_sub_resource_id=aws_account_id,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@timeit
|
|
167
|
+
@aws_handle_regions
|
|
168
|
+
def get_sso_users(
|
|
169
|
+
boto3_session: boto3.session.Session,
|
|
170
|
+
identity_store_id: str,
|
|
171
|
+
region: str,
|
|
172
|
+
) -> list[dict[str, Any]]:
|
|
173
|
+
"""
|
|
174
|
+
Get all SSO users for a given Identity Store
|
|
175
|
+
"""
|
|
176
|
+
client = boto3_session.client("identitystore", region_name=region)
|
|
177
|
+
users = []
|
|
178
|
+
|
|
179
|
+
paginator = client.get_paginator("list_users")
|
|
180
|
+
for page in paginator.paginate(IdentityStoreId=identity_store_id):
|
|
181
|
+
user_page = page.get("Users", [])
|
|
182
|
+
for user in user_page:
|
|
183
|
+
users.append(user)
|
|
184
|
+
|
|
185
|
+
return users
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@timeit
|
|
189
|
+
@aws_handle_regions
|
|
190
|
+
def get_sso_groups(
|
|
191
|
+
boto3_session: boto3.session.Session,
|
|
192
|
+
identity_store_id: str,
|
|
193
|
+
region: str,
|
|
194
|
+
) -> list[dict[str, Any]]:
|
|
195
|
+
"""
|
|
196
|
+
Get all SSO groups for a given Identity Store
|
|
197
|
+
"""
|
|
198
|
+
client = boto3_session.client("identitystore", region_name=region)
|
|
199
|
+
groups: list[dict[str, Any]] = []
|
|
200
|
+
|
|
201
|
+
paginator = client.get_paginator("list_groups")
|
|
202
|
+
for page in paginator.paginate(IdentityStoreId=identity_store_id):
|
|
203
|
+
group_page = page.get("Groups", [])
|
|
204
|
+
for group in group_page:
|
|
205
|
+
groups.append(group)
|
|
206
|
+
|
|
207
|
+
return groups
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def transform_sso_users(
|
|
211
|
+
users: list[dict[str, Any]],
|
|
212
|
+
user_group_memberships: dict[str, list[str]] | None = None,
|
|
213
|
+
user_permissionsets: list[dict[str, Any]] | None = None,
|
|
214
|
+
) -> list[dict[str, Any]]:
|
|
215
|
+
"""
|
|
216
|
+
Transform SSO users to match the expected schema, optionally including group memberships
|
|
217
|
+
and permission set assignments.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
users: List of SSO users from AWS API
|
|
221
|
+
user_group_memberships: Optional mapping of UserId -> [GroupIds]
|
|
222
|
+
user_permissionsets: Optional list of permission set assignments with shape:
|
|
223
|
+
[{UserId: str, PermissionSetArn: str, AccountId: str}, ...]
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Transformed users with MemberOfGroups and AssignedPermissionSets fields added
|
|
227
|
+
"""
|
|
228
|
+
# Build mapping from UserId to list of PermissionSetArns
|
|
229
|
+
user_permission_sets: dict[str, list[str]] = {}
|
|
230
|
+
if user_permissionsets:
|
|
231
|
+
for assignment in user_permissionsets:
|
|
232
|
+
user_id = assignment["UserId"]
|
|
233
|
+
perm_set = assignment["PermissionSetArn"]
|
|
234
|
+
user_permission_sets.setdefault(user_id, []).append(perm_set)
|
|
235
|
+
|
|
236
|
+
# Transform users
|
|
237
|
+
transformed_users = []
|
|
238
|
+
for user in users:
|
|
239
|
+
if user.get("ExternalIds"):
|
|
240
|
+
user["ExternalId"] = user["ExternalIds"][0].get("Id")
|
|
241
|
+
# Add group memberships if provided
|
|
242
|
+
if user_group_memberships:
|
|
243
|
+
user["MemberOfGroups"] = user_group_memberships.get(user["UserId"], [])
|
|
244
|
+
# Add direct permission set assignments if available
|
|
245
|
+
if user_permission_sets:
|
|
246
|
+
user["AssignedPermissionSets"] = user_permission_sets.get(
|
|
247
|
+
user["UserId"], []
|
|
248
|
+
)
|
|
249
|
+
transformed_users.append(user)
|
|
250
|
+
return transformed_users
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def transform_sso_groups(
|
|
254
|
+
groups: list[dict[str, Any]],
|
|
255
|
+
group_role_assignments: list[dict[str, Any]] | None = None,
|
|
256
|
+
) -> list[dict[str, Any]]:
|
|
257
|
+
"""
|
|
258
|
+
Transform SSO groups to match the expected schema, optionally including permission set assignments.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
groups: List of SSO groups from AWS API
|
|
262
|
+
group_role_assignments: Optional list of role assignments with shape:
|
|
263
|
+
[{GroupId: str, PermissionSetArn: str, AccountId: str}, ...]
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Transformed groups with AssignedPermissionSets field added
|
|
267
|
+
"""
|
|
268
|
+
# Build mapping from GroupId to list of PermissionSetArns
|
|
269
|
+
group_permission_sets: dict[str, list[str]] = {}
|
|
270
|
+
if group_role_assignments:
|
|
271
|
+
for assignment in group_role_assignments:
|
|
272
|
+
group_id = assignment["GroupId"]
|
|
273
|
+
perm_set = assignment["PermissionSetArn"]
|
|
274
|
+
group_permission_sets.setdefault(group_id, []).append(perm_set)
|
|
275
|
+
|
|
276
|
+
# Transform groups
|
|
277
|
+
transformed_groups: list[dict[str, Any]] = []
|
|
278
|
+
for group in groups:
|
|
279
|
+
if group.get("ExternalIds"):
|
|
280
|
+
group["ExternalId"] = group["ExternalIds"][0].get("Id")
|
|
281
|
+
# Add permission set assignments if available
|
|
282
|
+
if group_permission_sets:
|
|
283
|
+
group["AssignedPermissionSets"] = group_permission_sets.get(
|
|
284
|
+
group["GroupId"], []
|
|
285
|
+
)
|
|
286
|
+
transformed_groups.append(group)
|
|
287
|
+
return transformed_groups
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
@timeit
|
|
291
|
+
def load_sso_users(
|
|
292
|
+
neo4j_session: neo4j.Session,
|
|
293
|
+
users: list[dict[str, Any]],
|
|
294
|
+
identity_store_id: str,
|
|
295
|
+
region: str,
|
|
296
|
+
aws_account_id: str,
|
|
297
|
+
aws_update_tag: int,
|
|
298
|
+
) -> None:
|
|
299
|
+
"""
|
|
300
|
+
Load SSO users into the graph
|
|
301
|
+
"""
|
|
302
|
+
logger.info(
|
|
303
|
+
f"Loading {len(users)} SSO users for identity store {identity_store_id} in region {region}",
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
load(
|
|
307
|
+
neo4j_session,
|
|
308
|
+
AWSSSOUserSchema(),
|
|
309
|
+
users,
|
|
310
|
+
lastupdated=aws_update_tag,
|
|
311
|
+
IdentityStoreId=identity_store_id,
|
|
312
|
+
AWS_ID=aws_account_id,
|
|
313
|
+
Region=region,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
@timeit
|
|
318
|
+
def load_sso_groups(
|
|
319
|
+
neo4j_session: neo4j.Session,
|
|
320
|
+
groups: list[dict[str, Any]],
|
|
321
|
+
identity_store_id: str,
|
|
322
|
+
region: str,
|
|
323
|
+
aws_account_id: str,
|
|
324
|
+
aws_update_tag: int,
|
|
325
|
+
) -> None:
|
|
326
|
+
"""
|
|
327
|
+
Load SSO groups into the graph
|
|
328
|
+
"""
|
|
329
|
+
logger.info(
|
|
330
|
+
f"Loading {len(groups)} SSO groups for identity store {identity_store_id} in region {region}",
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
load(
|
|
334
|
+
neo4j_session,
|
|
335
|
+
AWSSSOGroupSchema(),
|
|
336
|
+
groups,
|
|
337
|
+
lastupdated=aws_update_tag,
|
|
338
|
+
IdentityStoreId=identity_store_id,
|
|
339
|
+
AWS_ID=aws_account_id,
|
|
340
|
+
Region=region,
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@timeit
|
|
345
|
+
@aws_handle_regions
|
|
346
|
+
def get_user_permissionsets(
|
|
347
|
+
boto3_session: boto3.session.Session,
|
|
348
|
+
users: list[dict[str, Any]],
|
|
349
|
+
instance_arn: str,
|
|
350
|
+
region: str,
|
|
351
|
+
) -> list[dict[str, Any]]:
|
|
352
|
+
"""
|
|
353
|
+
Get permissionsets for SSO users, taking into account which accounts the user is assigned to.
|
|
354
|
+
Although a permissionset can be assigned to multiple accounts, it is possible for the user
|
|
355
|
+
to be assigned to just a subset of those!
|
|
356
|
+
"""
|
|
357
|
+
logger.info(f"Getting permissionsets for {len(users)} users")
|
|
358
|
+
client = boto3_session.client("sso-admin", region_name=region)
|
|
359
|
+
user_permissionsets = []
|
|
360
|
+
|
|
361
|
+
for user in users:
|
|
362
|
+
user_id = user["UserId"]
|
|
363
|
+
paginator = client.get_paginator("list_account_assignments_for_principal")
|
|
364
|
+
for page in paginator.paginate(
|
|
365
|
+
InstanceArn=instance_arn,
|
|
366
|
+
PrincipalId=user_id,
|
|
367
|
+
PrincipalType="USER",
|
|
368
|
+
):
|
|
369
|
+
for assignment in page.get("AccountAssignments", []):
|
|
370
|
+
user_permissionsets.append(
|
|
371
|
+
{
|
|
372
|
+
"UserId": user_id,
|
|
373
|
+
"PermissionSetArn": assignment.get("PermissionSetArn"),
|
|
374
|
+
"AccountId": assignment.get("AccountId"),
|
|
375
|
+
},
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
return user_permissionsets
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
@timeit
|
|
382
|
+
@aws_handle_regions
|
|
383
|
+
def get_group_permissionsets(
|
|
384
|
+
boto3_session: boto3.session.Session,
|
|
385
|
+
groups: list[dict[str, Any]],
|
|
386
|
+
instance_arn: str,
|
|
387
|
+
region: str,
|
|
388
|
+
) -> list[dict[str, Any]]:
|
|
389
|
+
"""
|
|
390
|
+
Get permissionsets for SSO groups, taking into account which accounts the group is assigned to.
|
|
391
|
+
"""
|
|
392
|
+
logger.info(f"Getting permissionsets for {len(groups)} groups")
|
|
393
|
+
client = boto3_session.client("sso-admin", region_name=region)
|
|
394
|
+
group_permissionsets: list[dict[str, Any]] = []
|
|
395
|
+
|
|
396
|
+
for group in groups:
|
|
397
|
+
group_id = group["GroupId"]
|
|
398
|
+
paginator = client.get_paginator("list_account_assignments_for_principal")
|
|
399
|
+
for page in paginator.paginate(
|
|
400
|
+
InstanceArn=instance_arn,
|
|
401
|
+
PrincipalId=group_id,
|
|
402
|
+
PrincipalType="GROUP",
|
|
403
|
+
):
|
|
404
|
+
for assignment in page.get("AccountAssignments", []):
|
|
405
|
+
group_permissionsets.append(
|
|
406
|
+
{
|
|
407
|
+
"GroupId": group_id,
|
|
408
|
+
"PermissionSetArn": assignment.get("PermissionSetArn"),
|
|
409
|
+
"AccountId": assignment.get("AccountId"),
|
|
410
|
+
}
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
return group_permissionsets
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
@timeit
|
|
417
|
+
@aws_handle_regions
|
|
418
|
+
def get_user_group_memberships(
|
|
419
|
+
boto3_session: boto3.session.Session,
|
|
420
|
+
identity_store_id: str,
|
|
421
|
+
groups: list[dict[str, Any]],
|
|
422
|
+
region: str,
|
|
423
|
+
) -> dict[str, list[str]]:
|
|
424
|
+
"""
|
|
425
|
+
Return a mapping of UserId -> [GroupIds] for all group memberships in the identity store.
|
|
426
|
+
"""
|
|
427
|
+
client = boto3_session.client("identitystore", region_name=region)
|
|
428
|
+
user_groups: dict[str, list[str]] = {}
|
|
429
|
+
|
|
430
|
+
for group in groups:
|
|
431
|
+
group_id = group["GroupId"]
|
|
432
|
+
paginator = client.get_paginator("list_group_memberships")
|
|
433
|
+
for page in paginator.paginate(
|
|
434
|
+
IdentityStoreId=identity_store_id, GroupId=group_id
|
|
435
|
+
):
|
|
436
|
+
for membership in page.get("GroupMemberships", []):
|
|
437
|
+
member = membership.get("MemberId", {})
|
|
438
|
+
user_id = member.get("UserId")
|
|
439
|
+
if user_id:
|
|
440
|
+
user_groups.setdefault(user_id, []).append(group_id)
|
|
441
|
+
|
|
442
|
+
return user_groups
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
@timeit
|
|
446
|
+
def _get_permset_roles(
|
|
447
|
+
neo4j_session: neo4j.Session,
|
|
448
|
+
permset_ids: list[str],
|
|
449
|
+
) -> dict[tuple[str, str], str]:
|
|
450
|
+
"""
|
|
451
|
+
Given a list of permission set ARNs, return a mapping of (permission set ARN, account ID) to role ARN
|
|
452
|
+
based on the ASSIGNED_TO_ROLE relationship in the graph.
|
|
453
|
+
"""
|
|
454
|
+
query = """
|
|
455
|
+
MATCH (role:AWSRole)<-[:ASSIGNED_TO_ROLE]-(permset:AWSPermissionSet)
|
|
456
|
+
MATCH (account:AWSAccount)-[:RESOURCE]->(role)
|
|
457
|
+
WHERE permset.arn IN $PermSetIds
|
|
458
|
+
RETURN permset.arn AS PermissionSetArn, role.arn AS RoleArn, account.id AS AccountId
|
|
459
|
+
"""
|
|
460
|
+
permset_to_role = neo4j_session.execute_read(
|
|
461
|
+
read_list_of_dicts_tx,
|
|
462
|
+
query,
|
|
463
|
+
PermSetIds=permset_ids,
|
|
464
|
+
)
|
|
465
|
+
return {
|
|
466
|
+
(entry["PermissionSetArn"], entry["AccountId"]): entry["RoleArn"]
|
|
467
|
+
for entry in permset_to_role
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
@timeit
|
|
472
|
+
def get_principal_roles(
|
|
473
|
+
neo4j_session: neo4j.Session,
|
|
474
|
+
principal_assignments: list[dict[str, Any]],
|
|
475
|
+
) -> list[dict[str, Any]]:
|
|
476
|
+
"""
|
|
477
|
+
At this point we've established that the principal has access to a given account
|
|
478
|
+
via a given permission set, and now we need to find the exact role in the account
|
|
479
|
+
it has access to.
|
|
480
|
+
:param neo4j_session: neo4j.Session
|
|
481
|
+
:param principal_assignments: either a list of {
|
|
482
|
+
"UserId": str
|
|
483
|
+
"AccountId": str,
|
|
484
|
+
"PermissionSetArn": str,
|
|
485
|
+
}, or a list of {
|
|
486
|
+
"GroupId": str,
|
|
487
|
+
"AccountId": str,
|
|
488
|
+
"PermissionSetArn": str,
|
|
489
|
+
}
|
|
490
|
+
:return: either a list of {
|
|
491
|
+
"UserId": str,
|
|
492
|
+
"AccountId": str,
|
|
493
|
+
"PermissionSetArn": str,
|
|
494
|
+
"RoleArn": str
|
|
495
|
+
} or,
|
|
496
|
+
a list of {
|
|
497
|
+
"GroupId": str,
|
|
498
|
+
"AccountId": str,
|
|
499
|
+
"PermissionSetArn": str,
|
|
500
|
+
"RoleArn": str
|
|
501
|
+
}
|
|
502
|
+
"""
|
|
503
|
+
# Get unique permission set ARNs from role assignments
|
|
504
|
+
permset_ids = list({pa["PermissionSetArn"] for pa in principal_assignments})
|
|
505
|
+
permset_to_role = _get_permset_roles(neo4j_session, permset_ids)
|
|
506
|
+
|
|
507
|
+
unmatched = 0
|
|
508
|
+
# Use the lookup table to enrich assignments with exact role ARNs
|
|
509
|
+
principal_roles = []
|
|
510
|
+
for assignment in principal_assignments:
|
|
511
|
+
lookup_key = (assignment["PermissionSetArn"], assignment["AccountId"])
|
|
512
|
+
role_arn = permset_to_role.get(lookup_key)
|
|
513
|
+
if not role_arn:
|
|
514
|
+
unmatched += 1
|
|
515
|
+
principal_roles.append(
|
|
516
|
+
{
|
|
517
|
+
**assignment,
|
|
518
|
+
"RoleArn": role_arn,
|
|
519
|
+
}
|
|
520
|
+
)
|
|
521
|
+
if unmatched > 0:
|
|
522
|
+
logger.info(
|
|
523
|
+
f"Identity Center: {unmatched} of {len(principal_assignments)} principal assignments "
|
|
524
|
+
"did not match a role. This usually means IAM roles for some permission sets/accounts "
|
|
525
|
+
"have not been ingested yet. Re-run the IAM sync, and then the Identity Center sync to fix."
|
|
526
|
+
)
|
|
527
|
+
return principal_roles
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
@timeit
|
|
531
|
+
def load_user_roles(
|
|
532
|
+
neo4j_session: neo4j.Session,
|
|
533
|
+
user_roles: list[dict[str, Any]],
|
|
534
|
+
aws_account_id: str,
|
|
535
|
+
aws_update_tag: int,
|
|
536
|
+
) -> None:
|
|
537
|
+
logger.info(f"Loading {len(user_roles)} user roles")
|
|
538
|
+
load_matchlinks(
|
|
539
|
+
neo4j_session,
|
|
540
|
+
AWSRoleToSSOUserMatchLink(),
|
|
541
|
+
user_roles,
|
|
542
|
+
lastupdated=aws_update_tag,
|
|
543
|
+
_sub_resource_label="AWSAccount",
|
|
544
|
+
_sub_resource_id=aws_account_id,
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
@timeit
|
|
549
|
+
def load_group_roles(
|
|
550
|
+
neo4j_session: neo4j.Session,
|
|
551
|
+
group_roles: list[dict[str, Any]],
|
|
552
|
+
aws_account_id: str,
|
|
553
|
+
aws_update_tag: int,
|
|
554
|
+
) -> None:
|
|
555
|
+
logger.info(f"Loading {len(group_roles)} group roles")
|
|
556
|
+
load_matchlinks(
|
|
557
|
+
neo4j_session,
|
|
558
|
+
AWSRoleToSSOGroupMatchLink(),
|
|
559
|
+
group_roles,
|
|
560
|
+
lastupdated=aws_update_tag,
|
|
561
|
+
_sub_resource_label="AWSAccount",
|
|
562
|
+
_sub_resource_id=aws_account_id,
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
@timeit
|
|
567
|
+
def cleanup(
|
|
568
|
+
neo4j_session: neo4j.Session,
|
|
569
|
+
common_job_parameters: dict[str, Any],
|
|
570
|
+
) -> None:
|
|
571
|
+
GraphJob.from_node_schema(
|
|
572
|
+
AWSIdentityCenterInstanceSchema(),
|
|
573
|
+
common_job_parameters,
|
|
574
|
+
).run(neo4j_session)
|
|
575
|
+
GraphJob.from_node_schema(AWSPermissionSetSchema(), common_job_parameters).run(
|
|
576
|
+
neo4j_session,
|
|
577
|
+
)
|
|
578
|
+
GraphJob.from_node_schema(AWSSSOUserSchema(), common_job_parameters).run(
|
|
579
|
+
neo4j_session,
|
|
580
|
+
)
|
|
581
|
+
GraphJob.from_node_schema(AWSSSOGroupSchema(), common_job_parameters).run(
|
|
582
|
+
neo4j_session,
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
# Clean up role assignment MatchLinks
|
|
586
|
+
GraphJob.from_matchlink(
|
|
587
|
+
AWSRoleToSSOUserMatchLink(),
|
|
588
|
+
"AWSAccount",
|
|
589
|
+
common_job_parameters["AWS_ID"],
|
|
590
|
+
common_job_parameters["UPDATE_TAG"],
|
|
591
|
+
).run(neo4j_session)
|
|
592
|
+
GraphJob.from_matchlink(
|
|
593
|
+
AWSRoleToSSOGroupMatchLink(),
|
|
594
|
+
"AWSAccount",
|
|
595
|
+
common_job_parameters["AWS_ID"],
|
|
596
|
+
common_job_parameters["UPDATE_TAG"],
|
|
597
|
+
).run(neo4j_session)
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
def _sync_permission_sets(
|
|
601
|
+
neo4j_session: neo4j.Session,
|
|
602
|
+
boto3_session: boto3.session.Session,
|
|
603
|
+
instance_arn: str,
|
|
604
|
+
region: str,
|
|
605
|
+
current_aws_account_id: str,
|
|
606
|
+
update_tag: int,
|
|
607
|
+
) -> bool:
|
|
608
|
+
"""
|
|
609
|
+
Sync permission sets for an Identity Center instance.
|
|
610
|
+
|
|
611
|
+
Returns:
|
|
612
|
+
True if permission set sync is supported, False for account-scoped instances
|
|
613
|
+
that don't support permission sets.
|
|
614
|
+
"""
|
|
615
|
+
try:
|
|
616
|
+
permission_sets = get_permission_sets(boto3_session, instance_arn, region)
|
|
617
|
+
# Transform permission sets to add RoleHint for fuzzy matching to IAM roles
|
|
618
|
+
permission_sets = transform_permission_sets(permission_sets, region)
|
|
619
|
+
load_permission_sets(
|
|
620
|
+
neo4j_session,
|
|
621
|
+
permission_sets,
|
|
622
|
+
instance_arn,
|
|
623
|
+
region,
|
|
624
|
+
current_aws_account_id,
|
|
625
|
+
update_tag,
|
|
626
|
+
)
|
|
627
|
+
return True
|
|
628
|
+
except botocore.exceptions.ClientError as error:
|
|
629
|
+
if _is_permission_set_sync_unsupported_error(error):
|
|
630
|
+
logger.warning(
|
|
631
|
+
"Skipping permission set sync for Identity Center instance %s in region %s "
|
|
632
|
+
"because the instance does not support permission sets. "
|
|
633
|
+
"Will attempt to sync users and groups only.",
|
|
634
|
+
instance_arn,
|
|
635
|
+
region,
|
|
636
|
+
)
|
|
637
|
+
return False
|
|
638
|
+
raise
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
def _sync_groups_and_users(
|
|
642
|
+
neo4j_session: neo4j.Session,
|
|
643
|
+
boto3_session: boto3.session.Session,
|
|
644
|
+
instance_arn: str,
|
|
645
|
+
identity_store_id: str,
|
|
646
|
+
region: str,
|
|
647
|
+
permission_set_sync_supported: bool,
|
|
648
|
+
current_aws_account_id: str,
|
|
649
|
+
update_tag: int,
|
|
650
|
+
) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
|
|
651
|
+
"""
|
|
652
|
+
Sync groups and users for an Identity Center instance.
|
|
653
|
+
|
|
654
|
+
Groups are synced first so that user->group membership edges can be created.
|
|
655
|
+
Permission set assignments are fetched (if supported) and used to enrich
|
|
656
|
+
the user/group nodes with HAS_PERMISSION_SET relationships, then returned
|
|
657
|
+
for later role assignment creation.
|
|
658
|
+
|
|
659
|
+
Args:
|
|
660
|
+
permission_set_sync_supported: If True, fetches and enriches permission set assignments
|
|
661
|
+
|
|
662
|
+
Returns:
|
|
663
|
+
(user_permission_set_assignments, group_permission_set_assignments)
|
|
664
|
+
These are the raw assignment data needed for creating ALLOWED_BY relationships.
|
|
665
|
+
Will be empty lists if permission_set_sync_supported is False.
|
|
666
|
+
"""
|
|
667
|
+
# Fetch groups first to avoid interleaving between groups and users
|
|
668
|
+
groups = get_sso_groups(boto3_session, identity_store_id, region)
|
|
669
|
+
|
|
670
|
+
# Get permission set assignments for groups (if permission sets are supported)
|
|
671
|
+
group_permissionsets_raw: list[dict[str, Any]] = []
|
|
672
|
+
if permission_set_sync_supported:
|
|
673
|
+
group_permissionsets_raw = get_group_permissionsets(
|
|
674
|
+
boto3_session,
|
|
675
|
+
groups,
|
|
676
|
+
instance_arn,
|
|
677
|
+
region,
|
|
678
|
+
)
|
|
679
|
+
|
|
680
|
+
# Transform and load groups with their permission set assignments FIRST
|
|
681
|
+
# so that user->group membership edges can attach in the same run.
|
|
682
|
+
transformed_groups = transform_sso_groups(groups, group_permissionsets_raw)
|
|
683
|
+
load_sso_groups(
|
|
684
|
+
neo4j_session,
|
|
685
|
+
transformed_groups,
|
|
686
|
+
identity_store_id,
|
|
687
|
+
region,
|
|
688
|
+
current_aws_account_id,
|
|
689
|
+
update_tag,
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
# Handle users AFTER groups exist
|
|
693
|
+
users = get_sso_users(boto3_session, identity_store_id, region)
|
|
694
|
+
user_group_memberships = get_user_group_memberships(
|
|
695
|
+
boto3_session,
|
|
696
|
+
identity_store_id,
|
|
697
|
+
groups,
|
|
698
|
+
region,
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
# Get direct permission set assignments for users (if permission sets are supported)
|
|
702
|
+
user_permissionsets_raw: list[dict[str, Any]] = []
|
|
703
|
+
if permission_set_sync_supported:
|
|
704
|
+
user_permissionsets_raw = get_user_permissionsets(
|
|
705
|
+
boto3_session,
|
|
706
|
+
users,
|
|
707
|
+
instance_arn,
|
|
708
|
+
region,
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
# Transform and load users with their group memberships AFTER groups exist
|
|
712
|
+
transformed_users = transform_sso_users(
|
|
713
|
+
users,
|
|
714
|
+
user_group_memberships,
|
|
715
|
+
user_permissionsets_raw,
|
|
716
|
+
)
|
|
717
|
+
load_sso_users(
|
|
718
|
+
neo4j_session,
|
|
719
|
+
transformed_users,
|
|
720
|
+
identity_store_id,
|
|
721
|
+
region,
|
|
722
|
+
current_aws_account_id,
|
|
723
|
+
update_tag,
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
# Return the raw assignment data for role assignment creation
|
|
727
|
+
return user_permissionsets_raw, group_permissionsets_raw
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
def _sync_role_assignments(
|
|
731
|
+
neo4j_session: neo4j.Session,
|
|
732
|
+
user_permissionsets_raw: list[dict[str, Any]],
|
|
733
|
+
group_permissionsets_raw: list[dict[str, Any]],
|
|
734
|
+
current_aws_account_id: str,
|
|
735
|
+
update_tag: int,
|
|
736
|
+
) -> None:
|
|
737
|
+
"""
|
|
738
|
+
Create ALLOWED_BY relationships between IAM roles and SSO principals.
|
|
739
|
+
|
|
740
|
+
This enriches the raw permission set assignment data with exact role ARNs
|
|
741
|
+
from the graph (using the composite key lookup), then creates the MatchLink
|
|
742
|
+
relationships.
|
|
743
|
+
|
|
744
|
+
Note: This must be called AFTER groups and users are loaded so that the
|
|
745
|
+
MatchLinks can find the existing AWSSSOUser/AWSSSOGroup nodes when creating
|
|
746
|
+
the ALLOWED_BY edges.
|
|
747
|
+
"""
|
|
748
|
+
user_roles = get_principal_roles(neo4j_session, user_permissionsets_raw)
|
|
749
|
+
load_user_roles(neo4j_session, user_roles, current_aws_account_id, update_tag)
|
|
750
|
+
|
|
751
|
+
group_roles = get_principal_roles(neo4j_session, group_permissionsets_raw)
|
|
752
|
+
load_group_roles(neo4j_session, group_roles, current_aws_account_id, update_tag)
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
def _sync_instance(
|
|
756
|
+
neo4j_session: neo4j.Session,
|
|
757
|
+
boto3_session: boto3.session.Session,
|
|
758
|
+
instance: dict[str, Any],
|
|
759
|
+
region: str,
|
|
760
|
+
current_aws_account_id: str,
|
|
761
|
+
update_tag: int,
|
|
762
|
+
) -> None:
|
|
763
|
+
"""
|
|
764
|
+
Sync a single Identity Center instance.
|
|
765
|
+
|
|
766
|
+
This syncs permission sets (if supported), groups, users, and role assignments
|
|
767
|
+
in the correct order to ensure all relationships can be created.
|
|
768
|
+
"""
|
|
769
|
+
instance_arn = instance["InstanceArn"]
|
|
770
|
+
identity_store_id = instance["IdentityStoreId"]
|
|
771
|
+
|
|
772
|
+
# Sync permission sets (may not be supported for account-scoped instances)
|
|
773
|
+
permission_set_sync_supported = _sync_permission_sets(
|
|
774
|
+
neo4j_session,
|
|
775
|
+
boto3_session,
|
|
776
|
+
instance_arn,
|
|
777
|
+
region,
|
|
778
|
+
current_aws_account_id,
|
|
779
|
+
update_tag,
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
# Sync groups and users (always happens, but enriched with permission sets if available)
|
|
783
|
+
user_assignments, group_assignments = _sync_groups_and_users(
|
|
784
|
+
neo4j_session,
|
|
785
|
+
boto3_session,
|
|
786
|
+
instance_arn,
|
|
787
|
+
identity_store_id,
|
|
788
|
+
region,
|
|
789
|
+
permission_set_sync_supported,
|
|
790
|
+
current_aws_account_id,
|
|
791
|
+
update_tag,
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
# Create role assignment relationships (only if permission sets are supported)
|
|
795
|
+
if permission_set_sync_supported:
|
|
796
|
+
_sync_role_assignments(
|
|
797
|
+
neo4j_session,
|
|
798
|
+
user_assignments,
|
|
799
|
+
group_assignments,
|
|
800
|
+
current_aws_account_id,
|
|
801
|
+
update_tag,
|
|
802
|
+
)
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
@timeit
|
|
806
|
+
def sync_identity_center_instances(
|
|
807
|
+
neo4j_session: neo4j.Session,
|
|
808
|
+
boto3_session: boto3.session.Session,
|
|
809
|
+
regions: list[str],
|
|
810
|
+
current_aws_account_id: str,
|
|
811
|
+
update_tag: int,
|
|
812
|
+
common_job_parameters: dict[str, Any],
|
|
813
|
+
) -> None:
|
|
814
|
+
"""
|
|
815
|
+
Sync Identity Center instances across all specified regions.
|
|
816
|
+
|
|
817
|
+
For each instance, syncs:
|
|
818
|
+
1. Permission sets (if supported by the instance type)
|
|
819
|
+
2. Groups and users (with permission set assignments if available)
|
|
820
|
+
3. Role assignment relationships (ALLOWED_BY edges from roles to principals)
|
|
821
|
+
|
|
822
|
+
Account-scoped Identity Center instances don't support permission sets and will
|
|
823
|
+
skip step 1 and 3, but still sync users and groups.
|
|
824
|
+
"""
|
|
825
|
+
logger.info(f"Syncing Identity Center instances for regions {regions}")
|
|
826
|
+
for region in regions:
|
|
827
|
+
logger.info(f"Syncing Identity Center instances for region {region}")
|
|
828
|
+
instances = get_identity_center_instances(boto3_session, region)
|
|
829
|
+
load_identity_center_instances(
|
|
830
|
+
neo4j_session,
|
|
831
|
+
instances,
|
|
832
|
+
region,
|
|
833
|
+
current_aws_account_id,
|
|
834
|
+
update_tag,
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
for instance in instances:
|
|
838
|
+
_sync_instance(
|
|
839
|
+
neo4j_session,
|
|
840
|
+
boto3_session,
|
|
841
|
+
instance,
|
|
842
|
+
region,
|
|
843
|
+
current_aws_account_id,
|
|
844
|
+
update_tag,
|
|
845
|
+
)
|
|
846
|
+
|
|
847
|
+
cleanup(neo4j_session, common_job_parameters)
|