prowler-cloud 5.13.1__py3-none-any.whl → 5.14.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.
- dashboard/__main__.py +2 -1
- dashboard/compliance/c5_azure.py +43 -0
- dashboard/compliance/fedramp_20x_ksi_low_aws.py +46 -0
- dashboard/compliance/fedramp_20x_ksi_low_azure.py +46 -0
- dashboard/compliance/fedramp_20x_ksi_low_gcp.py +46 -0
- dashboard/compliance/hipaa_gcp.py +25 -0
- dashboard/compliance/nist_csf_2_0_aws.py +24 -0
- dashboard/compliance/prowler_threatscore_kubernetes.py +28 -0
- prowler/AGENTS.md +366 -0
- prowler/CHANGELOG.md +85 -2
- prowler/__main__.py +54 -7
- prowler/compliance/aws/ens_rd2022_aws.json +1 -1
- prowler/compliance/aws/fedramp_20x_ksi_low_aws.json +347 -0
- prowler/compliance/aws/nis2_aws.json +1 -1
- prowler/compliance/aws/nist_csf_2.0_aws.json +1781 -0
- prowler/compliance/azure/c5_azure.json +9471 -0
- prowler/compliance/azure/ens_rd2022_azure.json +1 -1
- prowler/compliance/azure/fedramp_20x_ksi_low_azure.json +358 -0
- prowler/compliance/azure/nis2_azure.json +1 -1
- prowler/compliance/gcp/c5_gcp.json +9401 -0
- prowler/compliance/gcp/ens_rd2022_gcp.json +1 -1
- prowler/compliance/gcp/fedramp_20x_ksi_low_gcp.json +293 -0
- prowler/compliance/gcp/hipaa_gcp.json +415 -0
- prowler/compliance/gcp/nis2_gcp.json +1 -1
- prowler/compliance/github/cis_1.0_github.json +6 -2
- prowler/compliance/kubernetes/prowler_threatscore_kubernetes.json +1269 -0
- prowler/compliance/m365/prowler_threatscore_m365.json +6 -6
- prowler/compliance/{oci/cis_3.0_oci.json → oraclecloud/cis_3.0_oraclecloud.json} +1 -1
- prowler/config/config.py +59 -5
- prowler/config/config.yaml +3 -0
- prowler/lib/check/check.py +1 -9
- prowler/lib/check/checks_loader.py +65 -1
- prowler/lib/check/models.py +12 -2
- prowler/lib/check/utils.py +1 -7
- prowler/lib/cli/parser.py +17 -7
- prowler/lib/mutelist/mutelist.py +15 -7
- prowler/lib/outputs/compliance/c5/c5_azure.py +92 -0
- prowler/lib/outputs/compliance/c5/c5_gcp.py +92 -0
- prowler/lib/outputs/compliance/c5/models.py +54 -0
- prowler/lib/outputs/compliance/cis/{cis_oci.py → cis_oraclecloud.py} +7 -7
- prowler/lib/outputs/compliance/cis/models.py +3 -3
- prowler/lib/outputs/compliance/prowler_threatscore/models.py +29 -0
- prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_kubernetes.py +98 -0
- prowler/lib/outputs/finding.py +16 -5
- prowler/lib/outputs/html/html.py +10 -8
- prowler/lib/outputs/outputs.py +1 -1
- prowler/lib/outputs/summary_table.py +1 -1
- prowler/lib/powershell/powershell.py +12 -11
- prowler/lib/scan/scan.py +105 -24
- prowler/lib/utils/utils.py +1 -1
- prowler/providers/aws/aws_regions_by_service.json +73 -15
- prowler/providers/aws/lib/quick_inventory/quick_inventory.py +1 -1
- prowler/providers/aws/lib/security_hub/security_hub.py +1 -1
- prowler/providers/aws/services/account/account_service.py +1 -1
- prowler/providers/aws/services/awslambda/awslambda_function_using_supported_runtimes/awslambda_function_using_supported_runtimes.metadata.json +1 -3
- prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_alarm_state_configured/cloudwatch_alarm_actions_alarm_state_configured.metadata.json +23 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_enabled/cloudwatch_alarm_actions_enabled.metadata.json +21 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_acls_alarm_configured/cloudwatch_changes_to_network_acls_alarm_configured.metadata.json +23 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_gateways_alarm_configured/cloudwatch_changes_to_network_gateways_alarm_configured.metadata.json +24 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_route_tables_alarm_configured/cloudwatch_changes_to_network_route_tables_alarm_configured.metadata.json +21 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_vpcs_alarm_configured/cloudwatch_changes_to_vpcs_alarm_configured.metadata.json +17 -11
- prowler/providers/aws/services/cloudwatch/cloudwatch_cross_account_sharing_disabled/cloudwatch_cross_account_sharing_disabled.metadata.json +20 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_kms_encryption_enabled/cloudwatch_log_group_kms_encryption_enabled.metadata.json +22 -13
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_no_secrets_in_logs/cloudwatch_log_group_no_secrets_in_logs.metadata.json +22 -17
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_not_publicly_accessible/cloudwatch_log_group_not_publicly_accessible.metadata.json +18 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_retention_policy_specific_days_enabled/cloudwatch_log_group_retention_policy_specific_days_enabled.metadata.json +27 -13
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled.metadata.json +20 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled.metadata.json +22 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_authentication_failures/cloudwatch_log_metric_filter_authentication_failures.metadata.json +25 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_aws_organizations_changes/cloudwatch_log_metric_filter_aws_organizations_changes.metadata.json +23 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk.metadata.json +17 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes.metadata.json +21 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_policy_changes/cloudwatch_log_metric_filter_policy_changes.metadata.json +21 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_root_usage/cloudwatch_log_metric_filter_root_usage.metadata.json +27 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_security_group_changes/cloudwatch_log_metric_filter_security_group_changes.metadata.json +22 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_sign_in_without_mfa/cloudwatch_log_metric_filter_sign_in_without_mfa.metadata.json +26 -12
- prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_unauthorized_api_calls/cloudwatch_log_metric_filter_unauthorized_api_calls.metadata.json +25 -12
- prowler/providers/aws/services/codeartifact/codeartifact_packages_external_public_publishing_disabled/codeartifact_packages_external_public_publishing_disabled.metadata.json +20 -11
- prowler/providers/aws/services/codebuild/codebuild_project_logging_enabled/codebuild_project_logging_enabled.metadata.json +22 -12
- prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.metadata.json +28 -12
- prowler/providers/aws/services/codebuild/codebuild_project_not_publicly_accessible/codebuild_project_not_publicly_accessible.metadata.json +22 -12
- prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.metadata.json +15 -10
- prowler/providers/aws/services/codebuild/codebuild_project_s3_logs_encrypted/codebuild_project_s3_logs_encrypted.metadata.json +19 -11
- prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.metadata.json +21 -12
- prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.metadata.json +19 -12
- prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.metadata.json +24 -13
- prowler/providers/aws/services/codebuild/codebuild_report_group_export_encrypted/codebuild_report_group_export_encrypted.metadata.json +35 -13
- prowler/providers/aws/services/codepipeline/__init__.py +0 -0
- prowler/providers/aws/services/codepipeline/codepipeline_client.py +6 -0
- prowler/providers/aws/services/codepipeline/codepipeline_project_repo_private/__init__.py +0 -0
- prowler/providers/aws/services/codepipeline/codepipeline_project_repo_private/codepipeline_project_repo_private.metadata.json +30 -0
- prowler/providers/aws/services/codepipeline/codepipeline_project_repo_private/codepipeline_project_repo_private.py +95 -0
- prowler/providers/aws/services/codepipeline/codepipeline_service.py +164 -0
- prowler/providers/aws/services/directconnect/directconnect_connection_redundancy/directconnect_connection_redundancy.metadata.json +18 -12
- prowler/providers/aws/services/directconnect/directconnect_virtual_interface_redundancy/directconnect_virtual_interface_redundancy.metadata.json +18 -12
- prowler/providers/aws/services/documentdb/documentdb_cluster_backup_enabled/documentdb_cluster_backup_enabled.metadata.json +24 -13
- prowler/providers/aws/services/documentdb/documentdb_cluster_cloudwatch_log_export/documentdb_cluster_cloudwatch_log_export.metadata.json +23 -13
- prowler/providers/aws/services/documentdb/documentdb_cluster_deletion_protection/documentdb_cluster_deletion_protection.metadata.json +24 -13
- prowler/providers/aws/services/documentdb/documentdb_cluster_multi_az_enabled/documentdb_cluster_multi_az_enabled.metadata.json +19 -13
- prowler/providers/aws/services/documentdb/documentdb_cluster_public_snapshot/documentdb_cluster_public_snapshot.metadata.json +20 -10
- prowler/providers/aws/services/documentdb/documentdb_cluster_storage_encrypted/documentdb_cluster_storage_encrypted.metadata.json +26 -13
- prowler/providers/aws/services/drs/drs_job_exist/drs_job_exist.metadata.json +20 -10
- prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.metadata.json +18 -11
- prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json +16 -11
- prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_multi_az/dynamodb_accelerator_cluster_multi_az.metadata.json +21 -13
- prowler/providers/aws/services/dynamodb/dynamodb_table_autoscaling_enabled/dynamodb_table_autoscaling_enabled.metadata.json +20 -12
- prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.metadata.json +17 -10
- prowler/providers/aws/services/dynamodb/dynamodb_table_deletion_protection_enabled/dynamodb_table_deletion_protection_enabled.metadata.json +21 -13
- prowler/providers/aws/services/dynamodb/dynamodb_table_protected_by_backup_plan/dynamodb_table_protected_by_backup_plan.metadata.json +18 -12
- prowler/providers/aws/services/dynamodb/dynamodb_tables_kms_cmk_encryption_enabled/dynamodb_tables_kms_cmk_encryption_enabled.metadata.json +18 -12
- prowler/providers/aws/services/dynamodb/dynamodb_tables_pitr_enabled/dynamodb_tables_pitr_enabled.metadata.json +19 -12
- prowler/providers/aws/services/ecr/ecr_registry_scan_images_on_push_enabled/ecr_registry_scan_images_on_push_enabled.metadata.json +16 -11
- prowler/providers/aws/services/ecr/ecr_repositories_lifecycle_policy_enabled/ecr_repositories_lifecycle_policy_enabled.metadata.json +22 -13
- prowler/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible.metadata.json +19 -13
- prowler/providers/aws/services/ecr/ecr_repositories_scan_images_on_push_enabled/ecr_repositories_scan_images_on_push_enabled.metadata.json +21 -13
- prowler/providers/aws/services/ecr/ecr_repositories_scan_vulnerabilities_in_latest_image/ecr_repositories_scan_vulnerabilities_in_latest_image.metadata.json +22 -12
- prowler/providers/aws/services/ecr/ecr_repositories_tag_immutability/ecr_repositories_tag_immutability.metadata.json +20 -12
- prowler/providers/aws/services/ecs/ecs_cluster_container_insights_enabled/ecs_cluster_container_insights_enabled.metadata.json +21 -11
- prowler/providers/aws/services/ecs/ecs_service_fargate_latest_platform_version/ecs_service_fargate_latest_platform_version.metadata.json +20 -11
- prowler/providers/aws/services/ecs/ecs_service_no_assign_public_ip/ecs_service_no_assign_public_ip.metadata.json +18 -12
- prowler/providers/aws/services/ecs/ecs_task_definitions_containers_readonly_access/ecs_task_definitions_containers_readonly_access.metadata.json +20 -13
- prowler/providers/aws/services/ecs/ecs_task_definitions_host_namespace_not_shared/ecs_task_definitions_host_namespace_not_shared.metadata.json +21 -13
- prowler/providers/aws/services/ecs/ecs_task_definitions_host_networking_mode_users/ecs_task_definitions_host_networking_mode_users.metadata.json +26 -13
- prowler/providers/aws/services/ecs/ecs_task_definitions_logging_block_mode/ecs_task_definitions_logging_block_mode.metadata.json +19 -12
- prowler/providers/aws/services/ecs/ecs_task_definitions_logging_enabled/ecs_task_definitions_logging_enabled.metadata.json +18 -12
- prowler/providers/aws/services/ecs/ecs_task_definitions_no_environment_secrets/ecs_task_definitions_no_environment_secrets.metadata.json +16 -12
- prowler/providers/aws/services/ecs/ecs_task_definitions_no_privileged_containers/ecs_task_definitions_no_privileged_containers.metadata.json +21 -14
- prowler/providers/aws/services/ecs/ecs_task_set_no_assign_public_ip/ecs_task_set_no_assign_public_ip.metadata.json +19 -13
- prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json +20 -13
- prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.metadata.json +20 -13
- prowler/providers/aws/services/eks/eks_cluster_network_policy_enabled/eks_cluster_network_policy_enabled.metadata.json +20 -14
- prowler/providers/aws/services/eks/eks_cluster_not_publicly_accessible/eks_cluster_not_publicly_accessible.metadata.json +22 -13
- prowler/providers/aws/services/eks/eks_cluster_private_nodes_enabled/eks_cluster_private_nodes_enabled.metadata.json +19 -13
- prowler/providers/aws/services/eks/eks_cluster_uses_a_supported_version/eks_cluster_uses_a_supported_version.metadata.json +21 -12
- prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.metadata.json +20 -13
- prowler/providers/aws/services/elasticache/elasticache_cluster_uses_public_subnet/elasticache_cluster_uses_public_subnet.metadata.json +20 -12
- prowler/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades.metadata.json +21 -12
- prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json +20 -13
- prowler/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled.metadata.json +23 -13
- prowler/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled.metadata.json +21 -12
- prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json +22 -14
- prowler/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled.metadata.json +20 -11
- prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.metadata.json +23 -13
- prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_cloudwatch_logging_enabled/elasticbeanstalk_environment_cloudwatch_logging_enabled.metadata.json +18 -12
- prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_enhanced_health_reporting/elasticbeanstalk_environment_enhanced_health_reporting.metadata.json +17 -12
- prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_managed_updates_enabled/elasticbeanstalk_environment_managed_updates_enabled.metadata.json +17 -11
- prowler/providers/aws/services/elb/elb_connection_draining_enabled/elb_connection_draining_enabled.metadata.json +22 -13
- prowler/providers/aws/services/elb/elb_cross_zone_load_balancing_enabled/elb_cross_zone_load_balancing_enabled.metadata.json +24 -13
- prowler/providers/aws/services/elb/elb_desync_mitigation_mode/elb_desync_mitigation_mode.metadata.json +20 -11
- prowler/providers/aws/services/elb/elb_insecure_ssl_ciphers/elb_insecure_ssl_ciphers.metadata.json +20 -10
- prowler/providers/aws/services/elb/elb_internet_facing/elb_internet_facing.metadata.json +20 -11
- prowler/providers/aws/services/elb/elb_is_in_multiple_az/elb_is_in_multiple_az.metadata.json +20 -12
- prowler/providers/aws/services/elb/elb_logging_enabled/elb_logging_enabled.metadata.json +19 -12
- prowler/providers/aws/services/elb/elb_ssl_listeners/elb_ssl_listeners.metadata.json +19 -11
- prowler/providers/aws/services/elb/elb_ssl_listeners_use_acm_certificate/elb_ssl_listeners_use_acm_certificate.metadata.json +17 -12
- prowler/providers/aws/services/elbv2/elbv2_cross_zone_load_balancing_enabled/elbv2_cross_zone_load_balancing_enabled.metadata.json +21 -13
- prowler/providers/aws/services/elbv2/elbv2_deletion_protection/elbv2_deletion_protection.metadata.json +19 -11
- prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.metadata.json +21 -12
- prowler/providers/aws/services/elbv2/elbv2_insecure_ssl_ciphers/elbv2_insecure_ssl_ciphers.metadata.json +18 -11
- prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.metadata.json +17 -10
- prowler/providers/aws/services/elbv2/elbv2_is_in_multiple_az/elbv2_is_in_multiple_az.metadata.json +22 -13
- prowler/providers/aws/services/elbv2/elbv2_listeners_underneath/elbv2_listeners_underneath.metadata.json +18 -12
- prowler/providers/aws/services/elbv2/elbv2_logging_enabled/elbv2_logging_enabled.metadata.json +17 -12
- prowler/providers/aws/services/elbv2/elbv2_nlb_tls_termination_enabled/elbv2_nlb_tls_termination_enabled.metadata.json +18 -11
- prowler/providers/aws/services/elbv2/elbv2_ssl_listeners/elbv2_ssl_listeners.metadata.json +18 -12
- prowler/providers/aws/services/elbv2/elbv2_waf_acl_attached/elbv2_waf_acl_attached.metadata.json +16 -11
- prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json +21 -13
- prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json +24 -11
- prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json +18 -11
- prowler/providers/aws/services/eventbridge/eventbridge_bus_cross_account_access/eventbridge_bus_cross_account_access.metadata.json +26 -13
- prowler/providers/aws/services/eventbridge/eventbridge_bus_exposed/eventbridge_bus_exposed.metadata.json +21 -11
- prowler/providers/aws/services/eventbridge/eventbridge_global_endpoint_event_replication_enabled/eventbridge_global_endpoint_event_replication_enabled.metadata.json +24 -13
- prowler/providers/aws/services/eventbridge/eventbridge_schema_registry_cross_account_access/eventbridge_schema_registry_cross_account_access.metadata.json +26 -14
- prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json +26 -15
- prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py +15 -16
- prowler/providers/aws/services/fms/fms_policy_compliant/fms_policy_compliant.metadata.json +23 -11
- prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_backups_enabled/fsx_file_system_copy_tags_to_backups_enabled.metadata.json +19 -12
- prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_volumes_enabled/fsx_file_system_copy_tags_to_volumes_enabled.metadata.json +17 -12
- prowler/providers/aws/services/fsx/fsx_windows_file_system_multi_az_enabled/fsx_windows_file_system_multi_az_enabled.metadata.json +22 -13
- prowler/providers/aws/services/glacier/glacier_vaults_policy_public_access/glacier_vaults_policy_public_access.metadata.json +21 -12
- prowler/providers/aws/services/iam/lib/policy.py +24 -16
- prowler/providers/aws/services/kinesis/kinesis_stream_data_retention_period/kinesis_stream_data_retention_period.metadata.json +21 -13
- prowler/providers/aws/services/kinesis/kinesis_stream_encrypted_at_rest/kinesis_stream_encrypted_at_rest.metadata.json +22 -13
- prowler/providers/azure/services/cosmosdb/cosmosdb_service.py +7 -2
- prowler/providers/azure/services/defender/defender_service.py +4 -2
- prowler/providers/azure/services/postgresql/postgresql_flexible_server_entra_id_authentication_enabled/__init__.py +0 -0
- prowler/providers/azure/services/postgresql/postgresql_flexible_server_entra_id_authentication_enabled/postgresql_flexible_server_entra_id_authentication_enabled.metadata.json +36 -0
- prowler/providers/azure/services/postgresql/postgresql_flexible_server_entra_id_authentication_enabled/postgresql_flexible_server_entra_id_authentication_enabled.py +43 -0
- prowler/providers/azure/services/postgresql/postgresql_service.py +66 -9
- prowler/providers/azure/services/storage/storage_service.py +13 -4
- prowler/providers/azure/services/vm/vm_service.py +4 -7
- prowler/providers/common/arguments.py +19 -16
- prowler/providers/common/provider.py +2 -18
- prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json +16 -15
- prowler/providers/gcp/services/cloudresourcemanager/cloudresourcemanager_service.py +30 -4
- prowler/providers/gcp/services/cloudstorage/cloudstorage_audit_logs_enabled/__init__.py +0 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_audit_logs_enabled/cloudstorage_audit_logs_enabled.metadata.json +36 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_audit_logs_enabled/cloudstorage_audit_logs_enabled.py +61 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_log_retention_policy_lock/cloudstorage_bucket_log_retention_policy_lock.metadata.json +12 -9
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_log_retention_policy_lock/cloudstorage_bucket_log_retention_policy_lock.py +10 -3
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/__init__.py +0 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.metadata.json +36 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.py +40 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/__init__.py +0 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.metadata.json +36 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.py +31 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_sufficient_retention_period/__init__.py +0 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_sufficient_retention_period/cloudstorage_bucket_sufficient_retention_period.metadata.json +35 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_sufficient_retention_period/cloudstorage_bucket_sufficient_retention_period.py +55 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/__init__.py +0 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.metadata.json +36 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.py +30 -0
- prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py +48 -2
- prowler/providers/github/services/organization/organization_default_repository_permission_strict/__init__.py +0 -0
- prowler/providers/github/services/organization/organization_default_repository_permission_strict/organization_default_repository_permission_strict.metadata.json +35 -0
- prowler/providers/github/services/organization/organization_default_repository_permission_strict/organization_default_repository_permission_strict.py +36 -0
- prowler/providers/github/services/organization/organization_members_mfa_required/organization_members_mfa_required.metadata.json +14 -8
- prowler/providers/github/services/organization/organization_repository_creation_limited/__init__.py +0 -0
- prowler/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited.metadata.json +30 -0
- prowler/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited.py +106 -0
- prowler/providers/github/services/organization/organization_service.py +84 -10
- prowler/providers/iac/iac_provider.py +279 -55
- prowler/providers/kubernetes/services/etcd/etcd_client_cert_auth/etcd_client_cert_auth.metadata.json +18 -13
- prowler/providers/kubernetes/services/etcd/etcd_no_auto_tls/etcd_no_auto_tls.metadata.json +16 -11
- prowler/providers/kubernetes/services/etcd/etcd_no_peer_auto_tls/etcd_no_peer_auto_tls.metadata.json +16 -11
- prowler/providers/kubernetes/services/etcd/etcd_peer_client_cert_auth/etcd_peer_client_cert_auth.metadata.json +18 -13
- prowler/providers/kubernetes/services/etcd/etcd_peer_tls_config/etcd_peer_tls_config.metadata.json +16 -12
- prowler/providers/kubernetes/services/etcd/etcd_tls_encryption/etcd_tls_encryption.metadata.json +16 -11
- prowler/providers/kubernetes/services/etcd/etcd_unique_ca/etcd_unique_ca.metadata.json +16 -10
- prowler/providers/m365/lib/powershell/m365_powershell.py +80 -93
- prowler/providers/m365/m365_provider.py +1 -6
- prowler/providers/mongodbatlas/exceptions/exceptions.py +16 -0
- prowler/providers/mongodbatlas/mongodbatlas_provider.py +15 -3
- prowler/providers/mongodbatlas/services/projects/projects_auditing_enabled/projects_auditing_enabled.metadata.json +20 -9
- prowler/providers/mongodbatlas/services/projects/projects_network_access_list_exposed_to_internet/projects_network_access_list_exposed_to_internet.metadata.json +14 -9
- prowler/providers/oraclecloud/lib/arguments/arguments.py +4 -13
- prowler/providers/oraclecloud/lib/service/service.py +3 -3
- prowler/providers/oraclecloud/{oci_provider.py → oraclecloud_provider.py} +15 -15
- prowler/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted.metadata.json +20 -16
- prowler/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days.metadata.json +17 -17
- prowler/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk.metadata.json +17 -19
- prowler/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk.metadata.json +18 -18
- prowler/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled.metadata.json +17 -18
- prowler/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled.metadata.json +1 -1
- prowler/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled.metadata.json +1 -1
- prowler/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled.metadata.json +1 -1
- prowler/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes.metadata.json +1 -1
- prowler/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access.metadata.json +1 -1
- prowler/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address.metadata.json +1 -1
- prowler/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted.metadata.json +1 -1
- prowler/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled.metadata.json +1 -1
- prowler/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic.metadata.json +1 -1
- prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port.metadata.json +1 -1
- prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port.metadata.json +1 -1
- prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port.metadata.json +1 -1
- prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port.metadata.json +1 -1
- prowler/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled.metadata.json +1 -1
- prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk.metadata.json +1 -1
- prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled.metadata.json +1 -1
- prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible.metadata.json +1 -1
- prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled.metadata.json +1 -1
- {prowler_cloud-5.13.1.dist-info → prowler_cloud-5.14.0.dist-info}/METADATA +17 -16
- {prowler_cloud-5.13.1.dist-info → prowler_cloud-5.14.0.dist-info}/RECORD +295 -246
- /prowler/compliance/{oci → oraclecloud}/__init__.py +0 -0
- {prowler_cloud-5.13.1.dist-info → prowler_cloud-5.14.0.dist-info}/LICENSE +0 -0
- {prowler_cloud-5.13.1.dist-info → prowler_cloud-5.14.0.dist-info}/WHEEL +0 -0
- {prowler_cloud-5.13.1.dist-info → prowler_cloud-5.14.0.dist-info}/entry_points.txt +0 -0
|
@@ -5,7 +5,7 @@ from pydantic.v1 import BaseModel
|
|
|
5
5
|
|
|
6
6
|
from prowler.lib.logger import logger
|
|
7
7
|
from prowler.providers.github.lib.service.service import GithubService
|
|
8
|
-
from prowler.providers.github.models import GithubAppIdentityInfo
|
|
8
|
+
from prowler.providers.github.models import GithubAppIdentityInfo
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Organization(GithubService):
|
|
@@ -38,13 +38,16 @@ class Organization(GithubService):
|
|
|
38
38
|
org_names_to_check = set()
|
|
39
39
|
|
|
40
40
|
try:
|
|
41
|
-
|
|
41
|
+
clients = getattr(self, "clients", [])
|
|
42
|
+
for client in clients:
|
|
42
43
|
if self.provider.organizations:
|
|
43
44
|
org_names_to_check.update(self.provider.organizations)
|
|
44
45
|
|
|
45
46
|
# If repositories are specified without organizations, don't perform organization checks
|
|
46
47
|
# Only add repository owners to organization checks if organizations are also specified
|
|
47
|
-
if self.provider
|
|
48
|
+
if getattr(self.provider, "repositories", None) and getattr(
|
|
49
|
+
self.provider, "organizations", None
|
|
50
|
+
):
|
|
48
51
|
for repo_name in self.provider.repositories:
|
|
49
52
|
if "/" in repo_name:
|
|
50
53
|
owner_name = repo_name.split("/")[0]
|
|
@@ -111,18 +114,19 @@ class Organization(GithubService):
|
|
|
111
114
|
logger.error(
|
|
112
115
|
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
|
113
116
|
)
|
|
114
|
-
elif not self.provider
|
|
117
|
+
elif not getattr(self.provider, "repositories", None):
|
|
115
118
|
# Default behavior: get all organizations the user is a member of
|
|
116
119
|
# Only when no repositories are specified
|
|
117
|
-
if isinstance(self.provider.identity,
|
|
118
|
-
orgs = client.get_user().get_orgs()
|
|
119
|
-
for org in orgs:
|
|
120
|
-
self._process_organization(org, organizations)
|
|
121
|
-
elif isinstance(self.provider.identity, GithubAppIdentityInfo):
|
|
120
|
+
if isinstance(self.provider.identity, GithubAppIdentityInfo):
|
|
122
121
|
orgs = client.get_organizations()
|
|
123
|
-
if orgs
|
|
122
|
+
if getattr(orgs, "totalCount", 0) > 0:
|
|
124
123
|
for org in orgs:
|
|
125
124
|
self._process_organization(org, organizations)
|
|
125
|
+
else:
|
|
126
|
+
# Default (personal access/OAuth): use user organizations
|
|
127
|
+
orgs = client.get_user().get_orgs()
|
|
128
|
+
for org in orgs:
|
|
129
|
+
self._process_organization(org, organizations)
|
|
126
130
|
|
|
127
131
|
except github.RateLimitExceededException as error:
|
|
128
132
|
logger.error(f"GitHub API rate limit exceeded: {error}")
|
|
@@ -144,10 +148,74 @@ class Organization(GithubService):
|
|
|
144
148
|
logger.error(
|
|
145
149
|
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
|
146
150
|
)
|
|
151
|
+
repo_creation_settings = {
|
|
152
|
+
"members_can_create_repositories": None,
|
|
153
|
+
"members_can_create_public_repositories": None,
|
|
154
|
+
"members_can_create_private_repositories": None,
|
|
155
|
+
"members_can_create_internal_repositories": None,
|
|
156
|
+
"members_allowed_repository_creation_type": None,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
def _extract_flag(attribute: str, expected_type: type):
|
|
160
|
+
"""Return attribute value if it matches expected type and is not a mock placeholder."""
|
|
161
|
+
try:
|
|
162
|
+
value = getattr(org, attribute, None)
|
|
163
|
+
if hasattr(value, "_mock_parent"):
|
|
164
|
+
return None
|
|
165
|
+
if expected_type is bool and isinstance(value, bool):
|
|
166
|
+
return value
|
|
167
|
+
if expected_type is str and isinstance(value, str):
|
|
168
|
+
return value
|
|
169
|
+
return None
|
|
170
|
+
except Exception as error:
|
|
171
|
+
logger.error(
|
|
172
|
+
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
|
173
|
+
)
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
repo_creation_settings["members_can_create_repositories"] = _extract_flag(
|
|
177
|
+
"members_can_create_repositories", bool
|
|
178
|
+
)
|
|
179
|
+
repo_creation_settings["members_can_create_public_repositories"] = (
|
|
180
|
+
_extract_flag("members_can_create_public_repositories", bool)
|
|
181
|
+
)
|
|
182
|
+
repo_creation_settings["members_can_create_private_repositories"] = (
|
|
183
|
+
_extract_flag("members_can_create_private_repositories", bool)
|
|
184
|
+
)
|
|
185
|
+
repo_creation_settings["members_can_create_internal_repositories"] = (
|
|
186
|
+
_extract_flag("members_can_create_internal_repositories", bool)
|
|
187
|
+
)
|
|
188
|
+
repo_creation_settings["members_allowed_repository_creation_type"] = (
|
|
189
|
+
_extract_flag("members_allowed_repository_creation_type", str)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
base_permission_raw = _extract_flag("default_repository_permission", str)
|
|
193
|
+
base_permission = (
|
|
194
|
+
base_permission_raw.lower()
|
|
195
|
+
if isinstance(base_permission_raw, str)
|
|
196
|
+
else None
|
|
197
|
+
)
|
|
198
|
+
|
|
147
199
|
organizations[org.id] = Org(
|
|
148
200
|
id=org.id,
|
|
149
201
|
name=org.login,
|
|
150
202
|
mfa_required=require_mfa,
|
|
203
|
+
members_can_create_repositories=repo_creation_settings[
|
|
204
|
+
"members_can_create_repositories"
|
|
205
|
+
],
|
|
206
|
+
members_can_create_public_repositories=repo_creation_settings[
|
|
207
|
+
"members_can_create_public_repositories"
|
|
208
|
+
],
|
|
209
|
+
members_can_create_private_repositories=repo_creation_settings[
|
|
210
|
+
"members_can_create_private_repositories"
|
|
211
|
+
],
|
|
212
|
+
members_can_create_internal_repositories=repo_creation_settings[
|
|
213
|
+
"members_can_create_internal_repositories"
|
|
214
|
+
],
|
|
215
|
+
members_allowed_repository_creation_type=repo_creation_settings[
|
|
216
|
+
"members_allowed_repository_creation_type"
|
|
217
|
+
],
|
|
218
|
+
base_permission=base_permission,
|
|
151
219
|
)
|
|
152
220
|
|
|
153
221
|
|
|
@@ -157,3 +225,9 @@ class Org(BaseModel):
|
|
|
157
225
|
id: int
|
|
158
226
|
name: str
|
|
159
227
|
mfa_required: Optional[bool] = False
|
|
228
|
+
members_can_create_repositories: Optional[bool] = None
|
|
229
|
+
members_can_create_public_repositories: Optional[bool] = None
|
|
230
|
+
members_can_create_private_repositories: Optional[bool] = None
|
|
231
|
+
members_can_create_internal_repositories: Optional[bool] = None
|
|
232
|
+
members_allowed_repository_creation_type: Optional[str] = None
|
|
233
|
+
base_permission: Optional[str] = None
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import re
|
|
2
3
|
import shutil
|
|
3
4
|
import subprocess
|
|
4
5
|
import sys
|
|
5
6
|
import tempfile
|
|
6
7
|
from os import environ
|
|
7
|
-
from typing import List
|
|
8
|
+
from typing import Generator, List
|
|
8
9
|
|
|
9
10
|
from alive_progress import alive_bar
|
|
10
11
|
from colorama import Fore, Style
|
|
@@ -17,7 +18,7 @@ from prowler.config.config import (
|
|
|
17
18
|
from prowler.lib.check.models import CheckReportIAC
|
|
18
19
|
from prowler.lib.logger import logger
|
|
19
20
|
from prowler.lib.utils.utils import print_boxes
|
|
20
|
-
from prowler.providers.common.models import Audit_Metadata
|
|
21
|
+
from prowler.providers.common.models import Audit_Metadata, Connection
|
|
21
22
|
from prowler.providers.common.provider import Provider
|
|
22
23
|
|
|
23
24
|
|
|
@@ -44,11 +45,12 @@ class IacProvider(Provider):
|
|
|
44
45
|
self.scan_repository_url = scan_repository_url
|
|
45
46
|
self.scanners = scanners
|
|
46
47
|
self.exclude_path = exclude_path
|
|
47
|
-
self.region = "
|
|
48
|
+
self.region = "branch"
|
|
48
49
|
self.audited_account = "local-iac"
|
|
49
50
|
self._session = None
|
|
50
51
|
self._identity = "prowler"
|
|
51
52
|
self._auth_method = "No auth"
|
|
53
|
+
self._temp_clone_dir = None # Track temporary directory for cleanup
|
|
52
54
|
|
|
53
55
|
if scan_repository_url:
|
|
54
56
|
oauth_app_token = oauth_app_token or environ.get("GITHUB_OAUTH_APP_TOKEN")
|
|
@@ -79,6 +81,20 @@ class IacProvider(Provider):
|
|
|
79
81
|
"No GitHub authentication method provided; proceeding without authentication."
|
|
80
82
|
)
|
|
81
83
|
|
|
84
|
+
# Clone repository and detect branch during initialization
|
|
85
|
+
# This ensures the branch is detected for both CLI and API usage
|
|
86
|
+
self._temp_clone_dir, branch_name = self._clone_repository(
|
|
87
|
+
self.scan_repository_url,
|
|
88
|
+
self.github_username,
|
|
89
|
+
self.personal_access_token,
|
|
90
|
+
self.oauth_app_token,
|
|
91
|
+
)
|
|
92
|
+
# Update scan_path to point to the cloned repository
|
|
93
|
+
self.scan_path = self._temp_clone_dir
|
|
94
|
+
# Update region with the detected branch name
|
|
95
|
+
self.region = branch_name
|
|
96
|
+
logger.info(f"Updated region to branch: {branch_name}")
|
|
97
|
+
|
|
82
98
|
# Audit Config
|
|
83
99
|
if config_content:
|
|
84
100
|
self._audit_config = config_content
|
|
@@ -130,6 +146,20 @@ class IacProvider(Provider):
|
|
|
130
146
|
def fixer_config(self):
|
|
131
147
|
return self._fixer_config
|
|
132
148
|
|
|
149
|
+
def __del__(self):
|
|
150
|
+
"""Cleanup temporary directory when provider is destroyed"""
|
|
151
|
+
self.cleanup()
|
|
152
|
+
|
|
153
|
+
def cleanup(self):
|
|
154
|
+
"""Remove temporary cloned repository if it exists"""
|
|
155
|
+
if self._temp_clone_dir:
|
|
156
|
+
try:
|
|
157
|
+
logger.info(f"Removing temporary directory {self._temp_clone_dir}...")
|
|
158
|
+
shutil.rmtree(self._temp_clone_dir)
|
|
159
|
+
self._temp_clone_dir = None
|
|
160
|
+
except Exception as error:
|
|
161
|
+
logger.warning(f"Failed to remove temporary directory: {error}")
|
|
162
|
+
|
|
133
163
|
def setup_session(self):
|
|
134
164
|
"""IAC provider doesn't need a session since it uses Trivy directly"""
|
|
135
165
|
return None
|
|
@@ -173,7 +203,7 @@ class IacProvider(Provider):
|
|
|
173
203
|
"Severity": finding["Severity"],
|
|
174
204
|
"ResourceType": "iac",
|
|
175
205
|
"Description": finding_description,
|
|
176
|
-
"Risk": "",
|
|
206
|
+
"Risk": "This provider has not defined a risk for this check.",
|
|
177
207
|
"RelatedUrl": finding.get("PrimaryURL", ""),
|
|
178
208
|
"Remediation": {
|
|
179
209
|
"Code": {
|
|
@@ -207,6 +237,8 @@ class IacProvider(Provider):
|
|
|
207
237
|
)
|
|
208
238
|
if finding_status == "MUTED":
|
|
209
239
|
report.muted = True
|
|
240
|
+
# Set the region from the provider
|
|
241
|
+
report.region = self.region
|
|
210
242
|
return report
|
|
211
243
|
except Exception as error:
|
|
212
244
|
logger.critical(
|
|
@@ -214,15 +246,50 @@ class IacProvider(Provider):
|
|
|
214
246
|
)
|
|
215
247
|
sys.exit(1)
|
|
216
248
|
|
|
249
|
+
def _detect_branch_name(self, repo_path: str) -> str:
|
|
250
|
+
"""
|
|
251
|
+
Detect the current branch name from a cloned repository.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
repo_path: Path to the cloned repository
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
str: The branch name, defaulting to "main" if detection fails
|
|
258
|
+
"""
|
|
259
|
+
try:
|
|
260
|
+
import os
|
|
261
|
+
|
|
262
|
+
# Read .git/HEAD to detect the current branch
|
|
263
|
+
head_file = os.path.join(repo_path, ".git", "HEAD")
|
|
264
|
+
if os.path.exists(head_file):
|
|
265
|
+
with open(head_file, "r") as f:
|
|
266
|
+
content = f.read().strip()
|
|
267
|
+
# Format: "ref: refs/heads/branch-name"
|
|
268
|
+
if content.startswith("ref: refs/heads/"):
|
|
269
|
+
branch_name = content[16:] # Remove "ref: refs/heads/"
|
|
270
|
+
logger.info(f"Detected branch: {branch_name}")
|
|
271
|
+
return branch_name
|
|
272
|
+
|
|
273
|
+
# Fallback: return "main" as default
|
|
274
|
+
logger.warning("Could not detect branch name, defaulting to 'main'")
|
|
275
|
+
return "main"
|
|
276
|
+
|
|
277
|
+
except Exception as error:
|
|
278
|
+
logger.error(f"Error detecting branch name: {error}")
|
|
279
|
+
return "main" # Safe fallback
|
|
280
|
+
|
|
217
281
|
def _clone_repository(
|
|
218
282
|
self,
|
|
219
283
|
repository_url: str,
|
|
220
284
|
github_username: str = None,
|
|
221
285
|
personal_access_token: str = None,
|
|
222
286
|
oauth_app_token: str = None,
|
|
223
|
-
) -> str:
|
|
287
|
+
) -> tuple[str, str]:
|
|
224
288
|
"""
|
|
225
289
|
Clone a git repository to a temporary directory, supporting GitHub authentication.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
tuple[str, str]: (temporary_directory, branch_name)
|
|
226
293
|
"""
|
|
227
294
|
try:
|
|
228
295
|
original_url = repository_url
|
|
@@ -242,50 +309,75 @@ class IacProvider(Provider):
|
|
|
242
309
|
logger.info(
|
|
243
310
|
f"Cloning repository {original_url} into {temporary_directory}..."
|
|
244
311
|
)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
312
|
+
|
|
313
|
+
# Check if we're in an environment with a TTY
|
|
314
|
+
# Celery workers and other non-interactive environments don't have TTY
|
|
315
|
+
# and cannot use the alive_bar
|
|
316
|
+
try:
|
|
317
|
+
if sys.stdout.isatty():
|
|
318
|
+
with alive_bar(
|
|
319
|
+
ctrl_c=False,
|
|
320
|
+
bar="blocks",
|
|
321
|
+
spinner="classic",
|
|
322
|
+
stats=False,
|
|
323
|
+
enrich_print=False,
|
|
324
|
+
) as bar:
|
|
325
|
+
try:
|
|
326
|
+
bar.title = f"-> Cloning {original_url}..."
|
|
327
|
+
porcelain.clone(
|
|
328
|
+
repository_url, temporary_directory, depth=1
|
|
329
|
+
)
|
|
330
|
+
bar.title = "-> Repository cloned successfully!"
|
|
331
|
+
except Exception as clone_error:
|
|
332
|
+
bar.title = "-> Cloning failed!"
|
|
333
|
+
raise clone_error
|
|
334
|
+
else:
|
|
335
|
+
# No TTY, just clone without progress bar
|
|
336
|
+
logger.info(f"Cloning {original_url}...")
|
|
254
337
|
porcelain.clone(repository_url, temporary_directory, depth=1)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
338
|
+
logger.info("Repository cloned successfully!")
|
|
339
|
+
except (AttributeError, OSError):
|
|
340
|
+
# Fallback if isatty() check fails
|
|
341
|
+
logger.info(f"Cloning {original_url}...")
|
|
342
|
+
porcelain.clone(repository_url, temporary_directory, depth=1)
|
|
343
|
+
logger.info("Repository cloned successfully!")
|
|
344
|
+
|
|
345
|
+
# Detect the branch name from the cloned repository
|
|
346
|
+
branch_name = self._detect_branch_name(temporary_directory)
|
|
347
|
+
|
|
348
|
+
return temporary_directory, branch_name
|
|
260
349
|
except Exception as error:
|
|
261
350
|
logger.critical(
|
|
262
351
|
f"{error.__class__.__name__}:{error.__traceback__.tb_lineno} -- {error}"
|
|
263
352
|
)
|
|
264
353
|
|
|
265
354
|
def run(self) -> List[CheckReportIAC]:
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
scan_dir = temp_dir = self._clone_repository(
|
|
269
|
-
self.scan_repository_url,
|
|
270
|
-
getattr(self, "github_username", None),
|
|
271
|
-
getattr(self, "personal_access_token", None),
|
|
272
|
-
getattr(self, "oauth_app_token", None),
|
|
273
|
-
)
|
|
274
|
-
else:
|
|
275
|
-
scan_dir = self.scan_path
|
|
355
|
+
"""
|
|
356
|
+
Execute the IaC scan.
|
|
276
357
|
|
|
358
|
+
Note: Repository cloning and branch detection now happen in __init__(),
|
|
359
|
+
so this method just runs the scan and returns results.
|
|
360
|
+
For CLI compatibility, cleanup is still performed at the end.
|
|
361
|
+
"""
|
|
277
362
|
try:
|
|
278
|
-
|
|
363
|
+
# Collect all batches from the generator
|
|
364
|
+
# scan_path now points to either the local directory or the cloned repo
|
|
365
|
+
reports = []
|
|
366
|
+
for batch in self.run_scan(
|
|
367
|
+
self.scan_path, self.scanners, self.exclude_path
|
|
368
|
+
):
|
|
369
|
+
reports.extend(batch)
|
|
279
370
|
finally:
|
|
280
|
-
if
|
|
281
|
-
|
|
282
|
-
|
|
371
|
+
# Clean up temporary directory if this was a repository scan
|
|
372
|
+
# This ensures CLI usage cleans up immediately after run()
|
|
373
|
+
if self._temp_clone_dir:
|
|
374
|
+
self.cleanup()
|
|
283
375
|
|
|
284
376
|
return reports
|
|
285
377
|
|
|
286
378
|
def run_scan(
|
|
287
379
|
self, directory: str, scanners: list[str], exclude_path: list[str]
|
|
288
|
-
) -> List[CheckReportIAC]:
|
|
380
|
+
) -> Generator[List[CheckReportIAC], None, None]:
|
|
289
381
|
try:
|
|
290
382
|
logger.info(f"Running IaC scan on {directory} ...")
|
|
291
383
|
trivy_command = [
|
|
@@ -302,25 +394,47 @@ class IacProvider(Provider):
|
|
|
302
394
|
]
|
|
303
395
|
if exclude_path:
|
|
304
396
|
trivy_command.extend(["--skip-dirs", ",".join(exclude_path)])
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
397
|
+
|
|
398
|
+
# Check if we're in an environment with a TTY
|
|
399
|
+
try:
|
|
400
|
+
if sys.stdout.isatty():
|
|
401
|
+
with alive_bar(
|
|
402
|
+
ctrl_c=False,
|
|
403
|
+
bar="blocks",
|
|
404
|
+
spinner="classic",
|
|
405
|
+
stats=False,
|
|
406
|
+
enrich_print=False,
|
|
407
|
+
) as bar:
|
|
408
|
+
try:
|
|
409
|
+
bar.title = f"-> Running IaC scan on {directory} ..."
|
|
410
|
+
# Run Trivy with JSON output
|
|
411
|
+
process = subprocess.run(
|
|
412
|
+
trivy_command,
|
|
413
|
+
capture_output=True,
|
|
414
|
+
text=True,
|
|
415
|
+
)
|
|
416
|
+
bar.title = "-> Scan completed!"
|
|
417
|
+
except Exception as error:
|
|
418
|
+
bar.title = "-> Scan failed!"
|
|
419
|
+
raise error
|
|
420
|
+
else:
|
|
421
|
+
# No TTY, just run without progress bar
|
|
422
|
+
logger.info(f"Running Trivy scan on {directory}...")
|
|
315
423
|
process = subprocess.run(
|
|
316
424
|
trivy_command,
|
|
317
425
|
capture_output=True,
|
|
318
426
|
text=True,
|
|
319
427
|
)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
428
|
+
logger.info("Trivy scan completed!")
|
|
429
|
+
except (AttributeError, OSError):
|
|
430
|
+
# Fallback if isatty() check fails
|
|
431
|
+
logger.info(f"Running Trivy scan on {directory}...")
|
|
432
|
+
process = subprocess.run(
|
|
433
|
+
trivy_command,
|
|
434
|
+
capture_output=True,
|
|
435
|
+
text=True,
|
|
436
|
+
)
|
|
437
|
+
logger.info("Trivy scan completed!")
|
|
324
438
|
# Log Trivy's stderr output with preserved log levels
|
|
325
439
|
if process.stderr:
|
|
326
440
|
for line in process.stderr.strip().split("\n"):
|
|
@@ -354,14 +468,15 @@ class IacProvider(Provider):
|
|
|
354
468
|
|
|
355
469
|
if not output:
|
|
356
470
|
logger.warning("No findings returned from Trivy scan")
|
|
357
|
-
return
|
|
471
|
+
return
|
|
358
472
|
except Exception as error:
|
|
359
473
|
logger.critical(
|
|
360
474
|
f"{error.__class__.__name__}:{error.__traceback__.tb_lineno} -- {error}"
|
|
361
475
|
)
|
|
362
476
|
sys.exit(1)
|
|
363
477
|
|
|
364
|
-
|
|
478
|
+
batch = []
|
|
479
|
+
batch_size = 100
|
|
365
480
|
|
|
366
481
|
# Process all trivy findings
|
|
367
482
|
for finding in output:
|
|
@@ -371,27 +486,44 @@ class IacProvider(Provider):
|
|
|
371
486
|
report = self._process_finding(
|
|
372
487
|
misconfiguration, finding["Target"], finding["Type"]
|
|
373
488
|
)
|
|
374
|
-
|
|
489
|
+
batch.append(report)
|
|
490
|
+
if len(batch) >= batch_size:
|
|
491
|
+
yield batch
|
|
492
|
+
batch = []
|
|
493
|
+
|
|
375
494
|
# Process Vulnerabilities
|
|
376
495
|
for vulnerability in finding.get("Vulnerabilities", []):
|
|
377
496
|
report = self._process_finding(
|
|
378
497
|
vulnerability, finding["Target"], finding["Type"]
|
|
379
498
|
)
|
|
380
|
-
|
|
499
|
+
batch.append(report)
|
|
500
|
+
if len(batch) >= batch_size:
|
|
501
|
+
yield batch
|
|
502
|
+
batch = []
|
|
503
|
+
|
|
381
504
|
# Process Secrets
|
|
382
505
|
for secret in finding.get("Secrets", []):
|
|
383
506
|
report = self._process_finding(
|
|
384
507
|
secret, finding["Target"], finding["Class"]
|
|
385
508
|
)
|
|
386
|
-
|
|
509
|
+
batch.append(report)
|
|
510
|
+
if len(batch) >= batch_size:
|
|
511
|
+
yield batch
|
|
512
|
+
batch = []
|
|
513
|
+
|
|
387
514
|
# Process Licenses
|
|
388
515
|
for license in finding.get("Licenses", []):
|
|
389
516
|
report = self._process_finding(
|
|
390
517
|
license, finding["Target"], finding["Type"]
|
|
391
518
|
)
|
|
392
|
-
|
|
519
|
+
batch.append(report)
|
|
520
|
+
if len(batch) >= batch_size:
|
|
521
|
+
yield batch
|
|
522
|
+
batch = []
|
|
393
523
|
|
|
394
|
-
|
|
524
|
+
# Yield any remaining findings in the last batch
|
|
525
|
+
if batch:
|
|
526
|
+
yield batch
|
|
395
527
|
|
|
396
528
|
except Exception as error:
|
|
397
529
|
if "No such file or directory: 'trivy'" in str(error):
|
|
@@ -434,3 +566,95 @@ class IacProvider(Provider):
|
|
|
434
566
|
)
|
|
435
567
|
|
|
436
568
|
print_boxes(report_lines, report_title)
|
|
569
|
+
|
|
570
|
+
@staticmethod
|
|
571
|
+
def test_connection(
|
|
572
|
+
scan_repository_url: str = None,
|
|
573
|
+
oauth_app_token: str = None,
|
|
574
|
+
access_token: str = None,
|
|
575
|
+
raise_on_exception: bool = True,
|
|
576
|
+
provider_id: str = None,
|
|
577
|
+
) -> "Connection":
|
|
578
|
+
"""Test connection to IaC repository.
|
|
579
|
+
|
|
580
|
+
Test the connection to the IaC repository using the provided credentials.
|
|
581
|
+
|
|
582
|
+
Args:
|
|
583
|
+
scan_repository_url (str): Repository URL to scan.
|
|
584
|
+
oauth_app_token (str): OAuth App token for authentication.
|
|
585
|
+
access_token (str): Access token for authentication (alias for oauth_app_token).
|
|
586
|
+
raise_on_exception (bool): Flag indicating whether to raise an exception if the connection fails.
|
|
587
|
+
provider_id (str): The provider ID, in this case it's the repository URL.
|
|
588
|
+
|
|
589
|
+
Returns:
|
|
590
|
+
Connection: Connection object with success status or error information.
|
|
591
|
+
|
|
592
|
+
Raises:
|
|
593
|
+
Exception: If failed to test the connection to the repository.
|
|
594
|
+
|
|
595
|
+
Examples:
|
|
596
|
+
>>> IacProvider.test_connection(scan_repository_url="https://github.com/user/repo")
|
|
597
|
+
Connection(is_connected=True)
|
|
598
|
+
"""
|
|
599
|
+
try:
|
|
600
|
+
# If provider_id is provided and scan_repository_url is not, use provider_id as the repository URL
|
|
601
|
+
if provider_id and not scan_repository_url:
|
|
602
|
+
scan_repository_url = provider_id
|
|
603
|
+
|
|
604
|
+
# Handle both oauth_app_token and access_token parameters
|
|
605
|
+
if access_token and not oauth_app_token:
|
|
606
|
+
oauth_app_token = access_token
|
|
607
|
+
|
|
608
|
+
if not scan_repository_url:
|
|
609
|
+
return Connection(
|
|
610
|
+
is_connected=False, error="Repository URL is required"
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
# Try to clone the repository to test the connection
|
|
614
|
+
with tempfile.TemporaryDirectory():
|
|
615
|
+
try:
|
|
616
|
+
if oauth_app_token:
|
|
617
|
+
# If token is provided, use it for authentication
|
|
618
|
+
# Extract the domain and path from the URL
|
|
619
|
+
url_pattern = r"(https?://)([^/]+)/(.+)"
|
|
620
|
+
match = re.match(url_pattern, scan_repository_url)
|
|
621
|
+
if match:
|
|
622
|
+
protocol, domain, path = match.groups()
|
|
623
|
+
# Construct URL with token
|
|
624
|
+
auth_url = f"{protocol}x-access-token:{oauth_app_token}@{domain}/{path}"
|
|
625
|
+
else:
|
|
626
|
+
auth_url = scan_repository_url
|
|
627
|
+
else:
|
|
628
|
+
# Public repository
|
|
629
|
+
auth_url = scan_repository_url
|
|
630
|
+
|
|
631
|
+
# Use dulwich to test the connection
|
|
632
|
+
porcelain.ls_remote(auth_url)
|
|
633
|
+
|
|
634
|
+
return Connection(is_connected=True)
|
|
635
|
+
|
|
636
|
+
except Exception as e:
|
|
637
|
+
error_msg = str(e)
|
|
638
|
+
if "authentication" in error_msg.lower() or "401" in error_msg:
|
|
639
|
+
return Connection(
|
|
640
|
+
is_connected=False,
|
|
641
|
+
error="Authentication failed. Please check your access token.",
|
|
642
|
+
)
|
|
643
|
+
elif "404" in error_msg or "not found" in error_msg.lower():
|
|
644
|
+
return Connection(
|
|
645
|
+
is_connected=False,
|
|
646
|
+
error="Repository not found or not accessible.",
|
|
647
|
+
)
|
|
648
|
+
else:
|
|
649
|
+
return Connection(
|
|
650
|
+
is_connected=False,
|
|
651
|
+
error=f"Failed to connect to repository: {error_msg}",
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
except Exception as error:
|
|
655
|
+
if raise_on_exception:
|
|
656
|
+
raise
|
|
657
|
+
return Connection(
|
|
658
|
+
is_connected=False,
|
|
659
|
+
error=f"Unexpected error testing connection: {str(error)}",
|
|
660
|
+
)
|
prowler/providers/kubernetes/services/etcd/etcd_client_cert_auth/etcd_client_cert_auth.metadata.json
CHANGED
|
@@ -1,31 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"Provider": "kubernetes",
|
|
3
3
|
"CheckID": "etcd_client_cert_auth",
|
|
4
|
-
"CheckTitle": "
|
|
4
|
+
"CheckTitle": "Etcd pod has client certificate authentication enabled (--client-cert-auth=true)",
|
|
5
5
|
"CheckType": [],
|
|
6
6
|
"ServiceName": "etcd",
|
|
7
7
|
"SubServiceName": "",
|
|
8
8
|
"ResourceIdTemplate": "",
|
|
9
9
|
"Severity": "high",
|
|
10
|
-
"ResourceType": "
|
|
11
|
-
"Description": "
|
|
12
|
-
"Risk": "
|
|
13
|
-
"RelatedUrl": "
|
|
10
|
+
"ResourceType": "Pod",
|
|
11
|
+
"Description": "**Etcd** is configured to require **TLS client certificate authentication** when the etcd container includes `--client-cert-auth`, so client access is validated with trusted certificates.",
|
|
12
|
+
"Risk": "Without **mTLS client auth**, any reachable client can query or mutate etcd:\n- Confidentiality: exposure of Secrets and cluster metadata\n- Integrity: tampering with RBAC, pods, and configs\n- Availability: destructive writes can disrupt the control plane",
|
|
13
|
+
"RelatedUrl": "",
|
|
14
|
+
"AdditionalURLs": [
|
|
15
|
+
"https://etcd.io/docs/latest/op-guide/security/",
|
|
16
|
+
"https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/"
|
|
17
|
+
],
|
|
14
18
|
"Remediation": {
|
|
15
19
|
"Code": {
|
|
16
|
-
"CLI": "
|
|
17
|
-
"NativeIaC": "
|
|
18
|
-
"Other": "",
|
|
19
|
-
"Terraform": ""
|
|
20
|
+
"CLI": "",
|
|
21
|
+
"NativeIaC": "",
|
|
22
|
+
"Other": "1. SSH to the control plane node that runs etcd\n2. Edit the static pod manifest: /etc/kubernetes/manifests/etcd.yaml\n3. Under spec.containers[0].command (or args), add:\n ```\n - --client-cert-auth=true # Critical: enables client certificate authentication\n ```\n4. Save the file; kubelet will restart the etcd pod automatically\n5. Repeat on each control-plane node hosting an etcd pod",
|
|
23
|
+
"Terraform": "```hcl\n# Enable client certificate authentication on etcd\nresource \"kubernetes_pod\" \"<example_resource_name>\" {\n metadata {\n name = \"<example_resource_name>\"\n namespace = \"kube-system\"\n }\n spec {\n container {\n name = \"etcd\"\n image = \"gcr.io/etcd-development/etcd:v3.5.13\"\n command = [\n \"etcd\",\n \"--client-cert-auth=true\" # Critical: enables client cert auth to pass the check\n ]\n }\n }\n}\n```"
|
|
20
24
|
},
|
|
21
25
|
"Recommendation": {
|
|
22
|
-
"Text": "
|
|
23
|
-
"Url": "https://
|
|
26
|
+
"Text": "Enforce **mutual TLS** for etcd clients by requiring validated certificates (`--client-cert-auth=true`) issued by a trusted CA.\n\nRestrict network access to etcd to API servers, rotate keys regularly, and apply **least privilege** and **separation of duties** for certificate management.",
|
|
27
|
+
"Url": "https://hub.prowler.com/check/etcd_client_cert_auth"
|
|
24
28
|
}
|
|
25
29
|
},
|
|
26
30
|
"Categories": [
|
|
27
|
-
"
|
|
28
|
-
"
|
|
31
|
+
"cluster-security",
|
|
32
|
+
"identity-access",
|
|
33
|
+
"encryption"
|
|
29
34
|
],
|
|
30
35
|
"DependsOn": [],
|
|
31
36
|
"RelatedTo": [],
|